| #if !(UNITY_IOS || UNITY_IPHONE) | 
| using System; | 
| using System.Runtime.InteropServices; | 
| using UnityEngine; | 
| using System.Collections.Generic; | 
| using System.IO; | 
|   | 
|   | 
| #if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1) && !UNITY_EDITOR | 
|  using File = UnityEngine.Windows.File; | 
| #else | 
| using File = System.IO.File; | 
| #endif | 
|   | 
| #if NETFX_CORE | 
| #if UNITY_WSA_10_0 | 
|         using System.IO.IsolatedStorage; | 
|         using static System.IO.Directory; | 
|         using static System.IO.File; | 
|         using static System.IO.FileStream; | 
| #endif | 
| #endif | 
|   | 
|   | 
| public class lzma | 
| { | 
|   | 
|     //if you want to be able to call the functions: get7zinfo, get7zSize, decode2Buffer from a thread set this string before to the Application.persistentDataPath ! | 
|     public static string persitentDataPath = ""; | 
|   | 
| #if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR | 
|   | 
|     internal static int[] props = new int[7]; | 
|     internal static bool defaultsSet = false; | 
|   | 
|     //0 = level, /* 0 <= level <= 9, default = 5 */ | 
|     //1 = dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ | 
|     //2 = lc, /* 0 <= lc <= 8, default = 3  */ | 
|     //3 = lp, /* 0 <= lp <= 4, default = 0  */ | 
|     //4 = pb, /* 0 <= pb <= 4, default = 2  */ | 
|     //5 = fb,  /* 5 <= fb <= 273, default = 32 */ | 
|     //6 = numThreads /* 1 or 2, default = 2 */ | 
|   | 
|     //A function that sets the compression properties for the lzma compressor. Will affect the lzma alone file and the lzma buffer compression. | 
|     //A simple usage of this function is to call it only with the 1st parameter that sets the compression level: setProps(9); | 
|     // | 
|     //Multithread safe advice: call this function before starting any thread operations !!! | 
|     public static void setProps(int level = 5, int dictSize = 16777216, int lc = 3, int lp = 0, int pb = 2, int fb = 32, int numThreads = 2) | 
|     { | 
|         defaultsSet = true; | 
|         props[0] = level; | 
|         props[1] = dictSize; | 
|         props[2] = lc; | 
|         props[3] = lp; | 
|         props[4] = pb; | 
|         props[5] = fb; | 
|         props[6] = numThreads; | 
|     } | 
| #endif | 
|   | 
|   | 
| #if (UNITY_WEBGL) && !UNITY_EDITOR | 
|   | 
| #if (!UNITY_WEBGL) | 
|             [DllImport("__Internal")] | 
|             public static extern int lsetPermissions(string filePath, string _user, string _group, string _other); | 
|             [DllImport("__Internal")] | 
|             private static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
| #endif | 
|   | 
|         [DllImport("__Internal")] | 
|         private static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("__Internal")] | 
|         private static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("__Internal")] | 
|         internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props); | 
|         [DllImport("__Internal")] | 
|         internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("__Internal")] | 
|         internal static extern void _releaseBuffer(IntPtr buffer);     | 
|         [DllImport("__Internal")] | 
|         internal static extern IntPtr Lzma_Compress( IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props); | 
|         [DllImport("__Internal")] | 
|         internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize,  IntPtr outbuffer,bool useHeader); | 
| #endif | 
|   | 
| #if UNITY_5_4_OR_NEWER | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && (!UNITY_EDITOR || UNITY_EDITOR_LINUX) | 
|         private const string libname = "lzma"; | 
| #elif UNITY_EDITOR || UNITY_STANDALONE_WIN  | 
|     private const string libname = "liblzma"; | 
| #endif | 
| #else | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR | 
|         private const string libname = "lzma"; | 
| #endif | 
| #if UNITY_EDITOR || UNITY_STANDALONE_WIN  | 
|         private const string libname = "liblzma"; | 
| #endif | 
| #endif | 
|   | 
| #if UNITY_EDITOR || UNITY_STANDALONE_WIN ||  UNITY_ANDROID || UNITY_STANDALONE_LINUX | 
| #if ( UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN | 
|             //set permissions of a file in user, group, other. Each string should contain any or all chars of "rwx". | 
|             //returns 0 on success | 
|             [DllImport(libname, EntryPoint = "lsetPermissions")] | 
|             internal static extern int lsetPermissions(string filePath, string _user, string _group, string _other); | 
| #endif | 
|     [DllImport(libname, EntryPoint = "decompress7zip")] | 
|     internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
|     [DllImport(libname, EntryPoint = "decompress7zip2")] | 
|     internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
|     [DllImport(libname, EntryPoint = "_getSize")] | 
|     internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength); | 
|     [DllImport(libname, EntryPoint = "lzmaUtil")] | 
|     internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props); | 
|     [DllImport(libname, EntryPoint = "decode2Buf")] | 
|     internal static extern int decode2Buf(string filePath, string entry, IntPtr buffer, IntPtr FileBuffer, int FileBufferLength); | 
|     [DllImport(libname, EntryPoint = "_releaseBuffer")] | 
|     internal static extern void _releaseBuffer(IntPtr buffer); | 
|     [DllImport(libname, EntryPoint = "Lzma_Compress")] | 
|     internal static extern IntPtr Lzma_Compress(IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props); | 
|     [DllImport(libname, EntryPoint = "Lzma_Uncompress")] | 
|     internal static extern int Lzma_Uncompress(IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer, bool useHeader); | 
| #endif | 
|   | 
| #if (UNITY_WP_8_1 || UNITY_WSA) && !UNITY_EDITOR | 
| #if UNITY_WSA_10_0 | 
|             [DllImport("liblzma", EntryPoint = "decompress7zip")] | 
|             internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
| #endif | 
|         [DllImport("liblzma", EntryPoint = "decompress7zip2")] | 
|         internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("liblzma", EntryPoint = "_getSize")] | 
|         internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("liblzma", EntryPoint = "decode2Buf")] | 
|         internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength); | 
|         [DllImport("liblzma", EntryPoint = "Lzma_Uncompress")] | 
|         internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer,bool useHeader); | 
| #endif | 
|   | 
|   | 
|     // set permissions of a file in user, group, other. | 
|     // Each string should contain any or all chars of "rwx". | 
|     // returns 0 on success | 
|     public static int setFilePermissions(string filePath, string _user, string _group, string _other) | 
|     { | 
| #if (UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN | 
|             return lsetPermissions(filePath, _user, _group, _other); | 
| #else | 
|         return -1; | 
| #endif | 
|     } | 
|   | 
|     // An integer variable to store the total number of files in a 7z archive, excluding the folders. | 
|     public static int trueTotalFiles = 0; | 
|   | 
|     //ERROR CODES: | 
|     //  1 : OK | 
|     //    2 : Could not find requested file in archive | 
|     // -1 : Could not open input(7z) file | 
|     // -2 : Decoder doesn't support this archive | 
|     // -3 : Can not allocate memory | 
|     // -4 : CRC error of 7z file | 
|     // -5 : Unknown error | 
|     // -6 : Can not open output file (usually when the path to write to, is invalid) | 
|     // -7 : Can not write output file | 
|     // -8 : Can not close output file | 
|   | 
|     //The most common use of this library is to download a 7z file in your Application.persistentDataPath directory | 
|     //and decompress it in a folder that you want. | 
|   | 
|     //int lz=lzma.doDecompress7zip(Application.persistentDataPath+"/myCompresedFile.7z",Application.persistentDataPath+"/myUncompressedFiles/"); | 
|   | 
|     //WSA8.1 does not support large files. | 
|   | 
|     //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z) | 
|     //exctractionPath    : the path in where you want your files to be extracted | 
|     //progress          : a single item integer array to get the progress of the extracted files (use this function when calling from a separate thread, otherwise call the 2nd implementation) | 
|     //                  : (for ios this integer is not properly updated. So we use the lzma.getProgressCount() function to get the progress. See example.) | 
|     //largeFiles        : set this to true if you are extracting files larger then 30-40 Mb. It is slower though but prevents crashing your app when extracting large files! | 
|     //fullPaths            : set this to true if you want to keep the folder structure of the 7z file. | 
|     //entry                : set the name of a single file file you want to extract from your archive. If the file resides in a folder, the full path should be added. | 
|     //                       (for example  game/meshes/small/table.mesh ) | 
|     //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will decompress from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX) | 
|     //use this function from a separate thread to get the progress  of the extracted files in the referenced 'progress' integer. | 
|     // | 
|     public static int doDecompress7zip(string filePath, string exctractionPath, int[] progress, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null) | 
|     { | 
|   | 
|         int res = 0; | 
|         GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned); | 
|   | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN | 
|   | 
|         if(FileBuffer != null) { | 
|             GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned); | 
|              | 
|                  | 
|             if (largeFiles){ | 
|                 res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|             }else{ | 
|                 res =  decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|             } | 
|                 fbuf.Free(); ibuf.Free(); return res; | 
|         } else { | 
|             if (largeFiles){ | 
|                 res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0); | 
|                 ibuf.Free(); return res; | 
|             }else{ | 
|                 res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0); | 
|                 ibuf.Free(); return res; | 
|             } | 
|         } | 
|          | 
| #endif | 
|   | 
| #if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0 | 
|         if (largeFiles) | 
|         { | 
|             res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
|         } | 
|         else | 
|         { | 
|             res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
|         } | 
| #endif | 
|   | 
| #if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR | 
|             res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
| #endif | 
|     } | 
|   | 
|     //same as above only the progress integer is a local variable. | 
|     //use this when you don't want to get the progress of the extracted files and when not calling the function from a separate thread. | 
|     public static int doDecompress7zip(string filePath, string exctractionPath, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null) | 
|     { | 
|         //make a check if the last '/' exists at the end of the exctractionPath and add it if it is missing | 
|         if (@exctractionPath.Substring(@exctractionPath.Length - 1, 1) != "/") { @exctractionPath += "/"; } | 
|   | 
|         int[] progress = new int[1]; | 
|         GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned); | 
|         int res = 0; | 
|   | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN | 
|         if(FileBuffer != null) { | 
|             GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned); | 
|              | 
|              | 
|             if (largeFiles){ | 
|                 res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|             }else{ | 
|                 res = decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|             } | 
|                 fbuf.Free(); ibuf.Free(); return res; | 
|         } else { | 
|             if (largeFiles){ | 
|                 res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|                 ibuf.Free(); return res; | 
|             }else{ | 
|                 res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|                 ibuf.Free(); return res; | 
|             } | 
|         } | 
| #endif | 
|   | 
| #if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0 | 
|         if (largeFiles) | 
|         { | 
|             res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
|         } | 
|         else | 
|         { | 
|             res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
|         } | 
| #endif | 
|   | 
| #if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR | 
|             res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             ibuf.Free(); return res; | 
| #endif | 
|     } | 
|   | 
|   | 
| #if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR | 
|     //ERROR CODES (for both encode/decode LzmaUtil functions): | 
|     //   1 : OK | 
|     // -10 : Can not read input file | 
|     // -11 : Can not write output file | 
|     // -12 : Can not allocate memory | 
|     // -13 : Data error | 
|   | 
|     //This function encodes a single archive in lzma alone format. | 
|     //inPath    : the file to be encoded. (use full path + file name) | 
|     //outPath    : the .lzma file that will be produced. (use full path + file name) | 
|     // | 
|     //You can set the compression properties by calling the setProps function before. | 
|     //setProps(9) for example will set compression evel to highest level. | 
|     public static int LzmaUtilEncode(string inPath, string outPath) | 
|     { | 
|         if (!defaultsSet) setProps(); | 
|         GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned); | 
|         int res = lzmaUtil(true, @inPath, @outPath, prps.AddrOfPinnedObject()); | 
|         prps.Free(); | 
|         return res; | 
|     } | 
|   | 
|   | 
|     //This function decodes a single archive in lzma alone format. | 
|     //inPath    : the .lzma file that will be decoded. (use full path + file name) | 
|     //outPath    : the decoded file. (use full path + file name) | 
|     public static int LzmaUtilDecode(string inPath, string outPath) | 
|     { | 
|         return lzmaUtil(false, @inPath, @outPath, IntPtr.Zero); | 
|     } | 
|   | 
| #endif | 
|   | 
|     //Lists get filled with filenames (including path if the file is in a folder) and uncompressed file sizes | 
|     public static List<string> ninfo = new List<string>();//filenames | 
|     public static List<long> sinfo = new List<long>();//file sizes | 
|   | 
|     //this function fills the ArrayLists with the filenames and file sizes that are in the 7zip file | 
|     //returns            : the total size in bytes of the files in the 7z archive  | 
|     // | 
|     //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z) | 
|     //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used) | 
|     //                    : this is useful when your 7z archive resides in a read only location. | 
|     //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename. | 
|     //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX) | 
|     // | 
|     //trueTotalFiles is an integer variable to store the total number of files in a 7z archive, excluding the folders. | 
|     public static long get7zInfo(string filePath, string tempPath = null, byte[] FileBuffer = null) | 
|     { | 
|   | 
|         ninfo.Clear(); sinfo.Clear(); | 
|         trueTotalFiles = 0; | 
|         int res = -1; | 
|         string logPath = ""; | 
|   | 
| #if !NETFX_CORE | 
|         if (@tempPath == null) | 
|         { | 
|             if (persitentDataPath.Length > 0) logPath = @persitentDataPath + "/sevenZip.log"; else logPath = @Application.persistentDataPath + "/sevenZip.log"; | 
|         } | 
|         else { logPath = @tempPath; } | 
| #endif | 
|         //for WSA, logPath should always be: Application.persistentDataPath + "/sevenZip.log";  | 
| #if NETFX_CORE | 
| #if UNITY_WSA_10_0 | 
|                 if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @Application.persistentDataPath + "/sevenZip.log"; | 
| #endif | 
| #if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 | 
|                 if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @UnityEngine.Windows.Directory.localFolder + "/sevenZip.log"; | 
| #endif | 
| #endif | 
|   | 
|         if (File.Exists(logPath + ".txt")) File.Delete(logPath + ".txt"); | 
|   | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN | 
|           if(FileBuffer != null) { | 
|                 GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned); | 
|                 res = _getSize(null, logPath,  fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|                 fbuf.Free(); | 
|             }else { | 
|                 res = _getSize(@filePath, logPath,  IntPtr.Zero, 0); | 
|             } | 
| #else | 
|         res = _getSize(@filePath, logPath, IntPtr.Zero, 0); | 
| #endif | 
|   | 
|         if (res == -1) { /*Debug.Log("Input file not found.");*/ return -1; } | 
|   | 
|         if (!File.Exists(logPath + ".txt")) {/* Debug.Log("Info file not found.");*/ return -3; } | 
|   | 
| #if !NETFX_CORE | 
|         StreamReader r = new StreamReader(logPath + ".txt"); | 
| #endif | 
| #if NETFX_CORE | 
| #if UNITY_WSA_10_0 | 
|             IsolatedStorageFile ipath = IsolatedStorageFile.GetUserStoreForApplication(); | 
|             StreamReader r = new StreamReader(new IsolatedStorageFileStream("sevenZip.log.txt", FileMode.Open, ipath)); | 
| #endif | 
| #if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 | 
|             var data = UnityEngine.Windows.File.ReadAllBytes(logPath + ".txt"); | 
|             string ss = System.Text.Encoding.UTF8.GetString(data,0,data.Length); | 
|             StringReader r = new StringReader(ss); | 
| #endif | 
| #endif | 
|   | 
|         string line; | 
|         string[] rtt; | 
|         long t = 0, sum = 0; | 
|   | 
|         while ((line = r.ReadLine()) != null) | 
|         { | 
|             rtt = line.Split('|'); | 
|             ninfo.Add(rtt[0]); | 
|             long.TryParse(rtt[1], out t); | 
|             sum += t; | 
|             sinfo.Add(t); | 
|             if (t > 0) trueTotalFiles++; | 
|         } | 
|   | 
| #if !NETFX_CORE | 
|         r.Close(); | 
| #endif | 
|         r.Dispose(); | 
|         File.Delete(logPath + ".txt"); | 
|   | 
|         return sum; | 
|     } | 
|   | 
|   | 
|     //this function returns the uncompressed file size of a given file in the 7z archive if specified, | 
|     //otherwise it will return the total uncompressed size of all the files in the archive. | 
|     // | 
|     //If you don't fill the filePath parameter it will assume that the get7zInfo function has already been called. | 
|     // | 
|     // | 
|     //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z) | 
|     //                     : if you call the function with filePath as null, it will try to find file sizes from the last call. | 
|     //fileName             : the file name we want to get the file size (if it resides in a folder add the folder path also) | 
|     //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used) | 
|     //                    : this is useful when your 7z archive resides in a read only location. | 
|     //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename. | 
|     //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX) | 
|     public static long get7zSize(string filePath = null, string fileName = null, string tempPath = null, byte[] FileBuffer = null) | 
|     { | 
|   | 
|         if (filePath != null) | 
|         { | 
|             if (get7zInfo(@filePath, @tempPath, FileBuffer) < 0) { return -1; } | 
|         } | 
|   | 
|         if (ninfo == null) | 
|         { | 
|             if (ninfo.Count == 0) { return -1; } | 
|         } | 
|   | 
|         long sum = 0; | 
|   | 
|         if (fileName != null) | 
|         { | 
|             for (int i = 0; i < ninfo.Count; i++) | 
|             { | 
|                 if (ninfo[i].ToString() == fileName) | 
|                 { | 
|                     return (long)sinfo[i]; | 
|                 } | 
|             } | 
|         } | 
|         else | 
|         { | 
|             for (int i = 0; i < ninfo.Count; i++) | 
|             { | 
|                 sum += (long)sinfo[i]; | 
|             } | 
|             return sum; | 
|         } | 
|         return -1;//nothing was found | 
|     } | 
|   | 
|   | 
|   | 
|     //A function to decode a specific archive in a 7z archive to a byte buffer | 
|     // | 
|     //filePath        : the full path to the 7z archive  | 
|     //entry            : the file name to decode to a buffer. If the file resides in a folder, the full path should be used. | 
|     //tempPath        : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used) | 
|     //                : this is useful when your 7z archive resides in a read only location. | 
|     //                : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename. | 
|     //FileBuffer    : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX) | 
|     public static byte[] decode2Buffer(string filePath, string entry, string tempPath = null, byte[] FileBuffer = null) | 
|     { | 
|         int bufs = (int)get7zSize(@filePath, entry, @tempPath, FileBuffer); | 
|         if (bufs <= 0) return null;//entry error or it does not exist | 
|         byte[] nb = new byte[bufs]; | 
|         int res = 0; | 
|   | 
|         GCHandle dec2buf = GCHandle.Alloc(nb, GCHandleType.Pinned); | 
|   | 
| #if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN | 
|           if(FileBuffer != null) { | 
|                 GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned); | 
|                 res = decode2Buf(null, entry, dec2buf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length); | 
|                 fbuf.Free(); | 
|             }else { | 
|                 res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
|             } | 
| #else | 
|         res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0); | 
| #endif | 
|   | 
|         dec2buf.Free(); | 
|         if (res == 1) { return nb; } | 
|         else { nb = null; return null; } | 
|   | 
|     } | 
|   | 
| #if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR | 
|   | 
|     //This function encodes inBuffer to lzma alone format into the outBuffer provided. | 
|     //The buffer can be saved also into a file and can be opened by applications that opens the lzma alone format. | 
|     //This buffer can be uncompressed by the decompressBuffer function. | 
|     //Returns true if success | 
|     //if makeHeader==false then the lzma 13 bytes header will not be added to the buffer. | 
|     // | 
|     //You can set the compression properties by calling the setProps function before. | 
|     //setProps(9) for example will set compression level to the highest level. | 
|     // | 
|     public static bool compressBuffer(byte[] inBuffer, ref byte[] outBuffer, bool makeHeader = true) | 
|     { | 
|   | 
|         if (!defaultsSet) setProps(); | 
|         GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned); | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         IntPtr ptr; | 
|   | 
|         int res = 0; | 
|   | 
|         ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject()); | 
|   | 
|         cbuf.Free(); prps.Free(); | 
|   | 
|         if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; } | 
|   | 
|         Array.Resize(ref outBuffer, res); | 
|         Marshal.Copy(ptr, outBuffer, 0, res); | 
|   | 
|         _releaseBuffer(ptr); | 
|   | 
|         return true; | 
|     } | 
|   | 
|   | 
|     //same as the above function, only it compresses a part of the input buffer. | 
|     // | 
|     //inBufferPartialLength: the size of the input buffer that should be compressed | 
|     //inBufferPartialIndex:  the offset of the input buffer from where the compression will start | 
|     // | 
|     public static bool compressBufferPartial(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool makeHeader = true) | 
|     { | 
|         if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return false; | 
|   | 
|         if (!defaultsSet) setProps(); | 
|         GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned); | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|   | 
|         IntPtr ptr; | 
|         IntPtr ptrPartial; | 
|   | 
|         int res = 0; | 
|   | 
|         ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex); | 
|   | 
|         ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject()); | 
|   | 
|         cbuf.Free(); | 
|   | 
|         if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; } | 
|   | 
|         Array.Resize(ref outBuffer, res); | 
|         Marshal.Copy(ptr, outBuffer, 0, res); | 
|   | 
|         _releaseBuffer(ptr); | 
|   | 
|         return true; | 
|     } | 
|   | 
|   | 
|     //same as compressBufferPartial, only this function will compress the data into a fixed size buffer | 
|     //the compressed size is returned so you can manipulate it at will. | 
|     public static int compressBufferPartialFixed(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool safe = true, bool makeHeader = true) | 
|     { | 
|         if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return 0; | 
|   | 
|         if (!defaultsSet) setProps(); | 
|         GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned); | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|   | 
|         IntPtr ptr; | 
|         IntPtr ptrPartial; | 
|   | 
|         int res = 0; | 
|   | 
|         ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex); | 
|   | 
|         ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject()); | 
|   | 
|         cbuf.Free(); | 
|   | 
|         if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; } | 
|   | 
|         //if the compressed buffer is larger then the fixed size buffer we use: | 
|         //1. then write only the data that fit in it. | 
|         //2. or we return 0.  | 
|         //It depends on if we set the safe flag to true or not. | 
|         if (res > outBuffer.Length) | 
|         { | 
|             if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; } | 
|         } | 
|   | 
|         Marshal.Copy(ptr, outBuffer, 0, res); | 
|   | 
|         _releaseBuffer(ptr); | 
|   | 
|         return res; | 
|     } | 
|   | 
|   | 
|     //same as the compressBuffer function, only this function will put the result in a fixed size buffer to avoid memory allocations. | 
|     //the compressed size is returned so you can manipulate it at will. | 
|     public static int compressBufferFixed(byte[] inBuffer, ref byte[] outBuffer, bool safe = true, bool makeHeader = true) | 
|     { | 
|   | 
|         if (!defaultsSet) setProps(); | 
|         GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned); | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         IntPtr ptr; | 
|   | 
|         int res = 0; | 
|   | 
|         ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject()); | 
|   | 
|         cbuf.Free(); prps.Free(); | 
|         if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; } | 
|   | 
|         //if the compressed buffer is larger then the fixed size buffer we use: | 
|         //1. then write only the data that fit in it. | 
|         //2. or we return 0.  | 
|         //It depends on if we set the safe flag to true or not. | 
|         if (res > outBuffer.Length) | 
|         { | 
|             if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; } | 
|         } | 
|   | 
|         Marshal.Copy(ptr, outBuffer, 0, res); | 
|   | 
|         _releaseBuffer(ptr); | 
|   | 
|         return res; | 
|     } | 
|   | 
| #endif | 
|   | 
|   | 
|   | 
|   | 
|   | 
|     //This function will decompress a compressed asset bundle. | 
|     //It finds the magic number of the lzma format and extracts from there. | 
|     // | 
|     //inBuffer:        the buffer that stores a compressed asset bundle. | 
|     //outBuffer:    a referenced buffer where the asset bundle will be uncompressed. | 
|     //The error codes | 
|     /* | 
|         OK 0 | 
|          | 
|         ERROR_DATA 1 | 
|         ERROR_MEM 2 | 
|         ERROR_UNSUPPORTED 4 | 
|         ERROR_PARAM 5 | 
|         ERROR_INPUT_EOF 6 | 
|         ERROR_OUTPUT_EOF 7 | 
|         ERROR_FAIL 11 | 
|         ERROR_THREAD 12 | 
|     */ | 
|     public static int decompressAssetBundle(byte[] inBuffer, ref byte[] outbuffer) | 
|     { | 
|   | 
|         int offset = 0; | 
|   | 
|         for (int i = 0; i < inBuffer.Length; i++) | 
|         { | 
|             if (i > 1024) break; | 
|             if (inBuffer[i] == 0x5d) | 
|             { | 
|                 if (inBuffer[i + 1] == 0x00) | 
|                 { | 
|                     if (inBuffer[i + 2] == 0x00) | 
|                     { | 
|                         if (inBuffer[i + 3] == 0x08) | 
|                         { | 
|                             offset = i; break; | 
|                         } | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|   | 
|         if (offset == 0 || offset > 1024) return 4; | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset); | 
|         int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, offset + 5); | 
|         if (uncompressedSize < 0) { cbuf.Free(); return 4; } | 
|         Array.Resize(ref outbuffer, uncompressedSize); | 
|         GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned); | 
|   | 
|         int res = Lzma_Uncompress(ptrBundle, inBuffer.Length - offset, uncompressedSize, obuf.AddrOfPinnedObject(), true); | 
|   | 
|         cbuf.Free(); | 
|         obuf.Free(); | 
|   | 
|         //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; } | 
|   | 
|         return res; | 
|     } | 
|   | 
|   | 
|     /* | 
|     //this will decompress an lzma alone format file. | 
|     public static  int decompressLzmaAlone(string inFile,  string outFile){ | 
|   | 
|         if(File.Exists(inFile)) { | 
|             var inBuffer = File.ReadAllBytes(inFile); | 
|   | 
|             int offset = 0; | 
|          | 
|             for(int i=0; i<inBuffer.Length; i++) { | 
|                 if(i>16) break; | 
|                 if(inBuffer[i] == 0x5d) { | 
|                     if(inBuffer[i+1] == 0x00) { | 
|                         if(inBuffer[i+2] == 0x00) { | 
|                             if(inBuffer[i+3] == 0x00) { | 
|                                 offset = i;  break;  | 
|                             } | 
|                         } | 
|                     } | 
|                 } | 
|             } | 
|          | 
|             if(offset>16) {  inBuffer=null; return 4; } | 
|   | 
|             GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|             IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset); | 
|             int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer,offset+5); | 
|             if(uncompressedSize<0) { cbuf.Free(); return 4; } | 
|             byte[] outBuffer = new byte[uncompressedSize]; | 
|             GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned); | 
|          | 
|             int res = Lzma_Uncompress(ptrBundle, inBuffer.Length-offset, uncompressedSize, obuf.AddrOfPinnedObject(), true); | 
|   | 
|             cbuf.Free(); | 
|             obuf.Free(); | 
|   | 
|             File.WriteAllBytes(outFile, outBuffer); | 
|   | 
|             Array.Resize(ref outBuffer, 0); | 
|             Array.Resize(ref inBuffer, 0); | 
|   | 
|             outBuffer = null; | 
|             inBuffer = null; | 
|   | 
|             GC.Collect(); | 
|   | 
|             return res;     | 
|         } else { | 
|             return -1; | 
|         }     | 
|     } | 
|     */ | 
|   | 
|   | 
|     //This function decompresses an lzma compressed byte buffer. | 
|     //If the useHeader flag is false you have to provide the uncompressed size of the buffer via the customLength integer. | 
|     //if res==0 operation was successful | 
|     //The error codes | 
|     /* | 
|         OK 0 | 
|          | 
|         ERROR_DATA 1 | 
|         ERROR_MEM 2 | 
|         ERROR_UNSUPPORTED 4 | 
|         ERROR_PARAM 5 | 
|         ERROR_INPUT_EOF 6 | 
|         ERROR_OUTPUT_EOF 7 | 
|         ERROR_FAIL 11 | 
|         ERROR_THREAD 12 | 
|         */ | 
|     public static int decompressBuffer(byte[] inBuffer, ref byte[] outbuffer, bool useHeader = true, int customLength = 0) | 
|     { | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         int uncompressedSize = 0; | 
|   | 
|         //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header  | 
|         //provide the known uncompressed size through the customLength integer. | 
|         if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength; | 
|   | 
|         Array.Resize(ref outbuffer, uncompressedSize); | 
|   | 
|         GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned); | 
|   | 
|         int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader); | 
|   | 
|         cbuf.Free(); | 
|         obuf.Free(); | 
|   | 
|         //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; } | 
|   | 
|         return res; | 
|     } | 
|   | 
|     public static byte[] decompressBuffer(byte[] inBuffer, bool useHeader = true, int customLength = 0) | 
|     { | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         int uncompressedSize = 0; | 
|   | 
|         //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header  | 
|         //provide the known uncompressed size through the customLength integer. | 
|         if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength; | 
|   | 
|         byte[] outbuffer = new byte[uncompressedSize]; | 
|   | 
|         GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned); | 
|   | 
|         int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader); | 
|   | 
|         cbuf.Free(); | 
|         obuf.Free(); | 
|   | 
|         if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return null; } | 
|   | 
|         return outbuffer; | 
|     } | 
|   | 
|   | 
|     //same as above function. Only this one outputs to a buffer of fixed which size isn't resized to avoid memory allocations. | 
|     //The fixed buffer should have a size that will be able to hold the incoming decompressed data. | 
|     //returns the uncompressed size. | 
|     public static int decompressBufferFixed(byte[] inBuffer, ref byte[] outbuffer, bool safe = true, bool useHeader = true, int customLength = 0) | 
|     { | 
|   | 
|         int uncompressedSize = 0; | 
|   | 
|         //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header  | 
|         //provide the known uncompressed size through the customLength integer. | 
|         if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength; | 
|   | 
|         //Check if the uncompressed size is bigger then the size of the fixed buffer. Then: | 
|         //1. write only the data that fit in it. | 
|         //2. or return a negative number.  | 
|         //It depends on if we set the safe flag to true or not. | 
|         if (uncompressedSize > outbuffer.Length) | 
|         { | 
|             if (safe) return -101; else uncompressedSize = outbuffer.Length; | 
|         } | 
|   | 
|         GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned); | 
|         GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned); | 
|   | 
|         int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader); | 
|   | 
|         cbuf.Free(); | 
|         obuf.Free(); | 
|   | 
|         if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return -res; } | 
|   | 
|         return uncompressedSize; | 
|     } | 
|   | 
| } | 
| #endif |