//Read a structure
        private static void ReadValueStruct(char c, Parser parser)
        {
            //Ignore whitespace
            if (char.IsWhiteSpace(c))
            {
                return;
            }

            //Catch comments
            if (c == '/')
            {
                parser.StateStack.Push(State.COMMENT);
                parser.CurrentString.Clear();
                parser.CurrentString.Append(c);
                return;
            }

            //Check for the end of the structure
            if (c == '}')
            {
                KVObject value = parser.ObjStack.Pop();
                parser.ObjStack.Peek().AddProperty(value.Key, new KVValue(KVType.OBJECT, value));
                parser.StateStack.Pop();
                return;
            }

            //Start looking for the next property name
            parser.StateStack.Push(State.PROP_NAME);
            parser.CurrentString.Clear();
            parser.CurrentString.Append(c);
        }
 public KV3File(
     KVObject root,
     string encoding = "text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d}",
     string format = "generic:version{7412167c-06e9-4698-aff2-e63eb59037e7}")
 {
     Root = root;
     Encoding = encoding;
     Format = format;
 }
示例#3
0
 public KV3File(
     KVObject root,
     string encoding = "text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d}",
     string format   = "generic:version{7412167c-06e9-4698-aff2-e63eb59037e7}")
 {
     Root     = root;
     Encoding = encoding;
     Format   = format;
 }
            public Parser()
            {
                //Initialise datastructures
                ObjStack = new Stack<KVObject>();
                StateStack = new Stack<State>();
                StateStack.Push(State.HEADER);

                Root = new KVObject("root");
                ObjStack.Push(Root);

                PreviousChar = '\0';
                CharBuffer = new Queue<char>();

                CurrentString = new StringBuilder();
            }
            public Parser()
            {
                //Initialise datastructures
                ObjStack   = new Stack <KVObject>();
                StateStack = new Stack <State>();
                StateStack.Push(State.HEADER);

                Root = new KVObject("root");
                ObjStack.Push(Root);

                PreviousChar = '\0';
                CharBuffer   = new Queue <char>();

                CurrentString = new StringBuilder();
            }
        //Seeking value state
        private static void SeekValue(char c, Parser parser)
        {
            //Ignore whitespace
            if (char.IsWhiteSpace(c) || c == '=')
            {
                return;
            }

            //Check struct opening
            if (c == '{')
            {
                parser.StateStack.Pop();
                parser.StateStack.Push(State.VALUE_STRUCT);

                parser.ObjStack.Push(new KVObject(parser.CurrentString.ToString()));
            }

            //Check for array opening
            else if (c == '[')
            {
                parser.StateStack.Pop();
                parser.StateStack.Push(State.VALUE_ARRAY);
                parser.StateStack.Push(State.SEEK_VALUE);

                parser.ObjStack.Push(new KVObject(parser.CurrentString.ToString(), true));
            }

            //Check for array closing
            else if (c == ']')
            {
                parser.StateStack.Pop();
                parser.StateStack.Pop();

                KVObject value = parser.ObjStack.Pop();
                parser.ObjStack.Peek().AddProperty(value.Key, new KVValue(KVType.ARRAY, value));
            }

            //String opening
            else if (c == '"')
            {
                //Check if a multistring or single string was found
                string next = PeekString(parser, 4);
                if (next.Contains("\"\"\n") || next == "\"\"\r\n")
                {
                    //Skip the next two "'s
                    SkipChars(parser, 2);

                    parser.StateStack.Pop();
                    parser.StateStack.Push(State.VALUE_STRING_MULTI);
                    parser.CurrentString.Clear();
                }
                else
                {
                    parser.StateStack.Pop();
                    parser.StateStack.Push(State.VALUE_STRING);
                    parser.CurrentString.Clear();
                }
            }

            //Boolean false
            else if (ReadAheadMatches(parser, c, "false"))
            {
                parser.StateStack.Pop();

                //Can directly be added
                parser.ObjStack.Peek().AddProperty(parser.CurrentName, new KVValue(KVType.BOOLEAN, false));

                //Skip next characters
                SkipChars(parser, "false".Length - 1);
            }

            //Boolean true
            else if (ReadAheadMatches(parser, c, "true"))
            {
                parser.StateStack.Pop();

                //Can directly be added
                parser.ObjStack.Peek().AddProperty(parser.CurrentName, new KVValue(KVType.BOOLEAN, true));

                //Skip next characters
                SkipChars(parser, "true".Length - 1);
            }

            //Null
            else if (ReadAheadMatches(parser, c, "null"))
            {
                parser.StateStack.Pop();

                //Can directly be added
                parser.ObjStack.Peek().AddProperty(parser.CurrentName, new KVValue(KVType.NULL, null));

                //Skip next characters
                SkipChars(parser, "null".Length - 1);
            }

            // Number
            else if (char.IsDigit(c))
            {
                parser.StateStack.Pop();
                parser.StateStack.Push(State.VALUE_NUMBER);
                parser.CurrentString.Clear();
                parser.CurrentString.Append(c);
            }

            //Flagged resource
            else
            {
                parser.StateStack.Pop();
                parser.StateStack.Push(State.VALUE_FLAGGED);
                parser.CurrentString.Clear();
                parser.CurrentString.Append(c);
            }
        }
        public override void Read(BinaryReader reader, Resource resource)
        {
            reader.BaseStream.Position = Offset;
            var outStream = new MemoryStream();
            BinaryWriter outWrite = new BinaryWriter(outStream);
            BinaryReader outRead = new BinaryReader(outStream); // Why why why why why why why

            var sig = reader.ReadBytes(4);
            if (Encoding.ASCII.GetString(sig) != Encoding.ASCII.GetString(SIG))
            {
                throw new InvalidDataException("Invalid KV Signature");
            }

            // outWrite.Write(sig);
            var encoding = reader.ReadBytes(16);
            if (Encoding.ASCII.GetString(encoding) != Encoding.ASCII.GetString(ENCODING))
            {
                throw new InvalidDataException("Unrecognized KV3 Encoding");
            }

            // outWrite.Write(encoding);
            var format = reader.ReadBytes(16);
            if (Encoding.ASCII.GetString(format) != Encoding.ASCII.GetString(FORMAT))
            {
                throw new InvalidDataException("Unrecognised KV3 Format");
            }

            // outWrite.Write(format);

            // Ok we are 100% sure its now KV, good

            // It is flags, right?
            var flags = reader.ReadUInt32(); // TODO: Figure out what this is
            // outWrite.Write(flags);
            if ((flags & 0x80000000) > 0)
            {
                outWrite.Write(reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)));
            }
            else
            {
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    try
                    {
                        var blockMask = reader.ReadUInt16();
                        for (int i = 0; i < 16; i++)
                        {
                            // is the ith bit 1
                            if ((blockMask & (1 << i)) > 0)
                            {
                                var offsetSize = reader.ReadUInt16();
                                var offset = ((offsetSize & 0xFFF0) >> 4) + 1;
                                var size = (offsetSize & 0x000F) + 3;

                                var lookupSize = (offset < size) ? offset : size; // If the offset is larger or equal to the size, use the size instead.

                                // Kill me now
                                var p = outRead.BaseStream.Position;
                                outRead.BaseStream.Position = p - offset;
                                var data = outRead.ReadBytes(lookupSize);
                                outWrite.BaseStream.Position = p;

                                while (size > 0)
                                {
                                    outWrite.Write(data, 0, (lookupSize < size) ? lookupSize : size);
                                    size -= lookupSize;
                                }
                            }
                            else
                            {
                                var data = reader.ReadByte();
                                outWrite.Write(data);
                            }
                        }
                    }
                    catch (EndOfStreamException e)
                    {
                        break;
                    }
                }
            }

            outRead.BaseStream.Position = 0;
            var stringCount = outRead.ReadUInt32(); //Assuming UInt
            stringArray = new string[stringCount];
            for (var i = 0; i < stringCount; i++)
            {
                stringArray[i] = outRead.ReadNullTermString(Encoding.UTF8);
            }

            Data = ParseBinaryKV3(outRead, null, true);
        }
        private KVObject ParseBinaryKV3(BinaryReader reader, KVObject parent, bool inArray = false)
        {
            string name = null;
            if (!inArray)
            {
                var stringID = reader.ReadInt32();
                name = (stringID == -1) ? string.Empty : stringArray[stringID];
            }

            var datatype = reader.ReadByte();
            KVFlag flagInfo = KVFlag.None;
            if ((datatype & 0x80) > 0)
            {
                datatype &= 0x7F; //Remove the flag bit.
                flagInfo = (KVFlag)reader.ReadByte();
            }

            switch (datatype)
            {
                case (byte)KVType.NULL:
                    parent.AddProperty(name, MakeValue(datatype, null, flagInfo));
                    break;
                case (byte)KVType.BOOLEAN:
                    parent.AddProperty(name, MakeValue(datatype, reader.ReadBoolean(), flagInfo));
                    break;
                case (byte)KVType.INTEGER:
                    parent.AddProperty(name, MakeValue(datatype, reader.ReadInt64(), flagInfo));
                    break;
                case (byte)KVType.DOUBLE:
                    parent.AddProperty(name, MakeValue(datatype, reader.ReadDouble(), flagInfo));
                    break;
                case (byte)KVType.STRING:
                    var id = reader.ReadInt32();
                    parent.AddProperty(name, MakeValue(datatype, id == -1 ? string.Empty : stringArray[id], flagInfo));
                    break;
                case (byte)KVType.ARRAY:
                    var arrayLength = reader.ReadInt32(); //UInt or Int?
                    var array = new KVObject(name, true);
                    for (var i = 0; i < arrayLength; i++)
                    {
                        ParseBinaryKV3(reader, array, true);
                    }

                    parent.AddProperty(name, MakeValue(datatype, array, flagInfo));
                    break;
                case (byte)KVType.OBJECT:
                    var objectLength = reader.ReadInt32(); //UInt or Int?
                    var newObject = new KVObject(name, false);
                    for (var i = 0; i < objectLength; i++)
                    {
                        ParseBinaryKV3(reader, newObject, false);
                    }

                    if (parent == null)
                    {
                        parent = newObject;
                    }
                    else
                    {
                        parent.AddProperty(name, MakeValue(datatype, newObject, flagInfo));
                    }

                    break;
                default:
                    throw new InvalidDataException(string.Format("Unknown KVType {0}", datatype));
            }

            return parent;
        }