Example #1
0
 def wrapRoot(self, root):
     if isinstance(root, bool):
         if root is True:
             return self.wrappedTrue
         else:
             return self.wrappedFalse
     elif isinstance(root, set):
         n = set()
         for value in root:
             n.add(self.wrapRoot(value))
         return HashableWrapper(n)
     elif isinstance(root, dict):
         n = {}
         for key, value in six.iteritems(root):
             n[self.wrapRoot(key)] = self.wrapRoot(value)
         return HashableWrapper(n)
     elif isinstance(root, list):
         n = []
         for value in root:
             n.append(self.wrapRoot(value))
         return HashableWrapper(n)
     elif isinstance(root, tuple):
         n = tuple([self.wrapRoot(value) for value in root])
         return HashableWrapper(n)
     else:
         return root
Example #2
0
 def writeObject(self, obj, output, setReferencePosition=False):
     """Serializes the given object to the output. Returns output.
        If setReferencePosition is True, will set the position the
        object was written.
     """
     def proc_variable_length(format, length):
         result = six.b('')
         if length > 0b1110:
             result += pack('!B', (format << 4) | 0b1111)
             result = self.writeObject(length, result)
         else:
             result += pack('!B', (format << 4) | length)
         return result
     
     if isinstance(obj, six.text_type) and obj == six.u(''):
         # The Apple Plist decoder can't decode a zero length Unicode string.
         obj = six.b('')
    
     if setReferencePosition:
         self.referencePositions[obj] = len(output)
     
     if obj is None:
         output += pack('!B', 0b00000000)
     elif isinstance(obj, BoolWrapper):
         if obj.value is False:
             output += pack('!B', 0b00001000)
         else:
             output += pack('!B', 0b00001001)
     elif isinstance(obj, Uid):
         size = self.intSize(obj)
         output += pack('!B', (0b1000 << 4) | size - 1)
         output += self.binaryInt(obj)
     elif isinstance(obj, six.integer_types):
         bytes = self.intSize(obj)
         root = math.log(bytes, 2)
         output += pack('!B', (0b0001 << 4) | int(root))
         output += self.binaryInt(obj)
     elif isinstance(obj, float):
         # just use doubles
         output += pack('!B', (0b0010 << 4) | 3)
         output += self.binaryReal(obj)
     elif isinstance(obj, datetime.datetime):
         timestamp = calendar.timegm(obj.utctimetuple())
         timestamp -= apple_reference_date_offset
         output += pack('!B', 0b00110011)
         output += pack('!d', float(timestamp))
     elif isinstance(obj, Data):
         output += proc_variable_length(0b0100, len(obj))
         output += obj
     elif isinstance(obj, six.text_type):
         bytes = obj.encode('utf_16_be')
         output += proc_variable_length(0b0110, len(bytes)//2)
         output += bytes
     elif isinstance(obj, six.binary_type):
         bytes = obj
         output += proc_variable_length(0b0101, len(bytes))
         output += bytes
     elif isinstance(obj, HashableWrapper):
         obj = obj.value
         if isinstance(obj, (set, list, tuple)):
             if isinstance(obj, set):
                 output += proc_variable_length(0b1100, len(obj))
             else:
                 output += proc_variable_length(0b1010, len(obj))
         
             objectsToWrite = []
             for objRef in obj:
                 (isNew, output) = self.writeObjectReference(objRef, output)
                 if isNew:
                     objectsToWrite.append(objRef)
             for objRef in objectsToWrite:
                 output = self.writeObject(objRef, output, setReferencePosition=True)
         elif isinstance(obj, dict):
             output += proc_variable_length(0b1101, len(obj))
             keys = []
             values = []
             objectsToWrite = []
             for key, value in six.iteritems(obj):
                 keys.append(key)
                 values.append(value)
             for key in keys:
                 (isNew, output) = self.writeObjectReference(key, output)
                 if isNew:
                     objectsToWrite.append(key)
             for value in values:
                 (isNew, output) = self.writeObjectReference(value, output)
                 if isNew:
                     objectsToWrite.append(value)
             for objRef in objectsToWrite:
                 output = self.writeObject(objRef, output, setReferencePosition=True)
     return output
Example #3
0
 def computeOffsets(self, obj, asReference=False, isRoot=False):
     def check_key(key):
         if key is None:
             raise InvalidPlistException('Dictionary keys cannot be null in plists.')
         elif isinstance(key, Data):
             raise InvalidPlistException('Data cannot be dictionary keys in plists.')
         elif not isinstance(key, (six.binary_type, six.text_type)):
             raise InvalidPlistException('Keys must be strings.')
     
     def proc_size(size):
         if size > 0b1110:
             size += self.intSize(size)
         return size
     # If this should be a reference, then we keep a record of it in the
     # uniques table.
     if asReference:
         if obj in self.computedUniques:
             return
         else:
             self.computedUniques.add(obj)
     
     if obj is None:
         self.incrementByteCount('nullBytes')
     elif isinstance(obj, BoolWrapper):
         self.incrementByteCount('boolBytes')
     elif isinstance(obj, Uid):
         size = self.intSize(obj)
         self.incrementByteCount('uidBytes', incr=1+size)
     elif isinstance(obj, six.integer_types):
         size = self.intSize(obj)
         self.incrementByteCount('intBytes', incr=1+size)
     elif isinstance(obj, (float)):
         size = self.realSize(obj)
         self.incrementByteCount('realBytes', incr=1+size)
     elif isinstance(obj, datetime.datetime):    
         self.incrementByteCount('dateBytes', incr=2)
     elif isinstance(obj, Data):
         size = proc_size(len(obj))
         self.incrementByteCount('dataBytes', incr=1+size)
     elif isinstance(obj, (six.text_type, six.binary_type)):
         size = proc_size(len(obj))
         self.incrementByteCount('stringBytes', incr=1+size)
     elif isinstance(obj, HashableWrapper):
         obj = obj.value
         if isinstance(obj, set):
             size = proc_size(len(obj))
             self.incrementByteCount('setBytes', incr=1+size)
             for value in obj:
                 self.computeOffsets(value, asReference=True)
         elif isinstance(obj, (list, tuple)):
             size = proc_size(len(obj))
             self.incrementByteCount('arrayBytes', incr=1+size)
             for value in obj:
                 asRef = True
                 self.computeOffsets(value, asReference=True)
         elif isinstance(obj, dict):
             size = proc_size(len(obj))
             self.incrementByteCount('dictBytes', incr=1+size)
             for key, value in six.iteritems(obj):
                 check_key(key)
                 self.computeOffsets(key, asReference=True)
                 self.computeOffsets(value, asReference=True)
     else:
         raise InvalidPlistException("Unknown object type.")