protected PlistObjectBase ReadValue(ContentReader input) { var type = (ValueType)input.ReadByte(); switch (type) { case ValueType.Array: var count = input.ReadInt32(); var array = new PlistArray(count); for (int i = 0; i < count; i++) { array.Add(ReadValue(input)); } return(array); case ValueType.Bool: return(new PlistBoolean(input.ReadBoolean())); case ValueType.Data: count = input.ReadInt32(); return(new PlistData(input.ReadBytes(count))); case ValueType.Date: return(new PlistDate(input.ReadObject <DateTime>())); case ValueType.Dictionary: count = input.ReadInt32(); var dict = new PlistDictionary(); for (int i = 0; i < count; i++) { string key = stringPool[input.ReadInt32()]; dict.Add(key, ReadValue(input)); } return(dict); case ValueType.Integer: return(new PlistInteger(input.ReadInt32())); case ValueType.Null: return(new PlistNull()); case ValueType.Real: return(new PlistReal(input.ReadSingle())); case ValueType.String: return(new PlistString(stringPool[input.ReadInt32()])); default: throw new InvalidOperationException(); } }
PlistArray ParseBinaryArray(int objRef) { var buffer = new PlistArray(); List <int> refs = new List <int>(); int refCount = 0; byte arrayByte = objectTable[offsetTable[objRef]]; int refStartPosition; refCount = GetCount(offsetTable[objRef], out refStartPosition); if (refCount < 15) { refStartPosition = offsetTable[objRef] + 1; } else { //The following integer has a header as well so we increase the refStartPosition by two to account for that. refStartPosition = offsetTable[objRef] + 2 + RegulateNullBytes(BitConverter.GetBytes(refCount), 1).Length; } for (int i = refStartPosition; i < refStartPosition + refCount * objRefSize; i += objRefSize) { byte[] refBuffer = objectTable.GetRange(i, objRefSize).ToArray(); Array.Reverse(refBuffer); refs.Add(BitConverter.ToInt32(RegulateNullBytes(refBuffer, 4), 0)); } for (int i = 0; i < refCount; i++) { buffer.Add(ParseBinary(refs[i])); } return(buffer); }
PlistObjectBase LoadFromNode(XmlReader reader) { Debug.Assert(reader.NodeType == XmlNodeType.Element); bool isEmpty = reader.IsEmptyElement; switch (reader.LocalName) { case "dict": var dict = new PlistDictionary(true); if (!isEmpty) { if (reader.ReadToDescendant("key")) { dict = LoadDictionaryContents(reader, dict); } reader.ReadEndElement(); } return(dict); case "array": if (isEmpty) { return(new PlistArray()); } //advance to first node reader.ReadStartElement(); while (reader.Read() && reader.NodeType != XmlNodeType.Element) { ; } // HACK: plist data in iPods is not even valid in some cases! Way to go Apple! // This hack checks to see if they really meant for this array to be a dict. if (reader.LocalName == "key") { var ret = LoadDictionaryContents(reader, new PlistDictionary(true)); reader.ReadEndElement(); return(ret); } var arr = new PlistArray(); do { if (reader.NodeType == XmlNodeType.Element) { var val = LoadFromNode(reader); if (val != null) { arr.Add(val); } } } while (reader.Read() && reader.NodeType != XmlNodeType.EndElement); reader.ReadEndElement(); return(arr); case "string": return(new PlistString(reader.ReadElementContentAsString())); case "integer": return(new PlistInteger(reader.ReadElementContentAsInt())); case "real": return(new PlistReal(reader.ReadElementContentAsFloat())); case "false": reader.ReadStartElement(); if (!isEmpty) { reader.ReadEndElement(); } return(new PlistBoolean(false)); case "true": reader.ReadStartElement(); if (!isEmpty) { reader.ReadEndElement(); } return(new PlistBoolean(true)); case "data": return(new PlistData(reader.ReadElementContentAsString())); case "date": #if NETFX_CORE return(new PlistDate(DateTime.Parse(reader.ReadElementContentAsString()))); #else return(new PlistDate(reader.ReadElementContentAsDateTime())); #endif default: throw new XmlException(String.Format("Plist Node `{0}' is not supported", reader.LocalName)); } }