Exemple #1
0
 private static XElement BuildElementXML(object root)
 {
     if (root == null)
     {
         throw new PlistException("unsupported null");
     }
     else if (root is bool)
     {
         if ((bool)root)
         {
             return(new XElement("true"));
         }
         else
         {
             return(new XElement("false"));
         }
     }
     else if (root is int)
     {
         return(new XElement("integer", root.ToString()));
     }
     else if (root is double)
     {
         return(new XElement("real", root.ToString()));
     }
     else if (root is DateTime)
     {
         DateTime date = (DateTime)root;
         var      str  = date.ToUniversalTime().ToString(DateFormat, System.Globalization.CultureInfo.InvariantCulture);
         return(new XElement("date", str));
     }
     else if (root is string)
     {
         string text = root as string;
         return(new XElement("string", text));
     }
     else if (root is byte[])
     {
         byte[] data = root as byte[];
         var    str  = System.Convert.ToBase64String(data);
         return(new XElement("data", str));
     }
     else if (root is PlistList)
     {
         PlistList objectArray = root as PlistList;
         object[]  contents    = new object[objectArray.Count];
         for (int i = 0; i < objectArray.Count; ++i)
         {
             contents[i] = BuildElementXML(objectArray[i]);
         }
         return(new XElement("array", contents));
     }
     else if (root is PlistDictionary)
     {
         PlistDictionary objectDictionary = root as PlistDictionary;
         object[]        contents         = new object[objectDictionary.Count * 2];
         int             i = 0;
         foreach (var kv in objectDictionary)
         {
             contents[i++] = new XElement("key", kv.Key);
             contents[i++] = BuildElementXML(kv.Value);
         }
         return(new XElement("dict", contents));
     }
     else
     {
         throw new PlistException("undefined data type");
     }
 }
