public MCSResource(int version) { magicHeader = MCSConstants.MR_MAGIC_NUMBER; switch (version) { case 1: header = new M3DResourceHeaderV1(); break; case 2: header = new M3DResourceHeaderV2(); break; default: break; } }
//Adds or replaces an entry in the resource file public bool Upsert(string key, byte[] bytes, bool writeToDisk = true) { int count = header.Keys.Length; int oldCount = count; //how much should we resize our body buffer? int deltaBytes = bytes.Length; int upsertIndex = -1; //are we replacing or adding? bool replace = false; for (int i = 0; i < count; i++) { //since we're replacing it, recalculate the correct body size if (header.Keys[i].Equals(key)) { replace = true; deltaBytes = bytes.Length - header.Lengths[i]; upsertIndex = i; break; } } if (!replace) { upsertIndex = count; count++; } M3DResourceHeaderV2 newHeader = new M3DResourceHeaderV2(); newHeader.FilePath = header.FilePath; newHeader.Keys = new string[count]; newHeader.Positions = new int[count]; newHeader.Lengths = new int[count]; byte[] newBody = new byte[body.Length + deltaBytes]; int bodyIndex = 0; //build a new header for (int i = 0; i < count; i++) { string currentKey = (i < oldCount ? header.Keys[i] : key); newHeader.Keys[i] = currentKey; newHeader.Positions[i] = bodyIndex; if (i != upsertIndex) { //copy the old one into the body Array.Copy(body, header.Positions[i], newBody, bodyIndex, header.Lengths[i]); newHeader.Lengths[i] = header.Lengths[i]; } else { //copy the new one into the body Array.Copy(bytes, 0, newBody, bodyIndex, bytes.Length); newHeader.Lengths[i] = bytes.Length; } bodyIndex += newHeader.Lengths[i]; } header = newHeader; body = newBody; if (writeToDisk && !String.IsNullOrEmpty(header.FilePath)) { Serialize(header.FilePath); } return(true); }
//Add file(s) to an existing resource (or new one) public bool Add(string key, List <string> paths) { int oldCount = header.Keys.Length; //we're adding a file... int count = oldCount + paths.Count; M3DResourceHeaderV1 newHeader = new M3DResourceHeaderV1(); newHeader.FilePath = header.FilePath; newHeader.Keys = new string[count]; newHeader.Positions = new int[count]; newHeader.Lengths = new int[count]; //copy the old one into the new if applicable if (oldCount > 0) { Array.Copy(header.Keys, newHeader.Keys, oldCount); Array.Copy(header.Positions, newHeader.Positions, oldCount); Array.Copy(header.Lengths, newHeader.Lengths, oldCount); } int index = 0; if (oldCount > 0) { //advance the index to the end of the file index = body.Length; } //re-index the header positions and lengths int totalLen = 0; for (int i = 0; i < count; i++) { int slot = i + oldCount; string path = paths[i]; newHeader.Keys[slot] = path; newHeader.Positions[slot] = totalLen; newHeader.Lengths[slot] = (int)new FileInfo(paths[i]).Length; totalLen += newHeader.Lengths[slot]; } //create a new body and copy the old one if we need to byte[] newBody = new byte[totalLen]; if (oldCount > 0) { Array.Copy(body, newBody, body.Length); } for (int i = 0; i < count; i++) { int slot = i + oldCount; string path = paths[i]; byte[] buffer = File.ReadAllBytes(paths[i]); int fileLen = buffer.Length; Array.Copy(buffer, 0, newBody, index, fileLen); index += fileLen; } header = newHeader; body = newBody; //if we have a current file path to save, save it if (header.FilePath != null) { Serialize(header.FilePath); } return(true); //success }
protected void DeserializeHeader(byte[] buffer) { int pos = 0; //magic bytes int magicHeaderIn = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; if (magicHeader != magicHeaderIn) { throw new Exception("Magic header not found, invalid M3DResource file"); } //version int version = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; switch (version) { case 1: //Version 1 header = new M3DResourceHeaderV1(); break; case 2: header = new M3DResourceHeaderV2(); break; default: UnityEngine.Debug.LogError("Version: " + version + " is not supported, please verify you have the most up-to-date version of MCS"); throw new Exception("Unknown M3DResource file version"); break; } byte[] tmpBuf; //header size int headerBufferSize = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; positionBody = headerBufferSize; //body size int bodyBufferSize = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; //Utility Flag if (version > 1 && version <= MCSConstants.LATEST_MAJOR_VERSION) { header.UtilityFlag = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; } //Filepath int filePathLen = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; byte[] filePathBytes = new byte[filePathLen]; System.Buffer.BlockCopy(buffer, pos, filePathBytes, 0, filePathLen); pos += filePathLen; header.FilePath = System.Text.Encoding.UTF8.GetString(filePathBytes); //UnityEngine.Debug.Log("filePath: " + header.filePath); //Total Entries int totalEntries = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; //UnityEngine.Debug.Log("total entries: " + totalEntries); header.Keys = new string[totalEntries]; header.Positions = new int[totalEntries]; header.Lengths = new int[totalEntries]; int totalKeysAsBytesLen = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; //UnityEngine.Debug.Log("totalKeysAsBytesLen : " + totalKeysAsBytesLen); //read each variable length key name until we're done for (int i = 0; i < totalEntries; i++) { int keyLen = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; tmpBuf = new byte[keyLen]; //UnityEngine.Debug.Log("KeyLen: " + i + " | " + keyLen + " | " + buffer.Length); System.Buffer.BlockCopy(buffer, pos, tmpBuf, 0, keyLen); pos += keyLen; header.Keys[i] = System.Text.Encoding.UTF8.GetString(tmpBuf); } //read the positions for (int i = 0; i < totalEntries; i++) { header.Positions[i] = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; } //read the lengths for (int i = 0; i < totalEntries; i++) { header.Lengths[i] = System.BitConverter.ToInt32(buffer, pos); pos += MCSConstants.SIZE_OF_INT; } /* * BinaryFormatter serializer = new BinaryFormatter(); * MemoryStream stream = new MemoryStream(buffer); * header = (M3DResourceHeader)serializer.Deserialize(stream); */ }