public void IndexOfTest() { NSArray array = new NSArray(); array.Add(1); array.Add("test"); Assert.AreEqual(0, array.IndexOf(1)); Assert.AreEqual(1, array.IndexOf("test")); }
public void InsertTest() { NSArray array = new NSArray(); array.Add(0); array.Add(1); array.Add(2); array.Insert(1, "test"); Assert.AreEqual(4, array.Count); Assert.AreEqual("test", array.ObjectAtIndex(1).ToObject()); }
public void AddAndContainsObjectTest() { NSArray array = new NSArray(); array.Add(1); Assert.IsTrue(array.Contains(1)); Assert.IsFalse(array.Contains(2)); }
public void EnumeratorTest() { NSArray array = new NSArray(); array.Add(0); array.Add(1); var enumerator = array.GetEnumerator(); Assert.IsNull(enumerator.Current); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(new NSNumber(0), enumerator.Current); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(new NSNumber(1), enumerator.Current); Assert.IsFalse(enumerator.MoveNext()); }
public void RemoveTest() { NSArray array = new NSArray(); array.Add(0); Assert.IsFalse(array.Remove((object)1)); Assert.IsTrue(array.Remove((object)0)); Assert.AreEqual(0, array.Count); }
/// <summary> /// Parses a node in the XML structure and returns the corresponding NSObject /// </summary> /// <returns>The corresponding NSObject.</returns> /// <param name="n">The XML node.</param> static NSObject ParseObject(XmlNode n) { if (n.Name.Equals("dict")) { NSDictionary dict = new NSDictionary(); List <XmlNode> children = FilterElementNodes(n.ChildNodes); for (int i = 0; i < children.Count; i += 2) { XmlNode key = children[i]; XmlNode val = children[i + 1]; string keyString = GetNodeTextContents(key); dict.Add(keyString, ParseObject(val)); } return(dict); } if (n.Name.Equals("array")) { List <XmlNode> children = FilterElementNodes(n.ChildNodes); NSArray array = new NSArray(children.Count); for (int i = 0; i < children.Count; i++) { array.Add(ParseObject(children[i])); } return(array); } if (n.Name.Equals("true")) { return(new NSNumber(true)); } if (n.Name.Equals("false")) { return(new NSNumber(false)); } if (n.Name.Equals("integer")) { return(new NSNumber(GetNodeTextContents(n), NSNumber.INTEGER)); } if (n.Name.Equals("real")) { return(new NSNumber(GetNodeTextContents(n), NSNumber.REAL)); } if (n.Name.Equals("string")) { return(new NSString(GetNodeTextContents(n))); } if (n.Name.Equals("data")) { return(new NSData(GetNodeTextContents(n))); } return(n.Name.Equals("date") ? new NSDate(GetNodeTextContents(n)) : null); }
/// <summary> /// Creates a NSArray with the contents of the given array. /// </summary> /// <param name="value">The value to represent as a NSObject.</param> /// <returns>A NSObject representing the given value.</returns> /// <exception cref="SystemException">When one of the objects contained in the array cannot be represented by a NSObject.</exception> public static NSArray Wrap(object[] value) { NSArray arr = new NSArray(value.Length); for (int i = 0; i < value.Length; i++) { arr.Add(Wrap(value[i])); } return(arr); }
/// <summary> /// Parses a node in the XML structure and returns the corresponding NSObject /// </summary> /// <returns>The corresponding NSObject.</returns> /// <param name="n">The XML node.</param> static NSObject ParseObject(XElement n, XmlOriginFactory originFactory) { var xmlOrigin = originFactory.GetOrigin(n); if (n.Name.LocalName.Equals("dict")) { NSDictionary dict = new NSDictionary(xmlOrigin); List <XElement> children = n.Elements().ToList(); for (int i = 0; i < children.Count; i += 2) { XElement key = children[i]; XElement val = children[i + 1]; string keyString = GetNodeTextContents(key); dict.Add(keyString, ParseObject(val, originFactory)); } return(dict); } if (n.Name.LocalName.Equals("array")) { List <XElement> children = n.Elements().ToList(); NSArray array = new NSArray(children.Count, xmlOrigin); for (int i = 0; i < children.Count; i++) { array.Add(ParseObject(children[i], originFactory)); } return(array); } if (n.Name.LocalName.Equals("true")) { return(new NSNumber(true, xmlOrigin)); } if (n.Name.LocalName.Equals("false")) { return(new NSNumber(false, xmlOrigin)); } if (n.Name.LocalName.Equals("integer")) { return(new NSNumber(GetNodeTextContents(n), NumberType.Integer, xmlOrigin)); } if (n.Name.LocalName.Equals("real")) { return(new NSNumber(GetNodeTextContents(n), NumberType.Real, xmlOrigin)); } if (n.Name.LocalName.Equals("string")) { return(new NSString(GetNodeTextContents(n), xmlOrigin)); } if (n.Name.LocalName.Equals("data")) { return(new NSData(GetNodeTextContents(n), xmlOrigin)); } return(n.Name.LocalName.Equals("date") ? new NSDate(GetNodeTextContents(n), xmlOrigin) : null); }
/// <summary> /// <para> /// Creates a NSObject representing the given .NET Object. /// </para> /// <para> /// Numerics of type <see cref="bool" />, <see cref="int" />, <see cref="long" />, <see cref="short" />, /// <see cref="byte" />, <see cref="float" /> or <see cref="double" /> are wrapped as NSNumber objects. /// </para> /// <para> /// Strings are wrapped as <see cref="NSString" /> objects and byte arrays as <see cref="NSData" /> objects. /// </para> /// <para> /// DateTime objects are wrapped as <see cref="NSDate" /> objects. /// </para> /// <para> /// Serializable classes are serialized and their data is stored in <see cref="NSData" /> objects. /// </para> /// <para> /// Arrays and Collection objects are converted to <see cref="NSArray" /> where each array member is wrapped into a /// <see cref="NSObject" />. /// </para> /// <para> /// Dictionaries are converted to <see cref="NSDictionary" />. Each key is converted to a string and each value /// wrapped into a <see cref="NSObject" />. /// </para> /// </summary> /// <param name="o">The object to represent.</param> /// <returns>A NSObject equivalent to the given object.</returns> public static NSObject Wrap(object o) { if (o == null) { throw new NullReferenceException("A null object cannot be wrapped as a NSObject"); } if (o is NSObject) { return((NSObject)o); } Type c = o.GetType(); if (typeof(bool).Equals(c)) { return(Wrap((bool)o)); } if (typeof(byte).Equals(c)) { return(Wrap((byte)o)); } if (typeof(short).Equals(c)) { return(Wrap((short)o)); } if (typeof(int).Equals(c)) { return(Wrap((int)o)); } if (typeof(long).IsAssignableFrom(c)) { return(Wrap((long)o)); } if (typeof(float).Equals(c)) { return(Wrap((float)o)); } if (typeof(double).IsAssignableFrom(c)) { return(Wrap((double)o)); } if (typeof(string).Equals(c)) { return(new NSString((string)o)); } if (typeof(DateTime).Equals(c)) { return(new NSDate((DateTime)o)); } if (c.IsArray) { Type cc = c.GetElementType(); if (cc.Equals(typeof(byte))) { return(Wrap((byte[])o)); } if (cc.Equals(typeof(bool))) { bool[] array = (bool[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } if (cc.Equals(typeof(float))) { float[] array = (float[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } if (cc.Equals(typeof(double))) { double[] array = (double[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } if (cc.Equals(typeof(short))) { short[] array = (short[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } if (cc.Equals(typeof(int))) { int[] array = (int[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } if (cc.Equals(typeof(long))) { long[] array = (long[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) { nsa.Add(Wrap(array[i])); } return(nsa); } return(Wrap((object[])o)); } if (typeof(Dictionary <string, object>).IsAssignableFrom(c)) { Dictionary <string, object> netDict = (Dictionary <string, object>)o; NSDictionary dict = new NSDictionary(); foreach (KeyValuePair <string, object> kvp in netDict) { dict.Add(kvp.Key, Wrap(kvp.Value)); } return(dict); } if (typeof(List <object>).IsAssignableFrom(c)) { return(Wrap(((List <object>)o).ToArray())); } throw new PropertyListException(string.Format("Cannot wrap an object of type {0}.", o.GetType().Name)); }
/// <summary> /// Parses an object inside the currently parsed binary property list. /// For the format specification check /// <a href="http://www.opensource.apple.com/source/CF/CF-855.17/CFBinaryPList.c"> /// Apple's binary property list parser implementation /// </a> /// . /// </summary> /// <returns>The parsed object.</returns> /// <param name="obj">The object ID.</param> /// <exception cref="PropertyListFormatException">When the property list's format could not be parsed.</exception> protected virtual NSObject ParseObject(ReadOnlySpan <byte> bytes, int obj) { int offset = offsetTable[obj]; byte type = bytes[offset]; int objType = (type & 0xF0) >> 4; //First 4 bits int objInfo = type & 0x0F; //Second 4 bits switch (objType) { case 0x0: { //Simple switch (objInfo) { case 0x0: { //null object (v1.0 and later) return(null); } case 0x8: { //false return(new NSNumber(false)); } case 0x9: { //true return(new NSNumber(true)); } case 0xC: { //URL with no base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xD: { //URL with base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xE: { //16-byte UUID (v1.0 and later) //TODO Implement binary UUID parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xF: { //filler byte return(null); } } break; } case 0x1: { //integer int length = 1 << objInfo; return(new NSNumber(bytes.Slice(offset + 1, length), NSNumber.INTEGER)); } case 0x2: { //real int length = 1 << objInfo; return(new NSNumber(bytes.Slice(offset + 1, length), NSNumber.REAL)); } case 0x3: { //Date if (objInfo != 0x3) { throw new PropertyListFormatException("The given binary property list contains a date object of an unknown type (" + objInfo + ")"); } return(new NSDate(bytes.Slice(offset + 1, 8))); } case 0x4: { //Data ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int dataoffset); return(new NSData(CopyOfRange(bytes, offset + dataoffset, offset + dataoffset + length))); } case 0x5: { //ASCII String, each character is 1 byte ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int stroffset); return(new NSString(bytes.Slice(offset + stroffset, length), Encoding.ASCII)); } case 0x6: { //UTF-16-BE String ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int stroffset); //UTF-16 characters can have variable length, but the Core Foundation reference implementation //assumes 2 byte characters, thus only covering the Basic Multilingual Plane length *= 2; return(new NSString(bytes.Slice(offset + stroffset, length), utf16BigEndian)); } case 0x7: { //UTF-8 string (v1.0 and later) ReadLengthAndOffset(bytes, objInfo, offset, out int strOffset, out int characters); //UTF-8 characters can have variable length, so we need to calculate the byte length dynamically //by reading the UTF-8 characters one by one int length = CalculateUtf8StringLength(bytes, offset + strOffset, characters); return(new NSString(bytes.Slice(offset + strOffset, length), Encoding.UTF8)); } case 0x8: { //UID (v1.0 and later) int length = objInfo + 1; return(new UID(bytes.Slice(offset + 1, length))); } case 0xA: { //Array ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int arrayOffset); NSArray array = new NSArray(length); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(bytes.Slice(offset + arrayOffset + i * objectRefSize, objectRefSize)); array.Add(ParseObject(bytes, objRef)); } return(array); } case 0xB: { //Ordered set (v1.0 and later) ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int contentOffset); NSSet set = new NSSet(true); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(bytes.Slice(offset + contentOffset + i * objectRefSize, objectRefSize)); set.AddObject(ParseObject(bytes, objRef)); } return(set); } case 0xC: { //Set (v1.0 and later) ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int contentOffset); NSSet set = new NSSet(); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(bytes.Slice(offset + contentOffset + i * objectRefSize, objectRefSize)); set.AddObject(ParseObject(bytes, objRef)); } return(set); } case 0xD: { //Dictionary ReadLengthAndOffset(bytes, objInfo, offset, out int length, out int contentOffset); //System.out.println("Parsing dictionary #"+obj); NSDictionary dict = new NSDictionary(length); for (int i = 0; i < length; i++) { int keyRef = (int)ParseUnsignedInt(bytes.Slice(offset + contentOffset + i * objectRefSize, objectRefSize)); int valRef = (int) ParseUnsignedInt(bytes.Slice(offset + contentOffset + length * objectRefSize + i * objectRefSize, objectRefSize)); NSObject key = ParseObject(bytes, keyRef); NSObject val = ParseObject(bytes, valRef); dict.Add(key.ToString(), val); } return(dict); } default: { Debug.WriteLine("WARNING: The given binary property list contains an object of unknown type (" + objType + ")"); break; } } return(null); }
/// <summary> /// Parses a node in the XML structure and returns the corresponding NSObject /// </summary> /// <returns>The corresponding NSObject.</returns> /// <param name="n">The XML node.</param> static NSObject ParseObject(XmlNode n) { if (n.Name.Equals("dict")) { NSDictionary dict = new NSDictionary(); List<XmlNode> children = FilterElementNodes(n.ChildNodes); for (int i = 0; i < children.Count; i += 2) { XmlNode key = children[i]; XmlNode val = children[i + 1]; string keyString = GetNodeTextContents(key); dict.Add(keyString, ParseObject(val)); } return dict; } if (n.Name.Equals("array")) { List<XmlNode> children = FilterElementNodes(n.ChildNodes); NSArray array = new NSArray(children.Count); for (int i = 0; i < children.Count; i++) { array.Add(ParseObject(children[i])); } return array; } if (n.Name.Equals("true")) return new NSNumber(true); if (n.Name.Equals("false")) return new NSNumber(false); if (n.Name.Equals("integer")) return new NSNumber(GetNodeTextContents(n), NSNumber.INTEGER); if (n.Name.Equals("real")) return new NSNumber(GetNodeTextContents(n), NSNumber.REAL); if (n.Name.Equals("string")) return new NSString(GetNodeTextContents(n)); if (n.Name.Equals("data")) return new NSData(GetNodeTextContents(n)); return n.Name.Equals("date") ? new NSDate(GetNodeTextContents(n)) : null; }
/// <summary> /// Parses an object inside the currently parsed binary property list. /// For the format specification check /// <a href="http://www.opensource.apple.com/source/CF/CF-855.17/CFBinaryPList.c"> /// Apple's binary property list parser implementation</a>. /// </summary> /// <returns>The parsed object.</returns> /// <param name="obj">The object ID.</param> /// <exception cref="PropertyListFormatException">When the property list's format could not be parsed.</exception> NSObject ParseObject(int obj) { int offset = offsetTable[obj]; byte type = bytes[offset]; int objType = (type & 0xF0) >> 4; //First 4 bits int objInfo = (type & 0x0F); //Second 4 bits switch (objType) { case 0x0: { //Simple switch (objInfo) { case 0x0: { //null object (v1.0 and later) return null; } case 0x8: { //false return new NSNumber(false); } case 0x9: { //true return new NSNumber(true); } case 0xC: { //URL with no base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xD: { //URL with base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xE: { //16-byte UUID (v1.0 and later) //TODO Implement binary UUID parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xF: { //filler byte return null; } } break; } case 0x1: { //integer int length = (int)Math.Pow(2, objInfo); return new NSNumber(CopyOfRange(bytes, offset + 1, offset + 1 + length), NSNumber.INTEGER); } case 0x2: { //real int length = (int)Math.Pow(2, objInfo); return new NSNumber(CopyOfRange(bytes, offset + 1, offset + 1 + length), NSNumber.REAL); } case 0x3: { //Date if (objInfo != 0x3) { throw new PropertyListFormatException("The given binary property list contains a date object of an unknown type (" + objInfo + ")"); } return new NSDate(CopyOfRange(bytes, offset + 1, offset + 9)); } case 0x4: { //Data int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int dataoffset = lengthAndOffset[1]; return new NSData(CopyOfRange(bytes, offset + dataoffset, offset + dataoffset + length)); } case 0x5: { //ASCII String int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; //Each character is 1 byte int stroffset = lengthAndOffset[1]; return new NSString(CopyOfRange(bytes, offset + stroffset, offset + stroffset + length), "ASCII"); } case 0x6: { //UTF-16-BE String int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int stroffset = lengthAndOffset[1]; //UTF-16 characters can have variable length, but the Core Foundation reference implementation //assumes 2 byte characters, thus only covering the Basic Multilingual Plane length *= 2; return new NSString(CopyOfRange(bytes, offset + stroffset, offset + stroffset + length), "UTF-16BE"); } case 0x7: { //UTF-8 string (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int strOffset = lengthAndOffset[1]; int characters = lengthAndOffset[0]; //UTF-8 characters can have variable length, so we need to calculate the byte length dynamically //by reading the UTF-8 characters one by one int length = CalculateUtf8StringLength(bytes, offset + strOffset, characters); return new NSString(CopyOfRange(bytes, offset + strOffset, offset + strOffset + length), "UTF-8"); } case 0x8: { //UID (v1.0 and later) int length = objInfo + 1; return new UID(obj.ToString(), CopyOfRange(bytes, offset + 1, offset + 1 + length)); } case 0xA: { //Array int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int arrayOffset = lengthAndOffset[1]; NSArray array = new NSArray(length); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + arrayOffset + i * objectRefSize, offset + arrayOffset + (i + 1) * objectRefSize)); array.Add(ParseObject(objRef)); } return array; } case 0xB: { //Ordered set (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; NSSet set = new NSSet(true); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); set.AddObject(ParseObject(objRef)); } return set; } case 0xC: { //Set (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; NSSet set = new NSSet(); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); set.AddObject(ParseObject(objRef)); } return set; } case 0xD: { //Dictionary int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; //System.out.println("Parsing dictionary #"+obj); NSDictionary dict = new NSDictionary(); for (int i = 0; i < length; i++) { int keyRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); int valRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + (length * objectRefSize) + i * objectRefSize, offset + contentOffset + (length * objectRefSize) + (i + 1) * objectRefSize)); NSObject key = ParseObject(keyRef); NSObject val = ParseObject(valRef); dict.Add(key.ToString(), val); } return dict; } default: { Console.WriteLine("WARNING: The given binary property list contains an object of unknown type (" + objType + ")"); break; } } return null; }
/// <summary> /// <para> /// Creates a NSObject representing the given .NET Object. /// </para><para> /// Numerics of type <see cref="bool"/>, <see cref="int"/>, <see cref="long"/>, <see cref="short"/>, <see cref="byte"/>, <see cref="float"/> or <see cref="double"/> are wrapped as NSNumber objects. /// </para><para> /// Strings are wrapped as <see cref="NSString"/> objects and byte arrays as <see cref="NSData"/> objects. /// </para><para> /// DateTime objects are wrapped as <see cref="NSDate"/> objects. /// </para><para> /// Serializable classes are serialized and their data is stored in <see cref="NSData"/> objects. /// </para><para> /// Arrays and Collection objects are converted to <see cref="NSArray"/> where each array member is wrapped into a <see cref="NSObject"/>. /// </para><para> /// Dictionaries are converted to <see cref="NSDictionary"/>. Each key is converted to a string and each value wrapped into a <see cref="NSObject"/>. /// </para> /// </summary> /// <param name="o">The object to represent.</param> ///<returns>A NSObject equivalent to the given object.</returns> public static NSObject Wrap(Object o) { if (o == null) throw new NullReferenceException("A null object cannot be wrapped as a NSObject"); if (o is NSObject) return (NSObject)o; Type c = o.GetType(); if (typeof(bool).Equals(c)) { return Wrap((bool)o); } if (typeof(Byte).Equals(c)) { return Wrap((int)(Byte)o); } if (typeof(short).Equals(c)) { return Wrap((int)(short)o); } if (typeof(int).Equals(c)) { return Wrap((int)(int)o); } if (typeof(long).IsAssignableFrom(c)) { return Wrap((long)o); } if (typeof(float).Equals(c)) { return Wrap((double)(float)o); } if (typeof(double).IsAssignableFrom(c)) { return Wrap((double)o); } if (typeof(string).Equals(c)) { return new NSString((string)o); } if (typeof(DateTime).Equals(c)) { return new NSDate((DateTime)o); } if (c.IsArray) { Type cc = c.GetElementType(); if (cc.Equals(typeof(byte))) { return Wrap((byte[])o); } if (cc.Equals(typeof(bool))) { bool[] array = (bool[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } if (cc.Equals(typeof(float))) { float[] array = (float[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } if (cc.Equals(typeof(double))) { double[] array = (double[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } if (cc.Equals(typeof(short))) { short[] array = (short[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } if (cc.Equals(typeof(int))) { int[] array = (int[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } if (cc.Equals(typeof(long))) { long[] array = (long[])o; NSArray nsa = new NSArray(array.Length); for (int i = 0; i < array.Length; i++) nsa.Add(Wrap(array[i])); return nsa; } return Wrap((Object[])o); } if (typeof(Dictionary<string,Object>).IsAssignableFrom(c)) { Dictionary<string,Object> netDict = (Dictionary<string,Object>)o; NSDictionary dict = new NSDictionary(); foreach (KeyValuePair<string, Object> kvp in netDict) { dict.Add(kvp.Key, Wrap(kvp.Value)); } return dict; } if (typeof(List<Object>).IsAssignableFrom(c)) return Wrap(((List<Object>)o).ToArray()); throw new PropertyListException(string.Format("Cannot wrap an object of type {0}.", o.GetType().Name)); }
/// <summary> /// Creates a NSArray with the contents of the given array. /// </summary> /// <param name="value">The value to represent as a NSObject.</param> /// <returns>A NSObject representing the given value.</returns> /// <exception cref="SystemException">When one of the objects contained in the array cannot be represented by a NSObject.</exception> public static NSArray Wrap(Object[] value) { NSArray arr = new NSArray(value.Length); for (int i = 0; i < value.Length; i++) { arr.Add(Wrap(value[i])); } return arr; }
/// <summary> /// Parses an object inside the currently parsed binary property list. /// For the format specification check /// <a href="http://www.opensource.apple.com/source/CF/CF-855.17/CFBinaryPList.c"> /// Apple's binary property list parser implementation</a>. /// </summary> /// <returns>The parsed object.</returns> /// <param name="obj">The object ID.</param> /// <exception cref="PropertyListFormatException">When the property list's format could not be parsed.</exception> NSObject ParseObject(int obj) { int offset = offsetTable[obj]; byte type = bytes[offset]; int objType = (type & 0xF0) >> 4; //First 4 bits int objInfo = (type & 0x0F); //Second 4 bits switch (objType) { case 0x0: { //Simple switch (objInfo) { case 0x0: { //null object (v1.0 and later) return(null); } case 0x8: { //false return(new NSNumber(false, new BinaryOrigin(offset, 1))); } case 0x9: { //true return(new NSNumber(true, new BinaryOrigin(offset, 1))); } case 0xC: { //URL with no base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xD: { //URL with base URL (v1.0 and later) //TODO Implement binary URL parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xE: { //16-byte UUID (v1.0 and later) //TODO Implement binary UUID parsing (not yet even implemented in Core Foundation as of revision 855.17) break; } case 0xF: { //filler byte return(null); } } break; } case 0x1: { //integer int length = (int)Math.Pow(2, objInfo); return(new NSNumber(CopyOfRange(bytes, offset + 1, offset + 1 + length), NumberType.Integer, new BinaryOrigin(offset, length))); } case 0x2: { //real int length = (int)Math.Pow(2, objInfo); return(new NSNumber(CopyOfRange(bytes, offset + 1, offset + 1 + length), NumberType.Real, new BinaryOrigin(offset, length))); } case 0x3: { //Date if (objInfo != 0x3) { throw new PropertyListFormatException("The given binary property list contains a date object of an unknown type (" + objInfo + ")"); } return(new NSDate(CopyOfRange(bytes, offset + 1, offset + 9), new BinaryOrigin(offset, 9))); } case 0x4: { //Data int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int dataoffset = lengthAndOffset[1]; return(new NSData(CopyOfRange(bytes, offset + dataoffset, offset + dataoffset + length), new BinaryOrigin(offset + dataoffset, length))); } case 0x5: { //ASCII String int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; //Each character is 1 byte int stroffset = lengthAndOffset[1]; return(new NSString(CopyOfRange(bytes, offset + stroffset, offset + stroffset + length), "ASCII", new BinaryOrigin(offset + stroffset, length))); } case 0x6: { //UTF-16-BE String int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int stroffset = lengthAndOffset[1]; //UTF-16 characters can have variable length, but the Core Foundation reference implementation //assumes 2 byte characters, thus only covering the Basic Multilingual Plane length *= 2; return(new NSString(CopyOfRange(bytes, offset + stroffset, offset + stroffset + length), "UTF-16BE", new BinaryOrigin(offset + stroffset, length))); } case 0x7: { //UTF-8 string (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int strOffset = lengthAndOffset[1]; int characters = lengthAndOffset[0]; //UTF-8 characters can have variable length, so we need to calculate the byte length dynamically //by reading the UTF-8 characters one by one int length = CalculateUtf8StringLength(bytes, offset + strOffset, characters); return(new NSString(CopyOfRange(bytes, offset + strOffset, offset + strOffset + length), "UTF-8", new BinaryOrigin(offset + strOffset, length))); } case 0x8: { //UID (v1.0 and later) int length = objInfo + 1; return(new UID(obj.ToString(), CopyOfRange(bytes, offset + 1, offset + 1 + length), new BinaryOrigin(offset + 1, length))); } case 0xA: { //Array int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int arrayOffset = lengthAndOffset[1]; NSArray array = new NSArray(length, new BinaryOrigin(offset + arrayOffset, length * objectRefSize)); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + arrayOffset + i * objectRefSize, offset + arrayOffset + (i + 1) * objectRefSize)); array.Add(ParseObject(objRef)); } return(array); } case 0xB: { //Ordered set (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; NSSet set = new NSSet(true, new BinaryOrigin(offset + contentOffset, length * objectRefSize)); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); set.AddObject(ParseObject(objRef)); } return(set); } case 0xC: { //Set (v1.0 and later) int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; NSSet set = new NSSet(new BinaryOrigin(offset + contentOffset, length * objectRefSize)); for (int i = 0; i < length; i++) { int objRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); set.AddObject(ParseObject(objRef)); } return(set); } case 0xD: { //Dictionary int[] lengthAndOffset = ReadLengthAndOffset(objInfo, offset); int length = lengthAndOffset[0]; int contentOffset = lengthAndOffset[1]; //System.out.println("Parsing dictionary #"+obj); NSDictionary dict = new NSDictionary(new BinaryOrigin(offset + contentOffset, 2 * length * objectRefSize)); for (int i = 0; i < length; i++) { int keyRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + i * objectRefSize, offset + contentOffset + (i + 1) * objectRefSize)); int valRef = (int)ParseUnsignedInt(CopyOfRange(bytes, offset + contentOffset + (length * objectRefSize) + i * objectRefSize, offset + contentOffset + (length * objectRefSize) + (i + 1) * objectRefSize)); NSObject key = ParseObject(keyRef); NSObject val = ParseObject(valRef); dict.Add(key.ToString(), val); } return(dict); } default: { Debug.WriteLine("WARNING: The given binary property list contains an object of unknown type (" + objType + ")"); break; } } return(null); }