Exemple #2
0
        private static ulong WriteObjectBinary(Stream stream, object root, byte objectRefSize, byte[] encodeBuffer, ref ulong objectIndex, List <ulong> offsetTable)
        {
            ulong objectRef = objectIndex++;
            ulong objectAt  = (ulong)stream.Position;

            offsetTable.Add(objectAt);

            if (root == null)
            {
                throw new PlistException("unsupported null");
            }
            else if (root is bool)
            {
                if ((bool)root)
                {
                    stream.WriteByte(TypeBitsBoolOrNil | TrueBit);
                }
                else
                {
                    stream.WriteByte(TypeBitsBoolOrNil | FalseBit);
                }
            }
            else if (root is int)
            {
                WriteInteger((int)root, stream);
            }
            else if (root is double)
            {
                // real, 2^3 = 8 byte
                // 0010 0011
                // force use double
                byte headbyte = TypeBitsReal | 0x03;
                stream.WriteByte(headbyte);
                var f64 = new Float64Bits((double)root);
                f64.Write(stream);
            }
            else if (root is DateTime)
            {
                DateTime date        = (DateTime)root;
                TimeSpan elapsedSpan = date.ToUniversalTime() - BaseTime;
                double   elapsed     = elapsedSpan.TotalSeconds;

                byte headbyte = TypeBitsDate | 0x03;
                stream.WriteByte(headbyte);
                var f64 = new Float64Bits(elapsed);
                f64.Write(stream);
            }
            else if (root is string)
            {
                string text = root as string;

                byte typebit;
                int  count;
                int  writeBytes;
                if (IsASCIIEncodable(text))
                {
                    typebit    = TypeBitsASCIIString;
                    writeBytes = ASCII.GetBytes(text, 0, text.Length, encodeBuffer, 0);
                    count      = writeBytes;
                }
                else
                {
                    typebit    = TypeBitsUTF16String;
                    writeBytes = UTF16BE.GetBytes(text, 0, text.Length, encodeBuffer, 0);
                    count      = writeBytes >> 1;
                }

                if (count < 15)
                {
                    byte headbyte = (byte)(typebit | count);
                    stream.WriteByte(headbyte);
                }
                else
                {
                    byte headbyte = (byte)(typebit | 0x0F);
                    stream.WriteByte(headbyte);
                    WriteInteger((long)count, stream);
                }
                stream.Write(encodeBuffer, 0, writeBytes);
            }
            else if (root is byte[])
            {
                byte[] data    = root as byte[];
                byte   typebit = TypeBitsBinaryData;
                if (data.Length < 15)
                {
                    byte headbyte = (byte)(typebit | data.Length);
                    stream.WriteByte(headbyte);
                }
                else
                {
                    byte headbyte = (byte)(typebit | 0x0F);
                    stream.WriteByte(headbyte);
                    WriteInteger(data.LongLength, stream);
                }
                stream.Write(data, 0, data.Length);
            }
            else if (root is PlistList)
            {
                PlistList objectArray = root as PlistList;
                byte      typebit     = TypeBitsArray;
                if (objectArray.Count < 15)
                {
                    byte headbyte = (byte)(typebit | objectArray.Count);
                    stream.WriteByte(headbyte);
                }
                else
                {
                    byte headbyte = (byte)(typebit | 0x0F);
                    stream.WriteByte(headbyte);
                    WriteInteger(objectArray.Count, stream);
                }

                ulong arrayAt = (ulong)stream.Position;

                // reserve data
                ulong reserveBytes = (ulong)objectArray.Count * objectRefSize;
                for (ulong i = 0; i < reserveBytes; ++i)
                {
                    stream.WriteByte(0);
                }
                for (int i = 0; i < objectArray.Count; ++i)
                {
                    ulong arrayObjectRef = WriteObjectBinary(stream, objectArray[i], objectRefSize, encodeBuffer, ref objectIndex, offsetTable);
                    stream.Seek((long)arrayAt + i * objectRefSize, SeekOrigin.Begin);
                    BigEndianWriter.WriteNBytesUnsignedInteger(stream, arrayObjectRef, objectRefSize);
                    stream.Seek(0, SeekOrigin.End);
                }
            }
            else if (root is PlistDictionary)
            {
                PlistDictionary objectDictionary = root as PlistDictionary;
                byte            typebit          = TypeBitsDictionary;
                if (objectDictionary.Count < 15)
                {
                    byte headbyte = (byte)(typebit | objectDictionary.Count);
                    stream.WriteByte(headbyte);
                }
                else
                {
                    byte headbyte = (byte)(typebit | 0x0F);
                    stream.WriteByte(headbyte);
                    WriteInteger(objectDictionary.Count, stream);
                }

                ulong dictionaryAt = (ulong)stream.Position;

                // reserve data
                ulong reserveBytes = (ulong)objectDictionary.Count * 2 * objectRefSize;
                for (ulong j = 0; j < reserveBytes; ++j)
                {
                    stream.WriteByte(0);
                }

                /* key, key, key, value, value, value... */
                long keyBytes = objectRefSize * (long)objectDictionary.Count;
                int  i        = 0;
                foreach (var objectKeyValue in objectDictionary)
                {
                    ulong arrayKeyRef   = WriteObjectBinary(stream, objectKeyValue.Key, objectRefSize, encodeBuffer, ref objectIndex, offsetTable);
                    ulong arrayValueRef = WriteObjectBinary(stream, objectKeyValue.Value, objectRefSize, encodeBuffer, ref objectIndex, offsetTable);

                    stream.Seek((long)dictionaryAt + i * objectRefSize, SeekOrigin.Begin);
                    BigEndianWriter.WriteNBytesUnsignedInteger(stream, arrayKeyRef, objectRefSize);

                    stream.Seek((long)dictionaryAt + keyBytes + i * objectRefSize, SeekOrigin.Begin);
                    BigEndianWriter.WriteNBytesUnsignedInteger(stream, arrayValueRef, objectRefSize);
                    stream.Seek(0, SeekOrigin.End);

                    i++;
                }
            }
            else
            {
                throw new PlistException();
            }
            return(objectRef);
        }
