Example #1
0
        // n = {4, 8}
        public static double ReadNBytesReal(byte[] bytes, int n, ulong at)
        {
            switch (n)
            {
            case 4:
                var f32 = new Float32Bits(bytes, at);
                return(f32.Value);

            case 8:
                var f64 = new Float64Bits(bytes, at);
                return(f64.Value);

            default:
                throw new PlistException("undefined byte size");
            }
        }
Example #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);
        }