public bool TryReadObject(out JsonObjectReader reader, ref JsonObjectFileInfo fileInfo)
        {
            fileInfo.StartLine = fileInfo.EndLine;

            int status;
            var length = ReadObject(out status, ref fileInfo);

            if (status == KResultInvalidJson)
            {
                throw new Exception($"JsonStreamReader.TryReadObject expected '{{' as the next character. Line=[{fileInfo.EndLine}]");
            }

            if (status != KResultSuccess)
            {
                reader = new JsonObjectReader
                {
                    Line = fileInfo.StartLine
                };

                return(false);
            }

            reader = new JsonObjectReader(m_ObjectBuffer, 0, length)
            {
                Line = fileInfo.StartLine
            };
            return(true);
        }
Пример #2
0
        public static void Accept(Stream input, Stream output)
        {
            var jsonStreamReader = new JsonStreamReader(input);

            using (var binaryStream = new MemoryStream())
                using (var binaryWriter = new BinaryWriter(binaryStream))
                {
                    var commandStreamWriter = new BinaryWriter(output);

                    var c = jsonStreamReader.ReadChar(); // '['
                    Assert.IsTrue(c == '[', $"FlatJson.FrontEnd.Accept expected '[' but found '{c}' as the first character of the stream. Line=[1]");

                    var fileInfo = new JsonObjectFileInfo();

                    // Read the next full json object from '{' to '}
                    JsonObjectReader objectReader;
                    while (jsonStreamReader.TryReadObject(out objectReader, ref fileInfo))
                    {
                        objectReader.ReadBeginObject();

                        // Unpack the typeId
                        var property = objectReader.ReadPropertyNameSegment();
                        Assert.IsTrue(property.Array[property.Offset] == '$');

                        var typeId = (UTinyTypeId)objectReader.ReadUInt16();

                        objectReader.Position = 0;

                        commandStreamWriter.Write(CommandType.GetCreateCommandType(typeId));

                        // Translate the json object to binary
                        BinaryTranslator.TranslateObject(ref objectReader, binaryWriter);

                        // Write the command payload as binary
                        commandStreamWriter.Write((uint)binaryStream.Position);
                        commandStreamWriter.Write(binaryStream.GetBuffer(), 0, (int)binaryStream.Position);
                        binaryStream.Position = 0;

                        c = jsonStreamReader.ReadChar(); // ',' or ']'
                        if (!(c == ',' || c == ']'))
                        {
                            throw new Exception($"FlatJson.FrontEnd.Accept expected ',' or ']' but found '{Escape(c)}' as the next character in the stream. Line=[{objectReader.Line}]");
                        }
                    }
                }
        }
        /// <summary>
        /// Reads a json object from '{' to '}'
        /// </summary>
        /// <param name="result">Read result</param>
        /// <returns>Number of characters read</returns>
        private int ReadObject(out int result, ref JsonObjectFileInfo fileInfo)
        {
            unsafe
            {
                fixed(char *p = m_CharBuffer)
                {
                    result = KResultError;
                    char c;
                    var  count = 0;

                    var index  = 0;
                    var buffer = m_ObjectBuffer;
                    var length = m_ObjectBuffer.Length;

                    // Read until we hit the first '{' brace
                    var found = false;

                    do
                    {
                        if (m_Position >= m_Count)
                        {
                            // Refill the underlying buffer
                            if (!FillBuffer())
                            {
                                result = KResultEndOfStream;
                                return(0);
                            }
                        }
                        for (; m_Position < m_Count; m_Position++)
                        {
                            c = *(p + m_Position);

                            if (c == '{')
                            {
                                found = true;
                                break;
                            }

                            switch (c)
                            {
                            case '\n':
                                fileInfo.StartLine++;
                                fileInfo.EndLine++;
                                continue;

                            case ' ':
                            case '\t':
                            case '\r':
                                continue;
                            }

                            result = KResultInvalidJson;
                            return(count);
                        }
                    } while (!found);

                    var begin = m_Position;
                    var depth = 1;

                    m_Position++;

                    // Read until we hit the matching '}' brace
                    found = false;
                    do
                    {
                        // Output buffer bounds check
                        if (index + m_Position - begin >= length - 1)
                        {
                            // realloc
                            length        *= 2;
                            m_ObjectBuffer = new char[length];
                            Array.Copy(buffer, m_ObjectBuffer, index);
                            buffer = m_ObjectBuffer;
                        }

                        if (m_Position >= m_Count)
                        {
                            // Copy to the output buffer
                            var len = m_Count - begin;
                            Array.Copy(m_CharBuffer, begin, buffer, index, len);

                            index += len;
                            count += len;

                            // Refill the underlying buffer
                            if (!FillBuffer())
                            {
                                result = KResultEndOfStream;
                                return(count);
                            }

                            begin = m_Position;
                        }

                        var end = m_Position + Math.Min(length - (index + m_Position - begin), m_Count - m_Position);

                        for (; m_Position < end; m_Position++)
                        {
                            c = *(p + m_Position);

                            if (c == '{')
                            {
                                depth++;
                            }
                            else if (c == '}')
                            {
                                depth--;

                                if (depth != 0)
                                {
                                    continue;
                                }

                                result = KResultSuccess;
                                found  = true;
                                m_Position++;

                                break;
                            }
                            else if (c == '\n')
                            {
                                fileInfo.EndLine++;
                            }
                        }
                    } while (!found);

                    // Flush to the output buffer
                    Array.Copy(m_CharBuffer, begin, buffer, index, m_Position - begin);

                    count += m_Position - begin;
                    return(count);
                }
            }
        }