Exemple #1
0
        /// <exception cref="ArgumentOutOfRangeException">Range specified by <paramref name="start"/> and <paramref name="byteCount"/> falls outside of the bounds of the buffer content.</exception>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public byte[] ToArray(int start, int byteCount)
        {
            BlobUtilities.ValidateRange(Count, start, byteCount);

            var result = new byte[byteCount];

            int chunkStartPosition = 0;
            int resultOffset       = 0;

            foreach (var chunk in GetChunks())
            {
                int chunkEndPosition = chunkStartPosition + chunk.Length;

                if (chunkEndPosition > start)
                {
                    int bytesToCopy = Math.Min(chunk.Length, result.Length - resultOffset);
                    if (bytesToCopy == 0)
                    {
                        break;
                    }

                    Array.Copy(chunk._buffer, Math.Max(start - chunkStartPosition, 0), result, resultOffset, bytesToCopy);

                    resultOffset += bytesToCopy;
                }

                chunkStartPosition = chunkEndPosition;
            }

            Debug.Assert(resultOffset == result.Length);
            return(result);
        }
Exemple #2
0
        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Range specified by <paramref name="start"/> and <paramref name="byteCount"/> falls outside of the bounds of the <paramref name="buffer"/>.</exception>
        /// <exception cref="InvalidOperationException">Builder is not writable, it has been linked with another one.</exception>
        public unsafe void WriteBytes(byte[] buffer, int start, int byteCount)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            BlobUtilities.ValidateRange(buffer.Length, start, byteCount);

            if (!IsHead)
            {
                ThrowHeadRequired();
            }

            // an empty array has no element pointer:
            if (buffer.Length == 0)
            {
                return;
            }

            fixed(byte *ptr = buffer)
            {
                WriteBytesUnchecked(ptr + start, byteCount);
            }
        }
Exemple #3
0
        /// <exception cref="ArgumentOutOfRangeException">Range specified by <paramref name="start"/> and <paramref name="byteCount"/> falls outside of the bounds of the buffer content.</exception>
        public byte[] ToArray(int start, int byteCount)
        {
            BlobUtilities.ValidateRange(Length, start, byteCount);

            var result = new byte[byteCount];

            Array.Copy(_buffer, _start + start, result, 0, byteCount);
            return(result);
        }
Exemple #4
0
        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);
            }
        }
        /// <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;
            }
        }
Exemple #6
0
        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);
                }
            }
        }
Exemple #7
0
        /// <exception cref="ArgumentOutOfRangeException">Range specified by <paramref name="start"/> and <paramref name="byteCount"/> falls outside of the bounds of the buffer content.</exception>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public byte[] ToArray(int start, int byteCount)
        {
            BlobUtilities.ValidateRange(Count, start, byteCount);

            var result = new byte[byteCount];

            int chunkStart  = 0;
            int bufferStart = start;
            int bufferEnd   = start + byteCount;

            foreach (var chunk in GetChunks())
            {
                int chunkEnd = chunkStart + chunk.Length;
                Debug.Assert(bufferStart >= chunkStart);

                if (chunkEnd > bufferStart)
                {
                    int bytesToCopy = Math.Min(bufferEnd, chunkEnd) - bufferStart;
                    Debug.Assert(bytesToCopy >= 0);

                    Array.Copy(chunk._buffer, bufferStart - chunkStart, result, bufferStart - start, bytesToCopy);
                    bufferStart += bytesToCopy;

                    if (bufferStart == bufferEnd)
                    {
                        break;
                    }
                }

                chunkStart = chunkEnd;
            }

            Debug.Assert(bufferStart == bufferEnd);

            return(result);
        }