/// <summary> /// Finds out the minimum binary property list format version that /// can be used to save the given NSObject tree. /// </summary> /// <returns>Version code</returns> /// <param name="root">Object root.</param> static int GetMinimumRequiredVersion(NSObject root) { int minVersion = VERSION_00; if (root == null) { minVersion = VERSION_10; } if (root is NSDictionary) { NSDictionary dict = (NSDictionary)root; foreach (NSObject o in dict.GetDictionary().Values) { int v = GetMinimumRequiredVersion(o); if (v > minVersion) minVersion = v; } } else if (root is NSArray) { NSArray array = (NSArray)root; foreach (NSObject o in array.GetArray()) { int v = GetMinimumRequiredVersion(o); if (v > minVersion) minVersion = v; } } else if (root is NSSet) { //Sets are only allowed in property lists v1+ minVersion = VERSION_10; NSSet set = (NSSet)root; foreach (NSObject o in set.AllObjects()) { int v = GetMinimumRequiredVersion(o); if (v > minVersion) minVersion = v; } } return minVersion; }
/// <summary> /// Saves a property list with the given object as root in binary format into an output stream. /// </summary> /// <param name="root">The root object.</param> /// <param name="outStream">The output stream.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsBinary(NSObject root, Stream outStream) { BinaryPropertyListWriter.Write(outStream, root); }
/// <summary> /// Saves a property list with the given object as root in XML format into an output stream. /// </summary> /// <param name="root">The root object.</param> /// <param name="outStream">The output stream.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsXml(NSObject root, Stream outStream) { #if NET40 // The StreamWriter constructor which takes a "leaveOpen" parameter is // not available on .NET 4.0 StreamWriter w = new StreamWriter(outStream, Encoding.UTF8); w.Write(root.ToXmlPropertyList()); w.Close(); #else using (StreamWriter w = new StreamWriter(outStream, Encoding.UTF8, bufferSize: 1024, leaveOpen: true)) { w.Write(root.ToXmlPropertyList()); } #endif }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSNumber"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSNumber"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSNumber"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSNumber)) return false; if (((NSNumber)obj).GetNSNumberType() != type) return false; switch (type) { case INTEGER: return (longValue == ((NSNumber)obj).ToLong()); case REAL: return (doubleValue == ((NSNumber)obj).ToDouble()); case BOOLEAN: return (boolValue == ((NSNumber)obj).ToBool()); default: return false; } }
internal static bool ArrayEquals(NSObject[] arrayA, NSObject[] arrayB) { if (arrayA.Length == arrayB.Length) { for (int i = 0; i < arrayA.Length; i++) { if (arrayA[i] != arrayB[i]) { return false; } } return true; } return false; }
void Write(NSObject root) { // magic bytes Write(new[] { (byte)'b', (byte)'p', (byte)'l', (byte)'i', (byte)'s', (byte)'t' }); //version switch (version) { case VERSION_00: { Write(new[] { (byte)'0', (byte)'0' }); break; } case VERSION_10: { Write(new[] { (byte)'1', (byte)'0' }); break; } case VERSION_15: { Write(new[] { (byte)'1', (byte)'5' }); break; } case VERSION_20: { Write(new[] { (byte)'2', (byte)'0' }); break; } } // assign IDs to all the objects. root.AssignIDs(this); idSizeInBytes = ComputeIdSizeInBytes(idMap.Count); // offsets of each object, indexed by ID long[] offsets = new long[idMap.Count]; // write each object, save offset for (int i = 0; i < idMap.Count; i++) { NSObject obj = idMap[i]; int id = i; offsets[id] = count; if (obj == null) { Write(0x00); } else { obj.ToBinary(this); } } // write offset table long offsetTableOffset = count; int offsetSizeInBytes = ComputeOffsetSizeInBytes(count); foreach (long offset in offsets) { WriteBytes(offset, offsetSizeInBytes); } if (version != VERSION_15) { // write trailer // 6 null bytes Write(new byte[6]); // size of an offset Write(offsetSizeInBytes); // size of a ref Write(idSizeInBytes); // number of objects WriteLong(idMap.Count); // top object int rootID = idMap.IndexOf(root); WriteLong(rootID); // offset table offset WriteLong(offsetTableOffset); } outStream.Flush(); }
internal void AssignID(NSObject obj) { if (obj is UID || obj is NSArray) { idMap.Add(obj); } else if (!idMap.Contains(obj)) { idMap.Add(obj); } }
/// <summary> /// Writes a binary plist serialization of the given object as the root. /// </summary> /// <param name="outStream">the stream to write to</param> /// <param name="root">the source of the data to write to the stream</param> /// <exception cref="IOException"></exception> public static void Write(Stream outStream, NSObject root) { int minVersion = GetMinimumRequiredVersion(root); if (minVersion > VERSION_00) { string versionString = ((minVersion == VERSION_10) ? "v1.0" : ((minVersion == VERSION_15) ? "v1.5" : ((minVersion == VERSION_20) ? "v2.0" : "v0.0"))); throw new IOException("The given property list structure cannot be saved. " + "The required version of the binary format (" + versionString + ") is not yet supported."); } BinaryPropertyListWriter w = new BinaryPropertyListWriter(outStream, minVersion); w.Write(root); }
/// <summary> /// Adds an object to the set. /// </summary> /// <param name="obj">The object to add.</param> public void AddObject(NSObject obj) { lock (set) { set.Add(obj); if (ordered) set.Sort(); } }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSSet"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSSet"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSSet"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSSet)) return false; if (set.Count != ((NSSet)obj).Count) return false; foreach (NSObject objS in (NSSet)obj) if (!set.Contains(objS)) return false; return true; }
/// <summary> /// Determines whether the set contains an object equal to a given object /// and returns that object if it is present. /// </summary> /// <param name="obj">The object to look for.</param> /// <returns>The object if it is present, <c>null</c> otherwise.</returns> public NSObject Member(NSObject obj) { lock (set) { foreach (NSObject o in set) { if (o.Equals(obj)) return o; } return null; } }
/// <summary> /// Finds out whether a given object is contained in the set. /// </summary> /// <returns><c>true</c>, when the object was found, <c>false</c> otherwise.</returns> /// <param name="obj">The object to look for.</param> public bool ContainsObject(NSObject obj) { return set.Contains(obj); }
/// <summary> /// Removes an object from the set. /// </summary> /// <param name="obj">The object to remove.</param> public void RemoveObject(NSObject obj) { lock (set) { set.Remove(obj); if (ordered) set.Sort(); } }
public void Write(NSObject root) { // magic bytes Write(new[] { (byte)'b', (byte)'p', (byte)'l', (byte)'i', (byte)'s', (byte)'t' }); //version switch (version) { case VERSION_00: { Write(new[] { (byte)'0', (byte)'0' }); break; } case VERSION_10: { Write(new[] { (byte)'1', (byte)'0' }); break; } case VERSION_15: { Write(new[] { (byte)'1', (byte)'5' }); break; } case VERSION_20: { Write(new[] { (byte)'2', (byte)'0' }); break; } } // assign IDs to all the objects. root.AssignIDs(this); idSizeInBytes = ComputeIdSizeInBytes(idMap.Count); // offsets of each object, indexed by ID long[] offsets = new long[idMap.Count]; // write each object, save offset for (int i = 0; i < idMap.Count; i++) { NSObject obj = idMap[i]; int id = i; offsets[id] = count; if (obj == null) { Write(0x00); } else { obj.ToBinary(this); } } // write offset table long offsetTableOffset = count; int offsetSizeInBytes = ComputeOffsetSizeInBytes(count); foreach (long offset in offsets) { WriteBytes(offset, offsetSizeInBytes); } if (version != VERSION_15) { // write trailer // 6 null bytes Write(new byte[6]); // size of an offset Write(offsetSizeInBytes); // size of a ref Write(idSizeInBytes); // number of objects WriteLong(idMap.Count); // top object int rootID = idMap.IndexOf(root); WriteLong(rootID); // offset table offset WriteLong(offsetTableOffset); } outStream.Flush(); }
/// <summary> /// Writes a binary plist serialization of the given object as the root /// into a byte array. /// </summary> /// <returns>The byte array containing the serialized property list</returns> /// <param name="root">The root object of the property list</param> /// <exception cref="IOException"></exception> public static byte[] WriteToArray(NSObject root) { MemoryStream bout = new MemoryStream(); Write(bout, root); return bout.ToArray(); }
/// <summary> /// Writes a binary plist file with the given object as the root. /// </summary> /// <param name="file">the file to write to</param> /// <param name="root">the source of the data to write to the file</param> /// <exception cref="IOException"></exception> public static void Write(FileInfo file, NSObject root) { FileStream fous = file.OpenWrite(); Write(fous, root); fous.Close(); }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSDate"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSDate"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSDate"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSDate)) return false; int equality = DateTime.Compare(date, ((NSDate)obj).Date); return equality == 0; }
/// <summary> /// Saves a property list with the given object as root into a XML file. /// </summary> /// <param name="root">The root object.</param> /// <param name="outFile">The output file.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsXml(NSObject root, FileInfo outFile) { string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); Stream fous = outFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); SaveAsXml(root, fous); fous.Close(); }
internal int GetID(NSObject obj) { if (obj is UID) { var uid = obj as UID; var first = idMap.OfType<UID>().First(v => NSObject.ArrayEquals(v.Bytes, uid.Bytes)); return idMap.IndexOf(first); } else if (obj is NSArray) { int index = 0; for (int i = 0; i < idMap.Count; i++) { if (idMap[i] == obj) { index = i; break; } } return index; } else { return idMap.IndexOf(obj); } }
/// <summary> /// Saves a property list with the given object as root in XML format into an output stream. /// </summary> /// <param name="root">The root object.</param> /// <param name="outStream">The output stream.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsXml(NSObject root, Stream outStream) { StreamWriter w = new StreamWriter(outStream, Encoding.UTF8); w.Write(root.ToXmlPropertyList()); w.Close(); }
/// <summary> /// Determines if the specific NSObject is the same as the NSObject overriding this method. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSObject"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSObject"/>; otherwise, <c>false</c>.</returns> public abstract bool Equals(NSObject obj);
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSArray"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSArray"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSArray"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSArray)) return false; if (array.Length != ((NSArray)obj).array.Length) return false; for (int i = 0; i < array.Length; i++) if (!array[i].Equals(((NSArray)obj).ObjectAtIndex(i))) return false; return true; }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSString"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSString"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSString"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSString)) return false; return content == ((NSString)obj).content; }
/// <summary> /// Returns a new array containing only the values stored at the given /// indices. The values are sorted by their index. /// </summary> /// <returns>The new array containing the objects stored at the given indices.</returns> /// <param name="indexes">The indices of the objects.</param> public NSObject[] ObjectsAtIndexes(params int[] indexes) { NSObject[] result = new NSObject[indexes.Length]; Array.Sort(indexes); for (int i = 0; i < indexes.Length; i++) result[i] = array[indexes[i]]; return result; }
/// <summary> /// Saves a property list with the given object as root into a XML file. /// </summary> /// <param name="root">The root object.</param> /// <param name="outFile">The output file.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsXml(NSObject root, FileInfo outFile) { string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); // Use Create here -- to make sure that when the updated file is shorter than // the original file, no "obsolete" data is left at the end. using (Stream fous = outFile.Open(FileMode.Create, FileAccess.ReadWrite)) { SaveAsXml(root, fous); } }
/// <summary> /// Remove the i-th element from the array. /// The array will be resized. /// </summary> /// <param name="i">The index of the object</param> public void Remove(int i) { if ((i >= array.Length) || (i < 0)) throw new IndexOutOfRangeException("invalid index:" + i + ";the array length is " + array.Length); NSObject[] newArray = new NSObject[array.Length - 1]; Array.Copy(array, 0, newArray, 0, i); Array.Copy(array, i + 1, newArray, i, array.Length - i - 1); array = newArray; }
/// <summary> /// Saves a property list with the given object as root into a binary file. /// </summary> /// <param name="root">The root object.</param> /// <param name="outFile">The output file.</param> /// <exception cref="IOException">When an error occurs during the writing process.</exception> public static void SaveAsBinary(NSObject root, FileInfo outFile) { string parent = outFile.DirectoryName; if (!Directory.Exists(parent)) Directory.CreateDirectory(parent); BinaryPropertyListWriter.Write(outFile, root); }
/// <summary> /// Writes a binary plist file with the given object as the root. /// </summary> /// <param name="file">the file to write to</param> /// <param name="root">the source of the data to write to the file</param> /// <exception cref="IOException"></exception> public static void Write(FileInfo file, NSObject root) { using (FileStream fous = file.OpenWrite()) { Write(fous, root); } }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.NSData"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.NSData"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.NSData"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is NSData)) return false; return ArrayEquals(bytes, ((NSData)obj).Bytes); }
/// <summary> /// Determines whether the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current <see cref="Claunia.PropertyList.UID"/>. /// </summary> /// <param name="obj">The <see cref="Claunia.PropertyList.NSObject"/> to compare with the current <see cref="Claunia.PropertyList.UID"/>.</param> /// <returns><c>true</c> if the specified <see cref="Claunia.PropertyList.NSObject"/> is equal to the current /// <see cref="Claunia.PropertyList.UID"/>; otherwise, <c>false</c>.</returns> public override bool Equals(NSObject obj) { if (!(obj is UID)) return false; if (((UID)obj).Name != name) return false; return ArrayEquals(((UID)obj).Bytes, bytes); }