unsafe static string GetEscapedString(string value) { var required = Encoding.UTF8.GetByteCount(value); byte[] buffer; required = required * 2 + 2; int result; while (true) { buffer = new byte[required]; fixed(byte *ptr = buffer) { result = ConvertUTF.WriteStringUtf8(value, ptr, buffer.Length); } if (result > 2) { break; } required *= 2; } return(Encoding.UTF8.GetString(buffer, 0, result)); }
public static Lookup?GenerateIndexedLookup(KeyValuePair <ulong, string>[] values, byte *destination, int available) { int valueCount = values.Length; if (valueCount == 0) { return(null); } var maxValue = values.Last().Key + 1; byte *endStrings = destination + available; byte *stringPtr = (byte *)(destination + (maxValue * 4)); var stringsStart = stringPtr; if (stringPtr >= destination + available) { return(null); } int valueIndex = 0; for (ulong i = 0; i < maxValue; i++) { long offset = stringPtr - stringsStart; if (offset > ushort.MaxValue) { return(null); } var enumName = GetString(values, (int)i, ref valueIndex); if (enumName == null) { *(uint *)(destination + (i * 4)) = 0; continue; } *(ushort *)(destination + (i * 4)) = (ushort)offset; int result = ConvertUTF.WriteStringUtf8(enumName, stringPtr, (int)(endStrings - stringPtr), useQuote: false); if (result <= 0 || result >= ushort.MaxValue) { return(null); } *(ushort *)(destination + (i * 4) + 2) = (ushort)result; stringPtr += result; } return(new Lookup(destination, stringsStart, stringPtr, LookupTypes.Indexed)); }
public static Lookup?GenerateSortedLookup(KeyValuePair <ulong, string>[] values, byte *destination, int available) { if (values.Length == 0) { return(null); } var maxValue = values[values.Length - 1].Key; if (maxValue > uint.MaxValue) { return(null); } byte *endStrings = destination + available; byte *stringPtr = (byte *)(destination + (values.Length * 8)); var stringsStart = stringPtr; if (stringPtr >= destination + available) { return(null); } int ix = 0; foreach (var value in values) { long offset = stringPtr - stringsStart; if (offset > ushort.MaxValue) { return(null); } *(uint *)(destination + ix) = (uint)value.Key; *(ushort *)(destination + ix + 4) = (ushort)offset; int result = ConvertUTF.WriteStringUtf8(value.Value, stringPtr, (int)(endStrings - stringPtr), useQuote: false); if (result <= 0 || result >= ushort.MaxValue) { return(null); } *(ushort *)(destination + ix + 6) = (ushort)result; stringPtr += result; ix += 8; } return(new Lookup(destination, stringsStart, stringPtr, LookupTypes.Sorted)); }
public static Lookup?GenerateVerboseLookup(KeyValuePair <ulong, string>[] values, byte *destination, int available) { if (values.Length == 0) { return(null); } byte *endStrings = destination + available; byte *stringPtr = (byte *)(destination + (values.Length * 16)); var stringsStart = stringPtr; if (stringPtr >= destination + available) { return(null); } int ix = 0; foreach (var value in values) { long offset = stringPtr - stringsStart; if (offset > ushort.MaxValue) { return(null); } int result = ConvertUTF.WriteStringUtf8(value.Value, stringPtr, (int)(endStrings - stringPtr), useQuote: false); if (result <= 0 || result >= ushort.MaxValue) { return(null); } var verbose = (VerboseEnum *)(destination + ix); bool inlined = verbose->Init(stringsStart, value.Key, stringPtr, result); if (!inlined) { stringPtr += result; } ix += 16; } return(new Lookup(destination, stringsStart, stringPtr, LookupTypes.Verbose)); }
static void WriteBase64ToStream(byte[] value, Stream stream, byte[] buffer, ref int available, ref byte *bufferOffset) { if (value == null) { ConvertUTF.NullToStream(stream, buffer, ref available, ref bufferOffset); return; } var dst = bufferOffset; var bufferStart = ConvertUTF.GetStart(buffer, dst, available); var lastBatchStart = bufferStart + buffer.Length - 5; // 4 for "digits", 1 for close quote int required = GetBase64StringLength(value.Length); // flush if there's not enough room for best case if (available < required) { ConvertUTF.Flush(stream, buffer, (int)(dst - bufferStart)); dst = bufferStart; } byte *start = dst; *dst++ = (byte)'"'; byte *lookup = BASE64; int three; int i; for (i = 0; i < value.Length - 2; i += 3) { if (dst > lastBatchStart) { ConvertUTF.Flush(stream, buffer, (int)(dst - bufferStart)); dst = bufferStart; } three = (value[i] << 16) | (value[i + 1] << 8) | (value[i + 2]); *dst++ = *(lookup + ((three >> 18))); *dst++ = *(lookup + ((three >> 12) & 63)); *dst++ = *(lookup + ((three >> 6) & 63)); *dst++ = *(lookup + ((three) & 63)); } // 1 in 3 chance we don't need this if (dst > lastBatchStart) { ConvertUTF.Flush(stream, buffer, (int)(dst - bufferStart)); dst = bufferStart; } switch (value.Length - i) { case 2: three = (value[i] << 10) | (value[i + 1] << 2); *dst++ = *(lookup + ((three >> 12))); *dst++ = *(lookup + ((three >> 6) & 63)); *dst++ = *(lookup + ((three) & 63)); *dst++ = (byte)'='; break; case 1: three = value[i] << 4; *dst++ = *(lookup + ((three >> 6))); *dst++ = *(lookup + ((three) & 63)); *dst++ = (byte)'='; *dst++ = (byte)'='; break; } *dst++ = (byte)'"'; bufferOffset = dst; available = buffer.Length - (int)(dst - bufferStart); }