Example #1
0
        //public static NbtDocument ParseValue(ref NbtReader reader)
        //{
        //
        //}
        //
        //public static bool TryParseValue(ref NbtReader reader, out NbtDocument document)
        //{
        //}

        private static void Parse(
            ref NbtReader reader,
            ref MetadataDb database,
            ref ByteStack <ContainerFrame> stack)
        {
            int rowCount = 0;

            while (reader.Read())
            {
                int      location = reader.TagLocation;
                NbtType  type     = reader.TagType;
                NbtFlags flags    = reader.TagFlags;

PeekStack:
                ref ContainerFrame frame = ref stack.TryPeek();
                if (!Unsafe.IsNullRef(ref frame))
                {
                    if (frame.ListEntriesRemaining == 0)
                    {
                        stack.TryPop();

                        int totalRowCount = rowCount - frame.InitialRowCount;
                        database.SetRowCount(frame.ContainerRow, totalRowCount);
                        goto PeekStack;
                    }
                    else if (frame.ListEntriesRemaining != -1)
                    {
                        frame.ListEntriesRemaining--;
                    }
                    else
                    {
                        frame.CompoundEntryCounter++;
                    }
                }

                switch (type)
                {
                case NbtType.End:
                {
                    // Documents with a single End tag (no Compound root) are valid.
                    if (stack.TryPop(out var compoundFrame))
                    {
                        int totalRowCount  = rowCount - compoundFrame.InitialRowCount;
                        int compoundLength = compoundFrame.CompoundEntryCounter - 1;     // -1 to exclude End

                        database.SetRowCount(compoundFrame.ContainerRow, totalRowCount);
                        database.SetLength(compoundFrame.ContainerRow, compoundLength);
                    }
                    continue;     // Continue to not increment row count
                }

                case NbtType.Compound:
                {
                    int containerRow = database.Append(
                        location, collectionLength: 0, rowCount: 1, type, flags);

                    stack.Push(new ContainerFrame(containerRow, rowCount)
                        {
                            ListEntriesRemaining = -1
                        });
                    break;
                }

                case NbtType.List:
                {
                    int listLength   = reader.TagCollectionLength;
                    int containerRow = database.Append(
                        location, listLength, rowCount: 1, type, flags);

                    stack.Push(new ContainerFrame(containerRow, rowCount)
                        {
                            ListEntriesRemaining = listLength
                        });
                    break;
                }

                default:
                    database.Append(location, reader.TagCollectionLength, rowCount: 1, type, flags);
                    break;
                }

                rowCount++;
            }

            database.TrimExcess();
        }