/// <summary> /// Add data to the image archive /// </summary> /// <param name="Key"></param> /// <param name="Bytes"></param> public void Add(string Key, byte[] Bytes) { lock (this) { if (this.archiveIndexKey.ContainsKey(Key)) { throw new Exception("Key already exists: " + Key); } MD5Checksum md5 = MD5Checksum.Generate(Bytes); ImageArchiveEntry entry; if (this.archiveIndexMD5.ContainsKey(md5)) { ImageArchiveEntry oldiae = this.archiveIndexMD5[md5]; entry = new ImageArchiveEntry { Key = Key, BytePositionStart = oldiae.BytePositionStart, Size = oldiae.Size, MD5 = md5 }; } else { entry = new ImageArchiveEntry { Key = Key, BytePositionStart = this.archiveFile.Position, Size = Bytes.Length, MD5 = md5 }; //Add the entry to the MD5 index. this.archiveIndexMD5.Add(md5, entry); //Add to memorystream this.archiveFile.Write(Bytes, 0, Bytes.Length); } //Add to key index this.archiveIndexKey.Add(Key, entry); } }
/// <summary> /// Remove the specific key from index. /// </summary> /// <param name="Key"></param> public void Remove(string Key) { lock (this) { if (!this.archiveIndexKey.ContainsKey(Key)) { throw new Exception("Key not found: " + Key); } ImageArchiveEntry removedEntry = this.archiveIndexKey[Key]; this.archiveIndexKey.Remove(Key); //Browse through each ImageArchiveEntry we have, to find out if we can remove this image from the stream. bool removeStream = true; foreach (KeyValuePair <string, ImageArchiveEntry> kvp in this.archiveIndexKey) { if (kvp.Value.MD5 == removedEntry.MD5) { removeStream = false; //Replace representation in MD5 index this.archiveIndexMD5[removedEntry.MD5] = kvp.Value; break; } } //If we can remove the stream if (removeStream) { //Adjust position mapping of entries after removed entry, but only if the removed entry isn't the last entry. if ((removedEntry.BytePositionStart + removedEntry.Size) == this.archiveFile.Length) { foreach (KeyValuePair <string, ImageArchiveEntry> kvp in this.archiveIndexKey) { if (kvp.Value.BytePositionStart > removedEntry.BytePositionStart) { kvp.Value.BytePositionStart -= removedEntry.Size; } } } //Remove this part of the stream. MemoryStream ms = new MemoryStream(); byte[] buffer; //Part before removed entry. if (removedEntry.BytePositionStart > 0) { buffer = new byte[removedEntry.BytePositionStart]; this.archiveFile.Read(buffer, 0, (int)removedEntry.BytePositionStart); ms.Write(buffer, 0, buffer.Length); } //Part after removed entry. if ((removedEntry.BytePositionStart + removedEntry.Size) <= this.archiveFile.Length) { int startpos = (int)removedEntry.BytePositionStart + removedEntry.Size; int length = (int)this.archiveFile.Length - startpos; buffer = new byte[length]; this.archiveFile.Read(buffer, startpos, length); ms.Write(buffer, 0, buffer.Length); } } } }