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;
}