object ParseObject()

in Agents/Xamarin.Interactive/Collections/PropertyList.cs [248:338]


        object ParseObject (ulong objectIndex)
        {
            Seek (offsetTable [objectIndex]);

            var header = reader.ReadByte ();
            var kind = (MarkerKind)(header & 0xF0);
            var subKind = (MarkerKind)(header);
            var length = header & 0x0F;

            switch ((MarkerKind)header) {
            case MarkerKind.Date:
                return PlistDate.FromAbsoluteTime (ReadSizedDouble (8));
            }

            switch (kind) {
            case MarkerKind.Data:
            case MarkerKind.AsciiString:
            case MarkerKind.Unicode16String:
            case MarkerKind.Array:
            case MarkerKind.Set:
            case MarkerKind.Dict:
                if (length == 0xF)
                    length = (int)ReadInt ();
                break;
            }

            switch (kind) {
            case MarkerKind.Null:
                switch (subKind) {
                case MarkerKind.Null:
                case MarkerKind.Fill:
                    return null;
                case MarkerKind.False:
                    return false;
                case MarkerKind.True:
                    return true;
                }
                break;
            case MarkerKind.Uid:
                var buffer = new byte [16];
                reader.Read (buffer, 0, length + 1);
                return new Guid (buffer);
            case MarkerKind.Int:
                return (long)ReadSizedInt (1UL << length);
            case MarkerKind.Real:
                return ReadSizedDouble (1UL << length);
            case MarkerKind.Data:
                return reader.ReadBytes (length);
            case MarkerKind.AsciiString:
                var strBytes = reader.ReadBytes (length);
                return Encoding.ASCII.GetString (strBytes);
            case MarkerKind.Unicode16String:
                var uniBytes = reader.ReadBytes (length);
                return Encoding.BigEndianUnicode.GetString (uniBytes);
            case MarkerKind.Array:
            case MarkerKind.Set:
                ICollection<object> array;
                if (kind == MarkerKind.Array)
                    array = new PlistArray ();
                else
                    array = new PlistSet ();

                var arrayStart = (ulong)stream.Position;

                for (var i = 0UL; i < (ulong)length; i++) {
                    Seek (arrayStart + i * trailer.ObjectRefSize);
                    var valueRef = ReadSizedInt (trailer.ObjectRefSize);
                    array.Add (ParseObject (valueRef));
                }

                return (object)array;
            case MarkerKind.Dict:
                var dict = new PlistDictionary ();
                var dictStart = (ulong)stream.Position;

                for (var i = 0UL; i < (ulong)length; i++) {
                    Seek (dictStart + i * trailer.ObjectRefSize);
                    var keyRef = ReadSizedInt (trailer.ObjectRefSize);

                    Seek (dictStart + i * trailer.ObjectRefSize + (ulong)length * trailer.ObjectRefSize);
                    var valueRef = ReadSizedInt (trailer.ObjectRefSize);

                    dict.Add ((string)ParseObject (keyRef), ParseObject (valueRef));
                }

                return dict;
            }

            Fatal ("Unhandled object kind: {0}", kind);
            return null;
        }