public void ReuseOfDeserializedInternerNotAllowed() { var interner = new LookasideStringInterner(StringComparer.OrdinalIgnoreCase, 1); int strIndex = interner.Intern("abc123def456"); MemoryStream stream = new MemoryStream(); INodePacketTranslator writetranslator = NodePacketTranslator.GetWriteTranslator(stream); interner.Translate(writetranslator); INodePacketTranslator readtranslator = NodePacketTranslator.GetReadTranslator(stream, null); var newInterner = new LookasideStringInterner(readtranslator); bool gotException = false; try { newInterner.Intern("foo"); } catch (Exception) { gotException = true; } Assert.IsTrue(gotException); }
public void Serialization() { var interner = new LookasideStringInterner(StringComparer.OrdinalIgnoreCase, 1); int nullIndex = interner.Intern(null); int emptyIndex = interner.Intern(String.Empty); int strIndex = interner.Intern("abc123def456"); MemoryStream stream = new MemoryStream(); INodePacketTranslator writetranslator = NodePacketTranslator.GetWriteTranslator(stream); interner.Translate(writetranslator); INodePacketTranslator readtranslator = NodePacketTranslator.GetReadTranslator(stream, null); var newInterner = new LookasideStringInterner(readtranslator); Assert.AreEqual(newInterner.GetString(nullIndex), null); Assert.AreEqual(newInterner.GetString(emptyIndex), String.Empty); Assert.AreEqual(newInterner.GetString(strIndex), "abc123def456"); }
/// <summary> /// Compresses the items. /// </summary> private void CompressItems() { ErrorUtilities.VerifyThrow(_compressedItems == null, "Items already compressed."); // We will just calculate a very rough starting buffer size for the memory stream based on the number of items and a // rough guess for an average number of bytes needed to store them compressed. This doesn't have to be accurate, just // big enough to avoid unnecessary buffer reallocations in most cases. int defaultCompressedBufferCapacity = _uncompressedItems.Length * 64; using (MemoryStream serializedStream = new MemoryStream(defaultCompressedBufferCapacity)) { using (DeflateStream deflateStream = new DeflateStream(serializedStream, CompressionMode.Compress)) { INodePacketTranslator serializedBufferTranslator = NodePacketTranslator.GetWriteTranslator(deflateStream); // Again, a rough calculation of buffer size, this time for an uncompressed buffer. We assume compression // will give us 2:1, as it's all text. int defaultUncompressedBufferCapacity = defaultCompressedBufferCapacity * 2; using (MemoryStream itemsStream = new MemoryStream(defaultUncompressedBufferCapacity)) { INodePacketTranslator itemTranslator = NodePacketTranslator.GetWriteTranslator(itemsStream); // When creating the interner, we use the number of items as the initial size of the collections since the // number of strings will be of the order of the number of items in the collection. This assumes basically // one unique string per item (frequently a path related to the item) with most of the rest of the metadata // being the same (and thus interning.) This is a hueristic meant to get us in the ballpark to avoid // too many reallocations when growing the collections. LookasideStringInterner interner = new LookasideStringInterner(StringComparer.Ordinal, _uncompressedItems.Length); for (int i = 0; i < _uncompressedItems.Length; i++) { _uncompressedItems[i].TranslateWithInterning(itemTranslator, interner); } interner.Translate(serializedBufferTranslator); byte[] buffer = itemsStream.ToArray(); serializedBufferTranslator.Translate(ref buffer); } } _compressedItems = serializedStream.ToArray(); } _uncompressedItems = null; }