Exemple #3
0
        public static bool EqualObject(object x, object y, double deltaReal, double deltaDateSeconds)
        {
            if (x.GetType() != y.GetType())
            {
                return(false);
            }

            if (x is bool || x is int || x is string)
            {
                bool eq = x.Equals(y);
                return(eq);
            }

            if (x is byte[])
            {
                byte[] xbyte = x as byte[];
                byte[] ybyte = y as byte[];
                if (xbyte.Length != ybyte.Length)
                {
                    return(false);
                }
                for (int i = 0; i < xbyte.Length; ++i)
                {
                    if (xbyte[i] != ybyte[i])
                    {
                        return(false);
                    }
                }
                return(true);
                // bool eq = (x as byte[]).SequenceEqual(y as byte[]);
                // return eq;
            }
            if (x is double)
            {
                bool eq = Math.Abs((double)x - (double)y) < deltaReal;
                return(eq);
            }
            if (x is DateTime)
            {
                var  deltaTime = (DateTime)x - (DateTime)y;
                bool eq        = Math.Abs(deltaTime.TotalSeconds) < deltaDateSeconds;
                return(eq);
            }

            if (x is PlistList)
            {
                PlistList xList = x as PlistList;
                PlistList yList = y as PlistList;
                if (xList.Count != yList.Count)
                {
                    return(false);
                }
                for (int i = 0; i < xList.Count; ++i)
                {
                    if (EqualObject(xList[i], yList[i], deltaReal, deltaDateSeconds) == false)
                    {
                        return(false);
                    }
                }
                return(true);
            }
            if (x is PlistDictionary)
            {
                PlistDictionary xDict = x as PlistDictionary;
                PlistDictionary yDict = y as PlistDictionary;
                if (xDict.Count != yDict.Count)
                {
                    return(false);
                }

                foreach (var kv in xDict)
                {
                    if (yDict.ContainsKey(kv.Key) == false)
                    {
                        return(false);
                    }
                    var yValue = yDict[kv.Key];
                    if (EqualObject(kv.Value, yValue, deltaReal, deltaDateSeconds) == false)
                    {
                        return(false);
                    }
                }
                return(true);
            }
            throw new PlistException("undefined data type");
        }
