/** * <summary>Remove a tag from the list.</summary> * * <param name="key">The key to remove.</param> * <returns>If the deletion was successfully done.</returns> */ public bool Delete(string key) { if (!file.Exists) { return(false); } using (MemoryStream decompressedData = new MemoryStream()) { using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream stream = GetDecompressStream(fs)) stream.CopyTo(decompressedData); KeyScout counter = InternalUtils.ScoutObjectData(decompressedData.ToArray(), key, new KeyScout()); if (counter == null) { return(false); } byte[] recompressed = InternalUtils.deleteSubObjectData(decompressedData.ToArray(), counter); using (FileStream newFile = new FileStream(file.FullName, FileMode.Open, FileAccess.Write, FileShare.Write)) { newFile.SetLength(0); using (Stream compressStream = GetCompressStream(newFile)) compressStream.Write(recompressed, 0, recompressed.Length); } } return(true); }
/** * <summary>Replace a key with another tag.</summary> * <param name="key">The key</param> * <param name="replacement">The data to replace the key</param> * <returns>If the replacement was successful.</returns> */ public bool ReplaceData(string key, ITag replacement) { if (!file.Exists) { return(false); } using (MemoryStream decompressed = new MemoryStream()) { using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream compStream = GetDecompressStream(fs)) compStream.CopyTo(decompressed); KeyScout counter = InternalUtils.ScoutObjectData(decompressed.ToArray(), key, new KeyScout()); if (counter.GetEnd() == null) { return(false); } MemoryStream memStream = new MemoryStream(); BigBinaryWriter bbw = new BigBinaryWriter(memStream); replacement.WriteData(bbw); bbw.Close(); byte[] replaceReturn = InternalUtils.ReplaceSubObjectData(decompressed.ToArray(), counter, memStream.ToArray()); using (FileStream newFile = new FileStream(file.FullName, FileMode.Create, FileAccess.Write, FileShare.Write)) { newFile.SetLength(0); using (Stream stream = GetCompressStream(newFile)) stream.Write(replaceReturn, 0, replaceReturn.Length); } } return(true); }
/** * <summary>Insert in a new tag.</summary> * <param name="data">The input array of bytes.</param> * <param name="counter">The KeyScout object containing information of the tag to set.</param> * <param name="dataToReplace">The bytes of the replacement data.</param> * * <returns>The output bytes.</returns> */ public static byte[] SetSubObjectData(byte[] data, KeyScout counter, byte[] dataToReplace) { KeyScoutChild child = counter.GetChildren()[counter.GetChildren().Count - 1]; byte[] array1 = new byte[data.Length + dataToReplace.Length]; Array.Copy(data, 0, array1, 0, child.GetStartingIndex() + 4 + child.GetSize()); Array.Copy(dataToReplace, 0, array1, child.GetStartingIndex() + 4 + child.GetSize(), dataToReplace.Length); Array.Copy(data, (child.GetStartingIndex() + 4 + child.GetSize()), array1, (child.GetStartingIndex() + 4 + child.GetSize()) + dataToReplace.Length, data.Length - (child.GetStartingIndex() + 4 + child.GetSize())); counter.AddAmount(dataToReplace.Length); foreach (KeyScoutChild childs in counter.GetChildren()) { int index = childs.GetStartingIndex(); int size = childs.GetSize(); array1[index] = (byte)(size >> 24); array1[index + 1] = (byte)(size >> 16); array1[index + 2] = (byte)(size >> 8); array1[index + 3] = (byte)(size); } return(array1); }
/** * <summary> * Replace a tag with another tag. * </summary> * <param name="data">The input array of bytes</param> * <param name="counter">The KeyScout object conatining the information of the tag to replace.</param> * <param name="dataToReplace">The bytes of the replacement data.</param> * <returns>The byte array after the replacement.</returns> */ public static byte[] ReplaceSubObjectData(byte[] data, KeyScout counter, byte[] dataToReplace) { counter.RemoveAmount(counter.GetEnd().GetSize() + 5); counter.AddAmount(dataToReplace.Length); KeyScoutChild end = counter.GetEnd(); byte[] array1 = new byte[data.Length - (5 + end.GetSize()) + dataToReplace.Length]; //Copy all of the information before the removed data. Array.Copy(data, 0, array1, 0, (end.GetStartingIndex() - 1)); Array.Copy(dataToReplace, 0, array1, end.GetStartingIndex() - 1, dataToReplace.Length); // copy all of the information after the removed data. Array.Copy(data, end.GetStartingIndex() + 4 + end.GetSize(), array1, end.GetStartingIndex() - 1 + dataToReplace.Length, data.Length - (end.GetStartingIndex() + 4 + end.GetSize())); foreach (KeyScoutChild child in counter.GetChildren()) { int index = child.GetStartingIndex(); int size = child.GetSize(); array1[index] = (byte)(size >> 24); array1[index + 1] = (byte)(size >> 16); array1[index + 2] = (byte)(size >> 8); array1[index + 3] = (byte)(size); } return(array1); }
/** * <summary> * This object goes through the data and scouts out the information from the given key. * This method is recursive, which is why the parameter offset exists. * </summary> * * <param name="data">The input array of bytes</param> * <param name="key">The key</param> * <param name="counter">The Scout object</param> * <param name="startIndex">The starting index for the count.</param> * <returns>The key scout.</returns> */ public static KeyScout ScoutObjectData(byte[] data, string key, KeyScout counter, int startIndex) { MemoryStream stream = new MemoryStream(data); BigBinaryReader binReader = new BigBinaryReader(stream); TagBuilder currentBuilder = new TagBuilder(); binReader.BaseStream.Seek(0, SeekOrigin.Begin); string name = key.Split('.')[0]; string otherKey = getKey(key.Split('.')); while (binReader.BaseStream.Position != binReader.BaseStream.Length) { KeyScoutChild child = new KeyScoutChild(); currentBuilder.setDataType(binReader.ReadByte()); child.SetStartingIndex((int)binReader.BaseStream.Position + startIndex); currentBuilder.setDataSize(binReader.ReadInt32()); currentBuilder.setStartingIndex(binReader.BaseStream.Position); currentBuilder.setNameSize(binReader.ReadInt16()); if (currentBuilder.getNameSize() != Encoding.UTF8.GetByteCount(name)) { binReader.BaseStream.Seek((currentBuilder.getStartingIndex() - stream.Position) + currentBuilder.getDataSize(), SeekOrigin.Current); currentBuilder = new TagBuilder(); continue; } byte[] nameBytes = binReader.ReadBytes(currentBuilder.getNameSize()); string tagName = Encoding.UTF8.GetString(nameBytes); currentBuilder.setName(tagName); if (tagName != name) { binReader.BaseStream.Seek((currentBuilder.getStartingIndex() - stream.Position) + currentBuilder.getDataSize(), SeekOrigin.Current); currentBuilder = new TagBuilder(); continue; } int binPos = (int)binReader.BaseStream.Position; byte[] value = binReader.ReadBytes((int)(currentBuilder.getStartingIndex() - stream.Position) + (int)currentBuilder.getDataSize()); currentBuilder.setValueBytes(value); binReader.Close(); if (otherKey != null) { validateNotCompressed(currentBuilder); child.SetSize(currentBuilder.getDataSize()); child.SetName(currentBuilder.getName()); counter.AddChild(child); return(ScoutObjectData(currentBuilder.getValueBytes(), otherKey, counter, binPos + startIndex)); } child.SetSize(currentBuilder.getDataSize()); child.SetName(currentBuilder.getName()); counter.SetEnd(child); return(counter); } return(null); }
/** * <summary>Remove a tag from the list.</summary> * * <param name="key">The key to remove.</param> * <returns>If the deletion was successfully done.</returns> */ public bool Delete(string key) { KeyScout counter = InternalUtils.ScoutObjectData(memStream.ToArray(), key, new KeyScout()); if (counter == null) { return(false); } byte[] recompressed = InternalUtils.deleteSubObjectData(memStream.ToArray(), counter); memStream.SetLength(0); memStream.Position = 0; memStream.Write(recompressed, 0, recompressed.Length); return(true); }
/** * <summary>Replace a key with another tag.</summary> * <param name="key">The key</param> * <param name="replacement">The data to replace the key</param> * <returns>If the replacement was successful.</returns> */ public bool ReplaceData(string key, ITag replacement) { KeyScout counter = InternalUtils.ScoutObjectData(memStream.ToArray(), key, new KeyScout()); if (counter.GetEnd() == null) { return(false); } MemoryStream tempStream = new MemoryStream(); BigBinaryWriter bbw = new BigBinaryWriter(tempStream); replacement.WriteData(bbw); bbw.Close(); byte[] replaceReturn = InternalUtils.ReplaceSubObjectData(memStream.ToArray(), counter, tempStream.ToArray()); memStream.SetLength(0); memStream.Position = 0; memStream.Write(replaceReturn, 0, replaceReturn.Length); return(true); }
/** * <summary>Delete a tag from an array of bytes using the KeyScout.</summary> * * <param name="data">The byte array to remove data from.</param> * <param name="counter">The KeyScout that contains information about the tag to remove.</param> * <returns>The byte array after the deletion.</returns> */ public static byte[] deleteSubObjectData(byte[] data, KeyScout counter) { counter.RemoveAmount(counter.GetEnd().GetSize() + 5); KeyScoutChild end = counter.GetEnd(); byte[] array1 = new byte[data.Length - (5 + end.GetSize())]; Array.Copy(data, 0, array1, 0, (end.GetStartingIndex() - 1)); Array.Copy(data, end.GetStartingIndex() + 4 + end.GetSize(), array1, end.GetStartingIndex() - 1, data.Length - (end.GetStartingIndex() + 4 + end.GetSize())); foreach (KeyScoutChild child in counter.GetChildren()) { int index = child.GetStartingIndex(); int size = child.GetSize(); array1[index] = (byte)(size >> 24); array1[index + 1] = (byte)(size >> 16); array1[index + 2] = (byte)(size >> 8); array1[index + 3] = (byte)size; } return(array1); }
/** * <summary> * This method can append, delete, and set tags. * <para>A note on keys when appending: <code>ObjectOne.ObjectTwo.tagName</code> When appending data <c>tagName</c> will not be the actual tag name. * The tag name written to the file is the name of the specified tag in the value parameter. Any parent objects that do not exist will be created. For example: * <code>ObjectOne.ObjectTwo.NewObject.tagName</code> If in the example above <c>NewObject</c> does not exist, than the object will be created with the value tag inside * of it. Please see the wiki for a more detailed explanation on this.</para> * <para>When value is null, the specified key is deleted. <c>The key MUST exist or an {@link ODSException} will be thrown.</c></para> * </summary> * * <param name="key"> * The key of the tag to append, delete, or set. * <para>When appending the key does not need to exist. ObjectTags that don't exist will be created automatically.</para> * <para>When the key is set to "" (An empty string) than it is assumed you want to append to the parent file.</para> * <para>Valid Tags:</para> * <code> * <para>ObjectOne.tagToDelete</para> * <para>ObjectOne.NewObject.tagToAppend</para> * <para>ObjectOne.tagToSet</para> * </code> * </param> * * <param name="value">The tag to append or replace the key with. <para>If this parameter is null than the key will be deleted.</para></param> * */ public void Set(string key, ITag value) { if (value == null) { bool output = Delete(key); if (!output) { throw new ODSException("The key " + key + " does not exist!"); } return; } if (key == "") { Save(new List <ITag>() { value }); return; } byte[] uncompressed = memStream.ToArray(); KeyScout counter = InternalUtils.ScoutObjectData(uncompressed, key, new KeyScout()); if (counter.GetEnd() == null) { if (counter.GetChildren().Count < 1) { Append(value); return; } string existingKey = ""; foreach (KeyScoutChild child in counter.GetChildren()) { if (existingKey.Length != 0) { existingKey += "."; } existingKey += child.GetName(); } string newKey = key.Replace(existingKey + ".", ""); ITag currentData; if (newKey.Split('.').Length > 1) { ObjectTag output = null; ObjectTag curTag = null; List <string> keys = new List <string>(newKey.Split('.')); int i = 0; foreach (string s in keys) { if (i == 0) { output = new ObjectTag(s); curTag = output; } else if (i == keys.Count - 1) { curTag.AddTag(value); } else { ObjectTag tag = new ObjectTag(s); curTag.AddTag(tag); curTag = tag; } i++; } currentData = output; } else { currentData = value; } // Actually replace the data and write it to the file. MemoryStream tempStream = new MemoryStream(); BigBinaryWriter bbw = new BigBinaryWriter(tempStream); currentData.WriteData(bbw); bbw.Close(); byte[] outputArray = InternalUtils.SetSubObjectData(uncompressed, counter, tempStream.ToArray()); memStream.SetLength(0); memStream.Position = 0; memStream.Write(outputArray, 0, outputArray.Length); } else { MemoryStream tempStream = new MemoryStream(); BigBinaryWriter bbw = new BigBinaryWriter(tempStream); value.WriteData(bbw); bbw.Close(); byte[] replaceReturn = InternalUtils.ReplaceSubObjectData(uncompressed, counter, tempStream.ToArray()); memStream.SetLength(0); memStream.Position = 0; memStream.Write(replaceReturn, 0, replaceReturn.Length); } }
/** * <summary> * This object goes through the data and scouts out the information from the given key. * This method is recursive, which is why the parameter offset exists. * </summary> * * <param name="data">The input array of bytes</param> * <param name="key">The key</param> * <param name="counter">The Scout object</param> * <returns>The key scout.</returns> */ public static KeyScout ScoutObjectData(byte[] data, string key, KeyScout counter) { return(ScoutObjectData(data, key, counter, 0)); }