public static ByteStringContext <ByteStringMemoryCache> .InternalScope GetSliceFromId <TTransaction>( TransactionOperationContext <TTransaction> context, string id, out Slice idSlice, byte?separator = null) where TTransaction : RavenTransaction { if (_jsonParserState == null) { _jsonParserState = new JsonParserState(); } _jsonParserState.Reset(); var strLength = id.Length; var maxStrSize = Encoding.GetMaxByteCount(strLength); var escapePositionsSize = JsonParserState.FindEscapePositionsMaxSize(id, out _); if (strLength > MaxIdSize) { ThrowDocumentIdTooBig(id); } var internalScope = context.Allocator.Allocate( maxStrSize // this buffer is allocated to also serve the GetSliceFromUnicodeKey + sizeof(char) * id.Length + escapePositionsSize + (separator != null ? 1 : 0), out var buffer); idSlice = new Slice(buffer); for (var i = 0; i < id.Length; i++) { var ch = id[i]; if (ch > 127) // not ASCII, use slower mode { strLength = ReadFromUnicodeKey(id, buffer, maxStrSize, separator); goto Finish; } if ((ch >= 65) && (ch <= 90)) { buffer.Ptr[i] = (byte)(ch | 0x20); } else { buffer.Ptr[i] = (byte)ch; } } _jsonParserState.FindEscapePositionsIn(buffer.Ptr, ref strLength, escapePositionsSize); if (separator != null) { buffer.Ptr[strLength] = separator.Value; strLength++; } Finish: buffer.Truncate(strLength); return(internalScope); }
private BlittableJsonReaderObject ReadObjectInternal(object builder, string documentId, BlittableJsonDocumentBuilder.UsageMode mode, IBlittableDocumentModifier modifier = null) { _jsonParserState.Reset(); _objectJsonParser.Reset(builder); _documentBuilder.Renew(documentId, mode); CachedProperties.NewDocument(); _documentBuilder._modifier = modifier; _documentBuilder.ReadObjectDocument(); if (_documentBuilder.Read() == false) { throw new InvalidOperationException("Partial content in object json parser shouldn't happen"); } _documentBuilder.FinalizeDocument(); _objectJsonParser.Reset(null); var reader = _documentBuilder.CreateReader(); return(reader); }
public static ByteStringContext.InternalScope GetLowerIdSliceAndStorageKey <TTransaction>( TransactionOperationContext <TTransaction> context, string str, out Slice lowerIdSlice, out Slice idSlice) where TTransaction : RavenTransaction { // Because we need to also store escape positions for the key when we store it // we need to store it as a lazy string value. // But lazy string value has two lengths, one is the string length, and the other // is the actual data size with the escape positions // In order to resolve this, we process the key to find escape positions, then store it // in the table using the following format: // // [var int - string len, string bytes, number of escape positions, escape positions] // // The total length of the string is stored in the actual table (and include the var int size // prefix. if (_jsonParserState == null) { _jsonParserState = new JsonParserState(); } _jsonParserState.Reset(); int strLength = str.Length; int maxStrSize = Encoding.GetMaxByteCount(strLength); int idSize = JsonParserState.VariableSizeIntSize(strLength); int escapePositionsSize = JsonParserState.FindEscapePositionsMaxSize(str); var scope = context.Allocator.Allocate(maxStrSize // lower key + idSize // the size of var int for the len of the key + maxStrSize // actual key + escapePositionsSize, out ByteString buffer); byte *ptr = buffer.Ptr; fixed(char *pChars = str) { for (var i = 0; i < strLength; i++) { uint ch = pChars[i]; // PERF: Trick to avoid multiple compare instructions on hot loops. // This is the same as (ch >= 65 && ch <= 90) if (ch - 65 <= 90 - 65) { ptr[i] = (byte)(ch | 0x20); } else { if (ch > 127) // not ASCII, use slower mode { goto UnlikelyUnicode; } ptr[i] = (byte)ch; } ptr[i + idSize + maxStrSize] = (byte)ch; } _jsonParserState.FindEscapePositionsIn(ptr, strLength, escapePositionsSize); } var writePos = ptr + maxStrSize; JsonParserState.WriteVariableSizeInt(ref writePos, strLength); escapePositionsSize = _jsonParserState.WriteEscapePositionsTo(writePos + strLength); idSize = escapePositionsSize + strLength + idSize; Slice.External(context.Allocator, ptr + maxStrSize, idSize, out idSlice); Slice.External(context.Allocator, ptr, str.Length, out lowerIdSlice); return(scope); UnlikelyUnicode: scope.Dispose(); return(UnicodeGetLowerIdAndStorageKey(context, str, out lowerIdSlice, out idSlice, maxStrSize, escapePositionsSize)); }
public static void GetLowerKeySliceAndStorageKey(JsonOperationContext context, string str, out byte *lowerKey, out int lowerSize, out byte *key, out int keySize) { // Because we need to also store escape positions for the key when we store it // we need to store it as a lazy string value. // But lazy string value has two lengths, one is the string length, and the other // is the actual data size with the escape positions // In order to resolve this, we process the key to find escape positions, then store it // in the table using the following format: // // [var int - string len, string bytes, number of escape positions, escape positions] // // The total length of the string is stored in the actual table (and include the var int size // prefix. if (_jsonParserState == null) { _jsonParserState = new JsonParserState(); } _jsonParserState.Reset(); keySize = JsonParserState.VariableSizeIntSize(str.Length); _jsonParserState.FindEscapePositionsIn(str); var escapePositionsSize = _jsonParserState.GetEscapePositionsSize(); var buffer = context.GetNativeTempBuffer( str.Length // lower key + keySize // the size of var int for the len of the key + str.Length // actual key + escapePositionsSize); for (var i = 0; i < str.Length; i++) { var ch = str[i]; if (ch > 127) // not ASCII, use slower mode { goto UnlikelyUnicode; } if ((ch >= 65) && (ch <= 90)) { buffer[i] = (byte)(ch | 0x20); } else { buffer[i] = (byte)ch; } buffer[i + keySize + str.Length] = (byte)ch; } var writePos = buffer + str.Length; JsonParserState.WriteVariableSizeInt(ref writePos, str.Length); _jsonParserState.WriteEscapePositionsTo(writePos + str.Length); keySize = escapePositionsSize + str.Length + keySize; key = buffer + str.Length; lowerKey = buffer; lowerSize = str.Length; return; UnlikelyUnicode: UnicodeGetLowerKeySliceAndStorageKey(context, str, out lowerKey, out lowerSize, out key, out keySize); }