Exemple #4
0
        private static object ReadObjectBinary(byte[] bytes, ref Trailer trailer, ulong objectRef)
        {
            ulong objectAt = ReadOffset(bytes, trailer, objectRef);
            byte  headbyte = bytes[objectAt];

            int type = headbyte & 0xF0;
            int nnnn = headbyte & 0x0F;

            switch (type)
            {
            case TypeBitsBoolOrNil:      /* 0000 null, false, true*/
                switch (nnnn)
                {
                case 0x0:
                    throw new PlistException("unsupported null");

                case FalseBit:
                    return(false);

                case TrueBit:
                    return(true);

                default:
                    throw new PlistException("undefined value");
                }

            case TypeBitsInteger:      /* 0001 integer */
            {
                ulong nextAt;
                long  integer = ReadInteger(bytes, objectAt, out nextAt);
                if (integer < int.MinValue || int.MaxValue < integer)
                {
                    throw new PlistException("int overflow, we use int for simplity.");
                }
                return((int)integer);
            }

            case TypeBitsReal:      /* 0010 real */
            {
                int nnnn_bytes = TwoPowNNNN(nnnn);
                var real       = BigEndianReader.ReadNBytesReal(bytes, nnnn_bytes, objectAt + 1);
                return(real);
            }

            case TypeBitsDate:      /* 0011 date */
            {
                double   elapsed = BigEndianReader.ReadNBytesReal(bytes, 8, objectAt + 1);
                var      span    = TimeSpan.FromSeconds(elapsed);
                DateTime date    = BaseTime.Add(span).ToLocalTime();
                return(date);
            }

            case TypeBitsBinaryData:      /* 0100 data */
            {
                ulong dataLength;
                ulong dataAt;
                IntNNNNorNextInt(bytes, objectAt, nnnn, out dataLength, out dataAt);

                byte[] data = new byte[dataLength];
                Array.Copy(bytes, (long)dataAt, data, 0, (long)dataLength);
                return(data);
            }

            case TypeBitsASCIIString:      /* 0101 ascii string */
            {
                ulong asciiCount;
                ulong asciiAt;
                IntNNNNorNextInt(bytes, objectAt, nnnn, out asciiCount, out asciiAt);
                string ascii;
                if (asciiAt + asciiCount < int.MaxValue)
                {
                    ascii = System.Text.Encoding.ASCII.GetString(bytes, (int)asciiAt, (int)asciiCount);
                }
                else
                {
                    byte[] asciiBytes = new byte[asciiCount];
                    Array.Copy(bytes, (long)asciiAt, asciiBytes, 0, (long)asciiCount);
                    ascii = System.Text.Encoding.ASCII.GetString(asciiBytes, 0, (int)asciiBytes.Length);
                }
                return(ascii);
            }

            case TypeBitsUTF16String:      /* 0110 utf16 string */
            {
                ulong utf16Count;
                ulong utf16At;
                IntNNNNorNextInt(bytes, objectAt, nnnn, out utf16Count, out utf16At);
                ulong utf16byteLength = utf16Count * 2;

                string utf16;
                if (utf16At + utf16byteLength < int.MaxValue)
                {
                    utf16 = UTF16BE.GetString(bytes, (int)utf16At, (int)utf16byteLength);
                }
                else
                {
                    byte[] utf16Bytes = new byte[utf16byteLength];
                    Array.Copy(bytes, (long)utf16At, utf16Bytes, 0, (long)utf16byteLength);
                    utf16 = UTF16BE.GetString(utf16Bytes, 0, utf16Bytes.Length);
                }
                return(utf16);
            }

            case TypeBitsArray:      /* 1010 array */
            {
                ulong count;
                ulong arrayAt;
                IntNNNNorNextInt(bytes, objectAt, nnnn, out count, out arrayAt);

                int       capacity    = (int)(Math.Min(count, int.MaxValue));
                PlistList objectArray = new PlistList(capacity);
                for (ulong i = 0; i < count; ++i)
                {
                    ulong arrayObjectRef = BigEndianReader.ReadNBytesUnsignedInteger(bytes, trailer.ObjectRefSize, arrayAt + trailer.ObjectRefSize * i);
                    objectArray.Add(ReadObjectBinary(bytes, ref trailer, arrayObjectRef));
                }
                return(objectArray);
            }

            case TypeBitsDictionary:     /* 1101 dictionary */
            {
                ulong count;
                ulong dictionaryAt;
                IntNNNNorNextInt(bytes, objectAt, nnnn, out count, out dictionaryAt);
                int             capacity         = (int)(Math.Min(count, int.MaxValue));
                PlistDictionary objectDictionary = new PlistDictionary(capacity);

                /* key, key, key, value, value, value... */
                ulong keyBytes = trailer.ObjectRefSize * count;
                for (ulong i = 0; i < count; ++i)
                {
                    ulong  keyObjectRef   = BigEndianReader.ReadNBytesUnsignedInteger(bytes, trailer.ObjectRefSize, dictionaryAt + trailer.ObjectRefSize * i);
                    ulong  valueObjectRef = BigEndianReader.ReadNBytesUnsignedInteger(bytes, trailer.ObjectRefSize, dictionaryAt + keyBytes + trailer.ObjectRefSize * i);
                    string keyObject      = ReadObjectBinary(bytes, ref trailer, keyObjectRef) as string;
                    object valueObject    = ReadObjectBinary(bytes, ref trailer, valueObjectRef);
                    objectDictionary.Add(keyObject, valueObject);
                }
                return(objectDictionary);
            }

            default:
                throw new PlistException("undefined data type");
            }
        }