private void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize) { fixed(char *strPtr = str) { char *charPtr = strPtr + start; int byteCount = BlobUtilities.GetUTF8ByteCount(charPtr, length); if (prependSize) { WriteCompressedInteger((uint)byteCount); } int startOffset = Advance(byteCount); _buffer.WriteUTF8(startOffset, charPtr, length, byteCount, allowUnpairedSurrogates); } }
private void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize) { if (!IsHead) { ThrowHeadRequired(); } fixed(char *strPtr = str) { char *currentPtr = strPtr + start; char *nextPtr; // the max size of compressed int is 4B: int byteLimit = FreeBytes - (prependSize ? sizeof(uint) : 0); int bytesToCurrent = BlobUtilities.GetUTF8ByteCount(currentPtr, length, byteLimit, out nextPtr); int charsToCurrent = (int)(nextPtr - currentPtr); int charsToNext = str.Length - charsToCurrent; int bytesToNext = BlobUtilities.GetUTF8ByteCount(nextPtr, charsToNext); if (prependSize) { WriteCompressedInteger((uint)(bytesToCurrent + bytesToNext)); } _buffer.WriteUTF8(Length, currentPtr, charsToCurrent, bytesToCurrent, allowUnpairedSurrogates); AddLength(bytesToCurrent); if (bytesToNext > 0) { Expand(bytesToNext); _buffer.WriteUTF8(0, nextPtr, charsToNext, bytesToNext, allowUnpairedSurrogates); AddLength(bytesToNext); } } }
/// <summary> /// Fills in stringIndexMap with data from stringIndex and write to stringWriter. /// Releases stringIndex as the stringTable is sealed after this point. /// </summary> private void SerializeStringHeap() { // Sort by suffix and remove stringIndex var sorted = new List <KeyValuePair <string, StringIdx> >(_strings); sorted.Sort(new SuffixSort()); _strings = null; _stringWriter = new BlobBuilder(1024); // Create VirtIdx to Idx map and add entry for empty string _stringIndexToResolvedOffsetMap = new int[sorted.Count + 1]; _stringIndexToResolvedOffsetMap[0] = 0; _stringWriter.WriteByte(0); // Find strings that can be folded string prev = string.Empty; foreach (KeyValuePair <string, StringIdx> entry in sorted) { int position = _stringHeapStartOffset + _stringWriter.Position; // It is important to use ordinal comparison otherwise we'll use the current culture! if (prev.EndsWith(entry.Key, StringComparison.Ordinal) && !BlobUtilities.IsLowSurrogateChar(entry.Key[0])) { // Map over the tail of prev string. Watch for null-terminator of prev string. _stringIndexToResolvedOffsetMap[entry.Value.MapIndex] = position - (BlobUtilities.GetUTF8ByteCount(entry.Key) + 1); } else { _stringIndexToResolvedOffsetMap[entry.Value.MapIndex] = position; _stringWriter.WriteUTF8(entry.Key, allowUnpairedSurrogates: false); _stringWriter.WriteByte(0); } prev = entry.Key; } }