Esempio n. 1
0
        void ReadTagHeader(bool readName)
        {
            // Setting state to error in case reader throws
            NbtParseState oldState = state;

            state = NbtParseState.Error;
            TagsRead++;
            TagName = (readName ? reader.ReadString() : null);

            valueCache = null;
            TagLength  = 0;
            atValue    = false;
            ListType   = NbtTagType.Unknown;

            switch (TagType)
            {
            case NbtTagType.Byte:
            case NbtTagType.Short:
            case NbtTagType.Int:
            case NbtTagType.Long:
            case NbtTagType.Float:
            case NbtTagType.Double:
            case NbtTagType.String:
                atValue = true;
                state   = oldState;
                break;

            case NbtTagType.IntArray:
            case NbtTagType.ByteArray:
            case NbtTagType.LongArray:
                TagLength = reader.ReadInt32();
                if (TagLength < 0)
                {
                    throw new NbtFormatException("Negative array length given: " + TagLength);
                }
                atValue = true;
                state   = oldState;
                break;

            case NbtTagType.List:
                ListType  = reader.ReadTagType();
                TagLength = reader.ReadInt32();
                if (TagLength < 0)
                {
                    throw new NbtFormatException("Negative tag length given: " + TagLength);
                }
                state = NbtParseState.AtListBeginning;
                break;

            case NbtTagType.Compound:
                state = NbtParseState.AtCompoundBeginning;
                break;

            default:
                // This should not happen unless NbtBinaryReader is bugged
                throw new NbtFormatException("Trying to read tag of unknown type.");
            }
        }
Esempio n. 2
0
        void ReadTagHeader(bool readName)
        {
            TagsRead++;
            TagName = (readName ? reader.ReadString() : null);

            valueCache = null;
            TagLength  = 0;
            atValue    = false;
            ListType   = NbtTagType.Unknown;

            switch (TagType)
            {
            case NbtTagType.Byte:
            case NbtTagType.Short:
            case NbtTagType.Int:
            case NbtTagType.Long:
            case NbtTagType.Float:
            case NbtTagType.Double:
            case NbtTagType.String:
                atValue = true;
                break;

            case NbtTagType.IntArray:
            case NbtTagType.ByteArray:
                TagLength = reader.ReadInt32();
                atValue   = true;
                break;

            case NbtTagType.List:
                ListType  = reader.ReadTagType();
                TagLength = reader.ReadInt32();
                state     = NbtParseState.AtListBeginning;
                break;

            case NbtTagType.Compound:
                state = NbtParseState.AtCompoundBeginning;
                break;

            default:
                throw new NbtFormatException("Trying to read tag of unknown type.");
            }
        }
Esempio n. 3
0
        public T[] ReadListAsArray <T>()
        {
            switch (state)
            {
            case NbtParseState.AtStreamEnd:
                throw new EndOfStreamException();

            case NbtParseState.Error:
                throw new InvalidReaderStateException(ErroneousStateError);

            case NbtParseState.AtListBeginning:
                GoDown();
                ListIndex = 0;
                TagType   = ListType;
                state     = NbtParseState.InList;
                break;

            case NbtParseState.InList:
                break;

            default:
                throw new InvalidOperationException("ReadListAsArray may only be used on List tags.");
            }

            int elementsToRead = ParentTagLength - ListIndex;

            // special handling for reading byte arrays (as byte arrays)
            if (ListType == NbtTagType.Byte && typeof(T) == typeof(byte))
            {
                TagsRead += elementsToRead;
                ListIndex = ParentTagLength - 1;
                T[] val = (T[])(object)reader.ReadBytes(elementsToRead);
                if (val.Length < elementsToRead)
                {
                    throw new EndOfStreamException();
                }
                return(val);
            }

            // for everything else, gotta read elements one-by-one
            var result = new T[elementsToRead];

            switch (ListType)
            {
            case NbtTagType.Byte:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadByte(), typeof(T));
                }
                break;

            case NbtTagType.Short:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadInt16(), typeof(T));
                }
                break;

            case NbtTagType.Int:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadInt32(), typeof(T));
                }
                break;

            case NbtTagType.Long:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadInt64(), typeof(T));
                }
                break;

            case NbtTagType.Float:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadSingle(), typeof(T));
                }
                break;

            case NbtTagType.Double:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadDouble(), typeof(T));
                }
                break;

            case NbtTagType.String:
                for (int i = 0; i < elementsToRead; i++)
                {
                    result[i] = (T)Convert.ChangeType(reader.ReadString(), typeof(T));
                }
                break;

            default:
                throw new InvalidOperationException("ReadListAsArray may only be used on lists of value types.");
            }
            TagsRead += elementsToRead;
            ListIndex = ParentTagLength - 1;
            return(result);
        }
