Example #1
0
        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"));
        }
Example #2
0
        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());
        }
Example #3
0
        public void AddAndContainsObjectTest()
        {
            NSArray array = new NSArray();
            array.Add(1);

            Assert.IsTrue(array.Contains(1));
            Assert.IsFalse(array.Contains(2));
        }
Example #4
0
        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());
        }
Example #5
0
        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);
        }
Example #6
0
        /// <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);
        }
Example #7
0
        /// <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);
        }
Example #8
0
        /// <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);
        }
Example #9
0
        /// <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));
        }
Example #10
0
        /// <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;
        }
Example #13
0
        /// <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));
        }
Example #14
0
 /// <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);
        }