示例#1
0
        public RbfStructure Load(Stream stream)
        {
            stack       = new Stack <RbfStructure>();
            descriptors = new List <RbfEntryDescription>();

            var reader = new DataReader(stream);
            var ident  = reader.ReadInt32();

            if (ident != RBF_IDENT)
            {
                throw new Exception("The file identifier does not match.");
            }

            while (reader.Position < reader.Length)
            {
                var descriptorIndex = reader.ReadByte();
                if (descriptorIndex == 0xFF) // close tag
                {
                    var b = reader.ReadByte();
                    if (b != 0xFF)
                    {
                        throw new Exception("Expected 0xFF but was " + b.ToString("X2"));
                    }

                    if (stack.Count > 0)
                    {
                        current = stack.Pop();
                    }
                    else
                    {
                        if (reader.Position != reader.Length)
                        {
                            throw new Exception("Expected end of stream but was not.");
                        }
                        return(current);
                    }
                }
                else if (descriptorIndex == 0xFD) // bytes
                {
                    var b = reader.ReadByte();
                    if (b != 0xFF)
                    {
                        throw new Exception("Expected 0xFF but was " + b.ToString("X2"));
                    }

                    var dataLength = reader.ReadInt32();
                    var data       = reader.ReadBytes(dataLength);

                    var bytesValue = new RbfBytes();
                    bytesValue.Value = data;
                    current.Children.Add(bytesValue);
                }
                else
                {
                    var dataType = reader.ReadByte();
                    if (descriptorIndex == descriptors.Count) // new descriptor + data
                    {
                        var nameLength = reader.ReadInt16();
                        var nameBytes  = reader.ReadBytes(nameLength);
                        var name       = Encoding.ASCII.GetString(nameBytes);

                        var descriptor = new RbfEntryDescription();
                        descriptor.Name = name;
                        descriptor.Type = dataType;
                        descriptors.Add(descriptor);

                        ParseElement(reader, descriptors.Count - 1);
                    }
                    else // existing descriptor + data
                    {
                        if (dataType != descriptors[descriptorIndex].Type)
                        {
                            throw new Exception("Data type does not match.");
                        }

                        ParseElement(reader, descriptorIndex);
                    }
                }
            }

            throw new Exception("Unexpected end of stream.");
        }
示例#2
0
        private void ParseElement(DataReader reader, int descriptorIndex)
        {
            var descriptor = descriptors[descriptorIndex];

            switch (descriptor.Type)
            {
            case 0:     // open element...
            {
                var structureValue = new RbfStructure();
                structureValue.Name = descriptor.Name;

                if (current != null)
                {
                    current.Children.Add(structureValue);
                    stack.Push(current);
                }

                current = structureValue;

                // 6 bytes
                var x1 = reader.ReadInt16();
                var x2 = reader.ReadInt16();
                var x3 = reader.ReadInt16();
                //if (x1 != 0)
                //    throw new Exception("unexpected");
                //if (x2 != 0)
                //    throw new Exception("unexpected");
                //if (x3 != 0)
                //    throw new Exception("unexpected");
                break;
            }

            case 0x10:
            {
                var intValue = new RbfUint32();
                intValue.Name  = descriptor.Name;
                intValue.Value = reader.ReadUInt32();
                current.Children.Add(intValue);
                break;
            }

            case 0x20:
            {
                var booleanValue = new RbfBoolean();
                booleanValue.Name  = descriptor.Name;
                booleanValue.Value = true;
                current.Children.Add(booleanValue);
                break;
            }

            case 0x30:
            {
                var booleanValue = new RbfBoolean();
                booleanValue.Name  = descriptor.Name;
                booleanValue.Value = false;
                current.Children.Add(booleanValue);
                break;
            }

            case 0x40:
            {
                var floatValue = new RbfFloat();
                floatValue.Name  = descriptor.Name;
                floatValue.Value = reader.ReadSingle();
                current.Children.Add(floatValue);
                break;
            }

            case 0x50:
            {
                var floatVectorValue = new RbfFloat3();
                floatVectorValue.Name = descriptor.Name;
                floatVectorValue.X    = reader.ReadSingle();
                floatVectorValue.Y    = reader.ReadSingle();
                floatVectorValue.Z    = reader.ReadSingle();
                current.Children.Add(floatVectorValue);
                break;
            }

            case 0x60:
            {
                var valueLength = reader.ReadInt16();
                var valueBytes  = reader.ReadBytes(valueLength);
                var value       = Encoding.ASCII.GetString(valueBytes);
                var stringValue = new RbfString();
                stringValue.Name  = descriptor.Name;
                stringValue.Value = value;
                current.Children.Add(stringValue);
                break;
            }

            default:
                throw new Exception("Unsupported data type.");
            }
        }