Esempio n. 4
0
        /// <summary> Reads the next tag from the stream. </summary>
        /// <returns> true if the next tag was read successfully; false if there are no more tags to read. </returns>
        /// <exception cref="NbtFormatException"> If an error occurred while parsing data in NBT format. </exception>
        /// <exception cref="InvalidReaderStateException"> If NbtReader cannot recover from a previous parsing error. </exception>
        public bool ReadToFollowing()
        {
            switch (state)
            {
            case NbtParseState.AtStreamBeginning:
                // set state to error in case reader.ReadTagType throws.
                state = NbtParseState.Error;
                // read first tag, make sure it's a compound
                if (reader.ReadTagType() != NbtTagType.Compound)
                {
                    throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
                }
                Depth   = 1;
                TagType = NbtTagType.Compound;
                // Read root name. Advance to the first inside tag.
                ReadTagHeader(true);
                RootName = TagName;
                return(true);

            case NbtParseState.AtCompoundBeginning:
                GoDown();
                state = NbtParseState.InCompound;
                goto case NbtParseState.InCompound;

            case NbtParseState.InCompound:
                state = NbtParseState.Error;
                if (atValue)
                {
                    SkipValue();
                }
                // Read next tag, check if we've hit the end
                if (canSeekStream)
                {
                    TagStartOffset = (int)(reader.BaseStream.Position - streamStartOffset);
                }

                // set state to error in case reader.ReadTagType throws.
                TagType = reader.ReadTagType();
                state   = NbtParseState.InCompound;

                if (TagType == NbtTagType.End)
                {
                    TagName = null;
                    TagsRead++;
                    state = NbtParseState.AtCompoundEnd;
                    if (SkipEndTags)
                    {
                        TagsRead--;
                        goto case NbtParseState.AtCompoundEnd;
                    }
                    else
                    {
                        return(true);
                    }
                }
                else
                {
                    ReadTagHeader(true);
                    return(true);
                }

            case NbtParseState.AtListBeginning:
                GoDown();
                ListIndex = -1;
                TagType   = ListType;
                state     = NbtParseState.InList;
                goto case NbtParseState.InList;

            case NbtParseState.InList:
                state = NbtParseState.Error;
                if (atValue)
                {
                    SkipValue();
                }
                ListIndex++;
                if (ListIndex >= ParentTagLength)
                {
                    GoUp();
                    if (ParentTagType == NbtTagType.List)
                    {
                        state   = NbtParseState.InList;
                        TagType = NbtTagType.List;
                        goto case NbtParseState.InList;
                    }
                    else if (ParentTagType == NbtTagType.Compound)
                    {
                        state = NbtParseState.InCompound;
                        goto case NbtParseState.InCompound;
                    }
                    else
                    {
                        // This should not happen unless NbtReader is bugged
                        throw new NbtFormatException(InvalidParentTagError);
                    }
                }
                else
                {
                    if (canSeekStream)
                    {
                        TagStartOffset = (int)(reader.BaseStream.Position - streamStartOffset);
                    }
                    state = NbtParseState.InList;
                    ReadTagHeader(false);
                }
                return(true);

            case NbtParseState.AtCompoundEnd:
                GoUp();
                if (ParentTagType == NbtTagType.List)
                {
                    state   = NbtParseState.InList;
                    TagType = NbtTagType.Compound;
                    goto case NbtParseState.InList;
                }
                else if (ParentTagType == NbtTagType.Compound)
                {
                    state = NbtParseState.InCompound;
                    goto case NbtParseState.InCompound;
                }
                else if (ParentTagType == NbtTagType.Unknown)
                {
                    state = NbtParseState.AtStreamEnd;
                    return(false);
                }
                else
                {
                    // This should not happen unless NbtReader is bugged
                    state = NbtParseState.Error;
                    throw new NbtFormatException(InvalidParentTagError);
                }

            case NbtParseState.AtStreamEnd:
                // nothing left to read!
                return(false);

            default:
                // Parsing error, or unexpected state.
                throw new InvalidReaderStateException(ErroneousStateError);
            }
        }