Exemple #1
0
        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));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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));
        }
Exemple #4
0
        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);
        }