예제 #1
0
 public ByamlWriter(Stream stream, bool supportPaths, ByteOrder byteOrder, ushort version)
 {
     _version      = version;
     _supportPaths = supportPaths;
     _byteOrder    = byteOrder;
     _writer       = new BinaryDataWriter(stream, ByamlFile.GetEncoding(byteOrder), true)
     {
         ByteOrder = _byteOrder
     };
 }
        protected Dictionary <uint, dynamic> _alreadyReadNodes = null; //Offset in the file, reference to node

        // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------

        public ByamlReader(Stream stream, bool supportPaths, ByteOrder byteOrder, ushort version, bool fastLoad = false)
        {
            _version      = version;
            _supportPaths = supportPaths;
            _byteOrder    = byteOrder;
            _fastLoad     = fastLoad;
            if (fastLoad)
            {
                _alreadyReadNodes = new Dictionary <uint, dynamic>();
            }

            _reader = new BinaryDataReader(stream, ByamlFile.GetEncoding(byteOrder), true)
            {
                ByteOrder = byteOrder
            };
        }
        protected bool TryStartLoading()
        {
            // Load the header, specifying magic bytes ("BY"), version and main node offsets.
            if (_reader.ReadUInt16() != BYAML_MAGIC)
            {
                //switch endian and try again
                _byteOrder = _byteOrder == ByteOrder.LittleEndian ? ByteOrder.BigEndian : ByteOrder.LittleEndian;

                _reader = new BinaryDataReader(_reader.BaseStream, ByamlFile.GetEncoding(_byteOrder), true)
                {
                    ByteOrder = _byteOrder
                };

                _reader.Position = 0;
                if (_reader.ReadUInt16() != BYAML_MAGIC)
                {
                    throw new Exception("Header mismatch");
                }
            }
            _version = _reader.ReadUInt16();
            uint nameArrayOffset   = _reader.ReadUInt32();
            uint stringArrayOffset = _reader.ReadUInt32();

            if (_reader.Length == 16)
            {
                _supportPaths = false;
            }
            else
            {
                using (_reader.TemporarySeek())
                {
                    // Paths are supported if the third offset is a path array (or unknown) and the fourth a root.
                    ByamlNodeType thirdNodeType = PeekNodeType(_reader);
                    _reader.Seek(sizeof(uint));
                    ByamlNodeType fourthNodeType = PeekNodeType(_reader);

                    _supportPaths = (thirdNodeType == ByamlNodeType.Unknown || thirdNodeType == ByamlNodeType.PathArray) &&
                                    (fourthNodeType == ByamlNodeType.Array || fourthNodeType == ByamlNodeType.Dictionary);
                }
            }


            uint pathArrayOffset = 0;

            if (_supportPaths)
            {
                pathArrayOffset = _reader.ReadUInt32();
            }
            uint rootNodeOffset = _reader.ReadUInt32();

            if (rootNodeOffset == 0) //empty byml
            {
                return(false);
            }

            // Read the name array, holding strings referenced by index for the names of other nodes.
            if (nameArrayOffset != 0)
            {
                _reader.Seek(nameArrayOffset, SeekOrigin.Begin);
                _nameArray = ReadCollectionNode(_reader.ReadUInt32());
            }

            // Read the optional string array, holding strings referenced by index in string nodes.
            if (stringArrayOffset != 0)
            {
                _reader.Seek(stringArrayOffset, SeekOrigin.Begin);
                _stringArray = ReadCollectionNode(_reader.ReadUInt32());
            }

            // Read the optional path array, holding paths referenced by index in path nodes.
            if (_supportPaths && pathArrayOffset != 0)
            {
                // The third offset is the root node, so just read that and we're done.
                _reader.Seek(pathArrayOffset, SeekOrigin.Begin);
                _pathArray = ReadCollectionNode(_reader.ReadUInt32());
            }

            // Read the root node.
            _reader.Seek(rootNodeOffset, SeekOrigin.Begin);

            return(true);



            dynamic ReadCollectionNode(uint lengthAndType)
            {
                int           length   = (int)Get3LsbBytes(lengthAndType);
                ByamlNodeType nodeType = (ByamlNodeType)Get1MsbByte(lengthAndType);

                switch (nodeType)
                {
                case ByamlNodeType.Array:
                    return(ReadArrayNode(_reader, length));

                case ByamlNodeType.Dictionary:
                    return(ReadDictionaryNode(_reader, length));

                case ByamlNodeType.StringArray:
                    return(ReadStringArrayNode(_reader, length));

                case ByamlNodeType.PathArray:
                    return(ReadPathArrayNode(_reader, length));

                default:
                    return(null);    //should never happen
                }
            }
        }