Example #1
0
        /// <summary>
        /// Reads a single node.
        /// </summary>
        /// <remarks>
        /// This won't read the file header or footer, and as such will fail if the stream is a full FBX file
        /// </remarks>
        /// <returns>The node</returns>
        /// <exception cref="FbxException">The FBX data was malformed
        /// for the reader's error level</exception>
        public FbxNode ReadNode(FbxDocument document)
        {
            var endOffset       = document.Version >= FbxVersion.v7_5 ? stream.ReadInt64() : stream.ReadInt32();
            var numProperties   = document.Version >= FbxVersion.v7_5 ? stream.ReadInt64() : stream.ReadInt32();
            var propertyListLen = document.Version >= FbxVersion.v7_5 ? stream.ReadInt64() : stream.ReadInt32();
            var nameLen         = stream.ReadByte();
            var name            = nameLen == 0 ? "" : Encoding.ASCII.GetString(stream.ReadBytes(nameLen));

            if (endOffset == 0)
            {
                // The end offset should only be 0 in a null node
                if (errorLevel >= ErrorLevel.Checked && (numProperties != 0 || propertyListLen != 0 || !string.IsNullOrEmpty(name)))
                {
                    throw new FbxException(stream.BaseStream.Position,
                                           "Invalid node; expected NULL record");
                }

                return(null);
            }

            var node = new FbxNode {
                Name = name
            };

            var propertyEnd = stream.BaseStream.Position + propertyListLen;

            // Read properties
            for (int i = 0; i < numProperties; i++)
            {
                node.AddProperty(ReadProperty());
            }

            if (errorLevel >= ErrorLevel.Checked && stream.BaseStream.Position != propertyEnd)
            {
                throw new FbxException(stream.BaseStream.Position,
                                       "Too many bytes in property list, end point is " + propertyEnd);
            }

            // Read nested nodes
            var listLen = endOffset - stream.BaseStream.Position;

            if (errorLevel >= ErrorLevel.Checked && listLen < 0)
            {
                throw new FbxException(stream.BaseStream.Position,
                                       "Node has invalid end point");
            }

            if (listLen > 0)
            {
                FbxNode nested;
                do
                {
                    nested = ReadNode(document);
                    node.AddNode(nested);
                } while (nested != null);
                if (errorLevel >= ErrorLevel.Checked && stream.BaseStream.Position != endOffset)
                {
                    throw new FbxException(stream.BaseStream.Position,
                                           "Too many bytes in node, end point is " + endOffset);
                }
            }
            return(node);
        }
Example #2
0
        /// <summary>
        /// Reads the next node from the stream
        /// </summary>
        /// <returns>The read node, or <c>null</c></returns>
        public FbxNode ReadNode()
        {
            var first = ReadToken();

            if (!(first is Identifier id))
            {
                if (first is EndOfStream)
                {
                    return(null);
                }

                throw new FbxException(_fbxAsciiFileInfo,
                                       "Unexpected '" + first + "', expected an identifier");
            }
            var node = new FbxNode {
                Name = id.Value
            };

            // Read properties
            object token       = ReadToken();
            bool   expectComma = false;

            while (!'{'.Equals(token) && !(token is Identifier) && !'}'.Equals(token))
            {
                if (expectComma)
                {
                    if (!','.Equals(token))
                    {
                        throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + token + "', expected a ','");
                    }
                    expectComma = false;
                    token       = ReadToken();
                    continue;
                }
                if (token is char c)
                {
                    switch (c)
                    {
                    case '*':
                        token = ReadArray();
                        break;

                    case '}':
                    case ':':
                    case ',':
                        throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + c + "' in property list");
                    }
                }
                node.AddProperty(new FbxValue(token));
                expectComma = true;                 // The final comma before the open brace isn't required
                token       = ReadToken();
            }
            // TODO: Merge property list into an array as necessary
            // Now we're either at an open brace, close brace or a new node
            if (token is Identifier || '}'.Equals(token))
            {
                prevToken = token;
                return(node);
            }
            // The while loop can't end unless we're at an open brace, so we can continue right on
            object endBrace = ReadToken();

            while (!'}'.Equals(endBrace))
            {
                prevToken = endBrace;                 // If it's not an end brace, the next node will need it
                node.AddNode(ReadNode());
                endBrace = ReadToken();
            }
            if (node.Nodes.Length < 1)            // If there's an open brace, we want that to be preserved
            {
                node.AddNode(null);
            }

            return(node);
        }
Example #3
0
        /// <summary>
        /// Reads the next node from the stream
        /// </summary>
        /// <returns>The read node, or <c>null</c></returns>
        public FbxNode ReadNode()
        {
            var first = ReadToken();

            if (!(first is IdentifierToken id))
            {
                if (first is Token tok && tok.TokenType == TokenType.EndOfStream)
                {
                    return(null);
                }
                throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + first + "', expected an identifier");
            }
            var node = new FbxNode(id);

            // Read properties
            Token token       = ReadToken();
            bool  expectComma = false;

            while (token.TokenType != TokenType.OpenBrace && token.TokenType != TokenType.Identifier && token.TokenType != TokenType.CloseBrace)
            {
                if (expectComma)
                {
                    if (token.TokenType != TokenType.Comma)
                    {
                        throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + token + "', expected a ','");
                    }
                    expectComma = false;
                    token       = ReadToken();
                    continue;
                }

                if (token.TokenType == TokenType.Asterix)
                {
                    token = ReadArray();
                }
                else if (token.TokenType == TokenType.CloseBrace || token.TokenType == TokenType.Comma)
                {
                    throw new FbxException(_fbxAsciiFileInfo, "Unexpected '" + token.TokenType + "' in property list");
                }

                node.AddProperty(token);
                expectComma = true;                 // The final comma before the open brace isn't required
                token       = ReadToken();
            }
            // TODO: Merge property list into an array as necessary
            // Now we're either at an open brace, close brace or a new node
            if (token.TokenType == TokenType.Identifier || token.TokenType == TokenType.CloseBrace)
            {
                _tokenStack.Push(token);
                return(node);
            }
            // The while loop can't end unless we're at an open brace, so we can continue right on
            Token endBrace = ReadToken();

            while (endBrace.TokenType != TokenType.CloseBrace)
            {
                _tokenStack.Push(endBrace);
                node.AddNode(ReadNode());
                endBrace = ReadToken();
            }
            if (node.Nodes.Length < 1)            // If there's an open brace, we want that to be preserved
            {
                node.AddNode(null);
            }

            return(node);
        }