summaryrefslogtreecommitdiffstats
path: root/cython/plist.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'cython/plist.pyx')
-rw-r--r--cython/plist.pyx699
1 files changed, 699 insertions, 0 deletions
diff --git a/cython/plist.pyx b/cython/plist.pyx
new file mode 100644
index 0000000..a1282e7
--- /dev/null
+++ b/cython/plist.pyx
@@ -0,0 +1,699 @@
+cdef extern from *:
+ ctypedef unsigned char uint8_t
+ ctypedef short int int16_t
+ ctypedef unsigned short int uint16_t
+ ctypedef unsigned int uint32_t
+ ctypedef int int32_t
+IF UNAME_MACHINE == 'x86_64':
+ ctypedef unsigned long int uint64_t
+ELSE:
+ ctypedef unsigned long long int uint64_t
+
+cimport python_unicode
+
+cdef extern from *:
+ ctypedef enum plist_type:
+ PLIST_BOOLEAN,
+ PLIST_UINT,
+ PLIST_REAL,
+ PLIST_STRING,
+ PLIST_ARRAY,
+ PLIST_DICT,
+ PLIST_DATE,
+ PLIST_DATA,
+ PLIST_KEY,
+ PLIST_NONE
+
+ plist_t plist_new_bool(uint8_t val)
+ void plist_get_bool_val(plist_t node, uint8_t *val)
+ void plist_set_bool_val(plist_t node, uint8_t val)
+
+ plist_t plist_new_uint(uint64_t val)
+ void plist_get_uint_val(plist_t node, uint64_t *val)
+ void plist_set_uint_val(plist_t node, uint64_t val)
+
+ plist_t plist_new_real(double val)
+ void plist_get_real_val(plist_t node, double *val)
+ void plist_set_real_val(plist_t node, double val)
+
+ plist_t plist_new_date(int32_t sec, int32_t usec)
+ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec)
+ void plist_set_date_val(plist_t node, int32_t sec, int32_t usec)
+
+ plist_t plist_new_string(char *val)
+ void plist_get_string_val(plist_t node, char **val)
+ void plist_set_string_val(plist_t node, char *val)
+
+ plist_t plist_new_data(char *val, uint64_t length)
+ void plist_get_data_val(plist_t node, char **val, uint64_t * length)
+ void plist_set_data_val(plist_t node, char *val, uint64_t length)
+
+ plist_t plist_new_dict()
+ int plist_dict_get_size(plist_t node)
+ plist_t plist_dict_get_item(plist_t node, char* key)
+ void plist_dict_set_item(plist_t node, char* key, plist_t item)
+ void plist_dict_insert_item(plist_t node, char* key, plist_t item)
+ void plist_dict_remove_item(plist_t node, char* key)
+
+ void plist_dict_new_iter(plist_t node, plist_dict_iter *iter)
+ void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val)
+
+ plist_t plist_new_array()
+ uint32_t plist_array_get_size(plist_t node)
+ plist_t plist_array_get_item(plist_t node, uint32_t n)
+ uint32_t plist_array_get_item_index(plist_t node)
+ void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
+ void plist_array_append_item(plist_t node, plist_t item)
+ void plist_array_insert_item(plist_t node, plist_t item, uint32_t n)
+ void plist_array_remove_item(plist_t node, uint32_t n)
+
+ void plist_free(plist_t plist)
+ plist_t plist_copy(plist_t plist)
+ void plist_to_xml(plist_t plist, char **plist_xml, uint32_t *length)
+ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t *length)
+
+ plist_t plist_get_parent(plist_t node)
+ plist_type plist_get_node_type(plist_t node)
+
+ void plist_set_type(plist_t node, plist_type type)
+
+ void plist_from_xml(char *plist_xml, uint32_t length, plist_t * plist)
+ void plist_from_bin(char *plist_bin, uint32_t length, plist_t * plist)
+
+cdef extern from *:
+ void free(void *ptr)
+
+cdef class Node:
+ def __init__(self, *args, **kwargs):
+ self._c_managed = True
+
+ def __dealloc__(self):
+ if self._c_node is not NULL and self._c_managed:
+ plist_free(self._c_node)
+
+ cpdef object __deepcopy__(self, memo={}):
+ return plist_t_to_node(plist_copy(self._c_node))
+
+ cpdef object copy(self):
+ cdef plist_t c_node = NULL
+ c_node = plist_copy(self._c_node)
+ return plist_t_to_node(c_node)
+
+ cpdef bytes to_xml(self):
+ cdef char* out = NULL
+ cdef uint32_t length
+ plist_to_xml(self._c_node, &out, &length)
+
+ return out[:length]
+
+ cpdef bytes to_bin(self):
+ cdef char* out = NULL
+ cdef uint32_t length
+ plist_to_bin(self._c_node, &out, &length)
+
+ return out[:length]
+
+ property parent:
+ def __get__(self):
+ cdef plist_t c_parent = NULL
+ cdef Node node
+
+ c_parent = plist_get_parent(self._c_node)
+ if c_parent == NULL:
+ return None
+
+ return plist_t_to_node(c_parent)
+
+ def __str__(self):
+ return str(self.get_value())
+
+cdef class Bool(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ if value is None:
+ self._c_node = plist_new_bool(0)
+ else:
+ self._c_node = plist_new_bool(bool(value))
+
+ def __nonzero__(self):
+ return self.get_value()
+
+ def __richcmp__(self, other, op):
+ cdef bool b = self.get_value()
+ if op == 0:
+ return b < other
+ if op == 1:
+ return b <= other
+ if op == 2:
+ return b == other
+ if op == 3:
+ return b != other
+ if op == 4:
+ return b > other
+ if op == 5:
+ return b >= other
+
+ def __repr__(self):
+ b = self.get_value()
+ return '<Bool: %s>' % b
+
+ cpdef set_value(self, value):
+ plist_set_bool_val(self._c_node, bool(value))
+
+ cpdef bool get_value(self):
+ cdef uint8_t value
+ plist_get_bool_val(self._c_node, &value)
+ return bool(value)
+
+cdef Bool Bool_factory(plist_t c_node, bool managed=True):
+ cdef Bool instance = Bool.__new__(Bool)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+cdef class Integer(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ if value is None:
+ self._c_node = plist_new_uint(0)
+ else:
+ self._c_node = plist_new_uint(int(value))
+
+ def __repr__(self):
+ i = self.get_value()
+ return '<Integer: %s>' % i
+
+ def __int__(self):
+ return self.get_value()
+
+ def __float__(self):
+ return float(self.get_value())
+
+ def __richcmp__(self, other, op):
+ cdef int i = self.get_value()
+ if op == 0:
+ return i < other
+ if op == 1:
+ return i <= other
+ if op == 2:
+ return i == other
+ if op == 3:
+ return i != other
+ if op == 4:
+ return i > other
+ if op == 5:
+ return i >= other
+
+ cpdef set_value(self, value):
+ plist_set_uint_val(self._c_node, int(value))
+
+ cpdef int get_value(self):
+ cdef uint64_t value
+ plist_get_uint_val(self._c_node, &value)
+ return value
+
+cdef Integer Integer_factory(plist_t c_node, bool managed=True):
+ cdef Integer instance = Integer.__new__(Integer)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+cdef class Real(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ if value is None:
+ self._c_node = plist_new_real(0.0)
+ else:
+ self._c_node = plist_new_real(float(value))
+
+ def __repr__(self):
+ r = self.get_value()
+ return '<Real: %s>' % r
+
+ def __float__(self):
+ return self.get_value()
+
+ def __int__(self):
+ return int(self.get_value())
+
+ def __richcmp__(self, other, op):
+ cdef float f = self.get_value()
+ if op == 0:
+ return f < other
+ if op == 1:
+ return f <= other
+ if op == 2:
+ return f == other
+ if op == 3:
+ return f != other
+ if op == 4:
+ return f > other
+ if op == 5:
+ return f >= other
+
+ cpdef set_value(self, value):
+ plist_set_real_val(self._c_node, float(value))
+
+ cpdef float get_value(self):
+ cdef double value
+ plist_get_real_val(self._c_node, &value)
+ return value
+
+cdef Real Real_factory(plist_t c_node, bool managed=True):
+ cdef Real instance = Real.__new__(Real)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+from python_version cimport PY_MAJOR_VERSION
+
+cdef class String(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ if value is None:
+ self._c_node = plist_new_string("")
+ else:
+ if isinstance(value, unicode):
+ utf8_data = value.encode('utf-8')
+ elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
+ value.decode('ascii')
+ utf8_data = value
+ else:
+ raise ValueError("requires text input, got %s" % type(value))
+ self._c_node = plist_new_string(utf8_data)
+
+ def __repr__(self):
+ s = self.get_value()
+ return '<String: %s>' % s
+
+ def __richcmp__(self, other, op):
+ cdef str s = self.get_value()
+ if op == 0:
+ return s < other
+ if op == 1:
+ return s <= other
+ if op == 2:
+ return s == other
+ if op == 3:
+ return s != other
+ if op == 4:
+ return s > other
+ if op == 5:
+ return s >= other
+
+ cpdef set_value(self, unicode value):
+ if value is None:
+ self._c_node = plist_new_string("")
+ else:
+ if isinstance(value, unicode):
+ utf8_data = value.encode('utf-8')
+ elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
+ value.decode('ascii')
+ utf8_data = value
+ else:
+ raise ValueError("requires text input, got %s" % type(value))
+ self._c_node = plist_new_string(utf8_data)
+
+ cpdef unicode get_value(self):
+ cdef char* value = NULL
+ plist_get_string_val(self._c_node, &value)
+ return python_unicode.PyUnicode_DecodeUTF8(value, len(value), 'strict')
+
+cdef String String_factory(plist_t c_node, bool managed=True):
+ cdef String instance = String.__new__(String)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+cdef extern from "plist_util.h":
+ void datetime_to_ints(object obj, int32_t* sec, int32_t* usec)
+ object ints_to_datetime(int32_t sec, int32_t usec)
+ int check_datetime(object obj)
+
+cdef plist_t create_date_plist(value=None):
+ cdef plist_t node = NULL
+ cdef int32_t secs
+ cdef int32_t usecs
+ if value is None:
+ node = plist_new_date(0, 0)
+ elif check_datetime(value):
+ datetime_to_ints(value, &secs, &usecs)
+ node = plist_new_date(secs, usecs)
+ return node
+
+cdef class Date(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ self._c_node = create_date_plist(value)
+
+ def __repr__(self):
+ d = self.get_value()
+ return '<Date: %s>' % d.ctime()
+
+ def __richcmp__(self, other, op):
+ d = self.get_value()
+ if op == 0:
+ return d < other
+ if op == 1:
+ return d <= other
+ if op == 2:
+ return d == other
+ if op == 3:
+ return d != other
+ if op == 4:
+ return d > other
+ if op == 5:
+ return d >= other
+
+ cpdef object get_value(self):
+ cdef int32_t secs = 0
+ cdef int32_t usecs = 0
+ cdef object result
+ plist_get_date_val(self._c_node, &secs, &usecs)
+ return ints_to_datetime(secs, usecs)
+
+ cpdef set_value(self, value):
+ cdef int32_t secs
+ cdef int32_t usecs
+ if not check_datetime(value):
+ raise ValueError("Expected a datetime")
+ datetime_to_ints(value, &secs, &usecs)
+ plist_set_date_val(self._c_node, secs, usecs)
+
+cdef Date Date_factory(plist_t c_node, bool managed=True):
+ cdef Date instance = Date.__new__(Date)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+cdef class Data(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ if value is None:
+ self._c_node = plist_new_data(NULL, 0)
+ else:
+ self._c_node = plist_new_data(value, len(value))
+
+ def __repr__(self):
+ d = self.get_value()
+ return '<Data: %s>' % d
+
+ def __richcmp__(self, other, op):
+ cdef str d = self.get_value()
+ if op == 0:
+ return d < other
+ if op == 1:
+ return d <= other
+ if op == 2:
+ return d == other
+ if op == 3:
+ return d != other
+ if op == 4:
+ return d > other
+ if op == 5:
+ return d >= other
+
+ cpdef bytes get_value(self):
+ cdef char* val = NULL
+ cdef uint64_t length = 0
+ plist_get_data_val(self._c_node, &val, &length)
+
+ return val[:length]
+
+ cpdef set_value(self, bytes value):
+ plist_set_data_val(self._c_node, value, len(value))
+
+cdef Data Data_factory(plist_t c_node, bool managed=True):
+ cdef Data instance = Data.__new__(Data)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ return instance
+
+cdef plist_t create_dict_plist(value=None):
+ cdef plist_t node = NULL
+ cdef plist_t c_node = NULL
+ node = plist_new_dict()
+ if value is not None and isinstance(value, dict):
+ for key, item in value.items():
+ c_node = native_to_plist_t(item)
+ plist_dict_insert_item(node, key, c_node)
+ c_node = NULL
+ return node
+
+cdef class Dict(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ self._c_node = create_dict_plist(value)
+
+ def __init__(self, value=None, *args, **kwargs):
+ self._init()
+
+ cdef void _init(self):
+ cdef plist_dict_iter it = NULL
+ cdef char* key = NULL
+ cdef plist_t subnode = NULL
+
+ self._map = {}
+
+ plist_dict_new_iter(self._c_node, &it);
+ plist_dict_next_item(self._c_node, it, &key, &subnode);
+
+ while subnode is not NULL:
+ self._map[key] = plist_t_to_node(subnode, False)
+ subnode = NULL
+ free(key)
+ key = NULL
+ plist_dict_next_item(self._c_node, it, &key, &subnode);
+ free(it)
+
+ def __dealloc__(self):
+ self._map = None
+ Node.__dealloc__(self)
+
+ def __richcmp__(self, other, op):
+ cdef dict d = self.get_value()
+ if op == 0:
+ return d < other
+ if op == 1:
+ return d <= other
+ if op == 2:
+ return d == other
+ if op == 3:
+ return d != other
+ if op == 4:
+ return d > other
+ if op == 5:
+ return d >= other
+
+ def __len__(self):
+ return len(self._map)
+
+ def __repr__(self):
+ return '<Dict: %s>' % self._map
+
+ cpdef dict get_value(self):
+ return dict([(key, value.get_value()) for key, value in self.items()])
+
+ cpdef set_value(self, dict value):
+ plist_free(self._c_node)
+ self._map = {}
+ self._c_node = NULL
+ self._c_node = create_dict_plist(value)
+ self._init()
+
+ def __iter__(self):
+ return self._map.__iter__()
+
+ cpdef bool has_key(self, key):
+ return self._map.has_key(key)
+
+ cpdef object get(self, key, default=None):
+ return self._map.get(key, default)
+
+ cpdef list keys(self):
+ return self._map.keys()
+
+ cpdef object iterkeys(self):
+ return self._map.iterkeys()
+
+ cpdef list items(self):
+ return self._map.items()
+
+ cpdef object iteritems(self):
+ return self._map.iteritems()
+
+ cpdef list values(self):
+ return self._map.values()
+
+ cpdef object itervalues(self):
+ return self._map.itervalues()
+
+ def __getitem__(self, key):
+ return self._map[key]
+
+ def __setitem__(self, key, value):
+ cdef Node n
+ if isinstance(value, Node):
+ n = value.copy()
+ else:
+ n = plist_t_to_node(native_to_plist_t(value), False)
+
+ plist_dict_insert_item(self._c_node, key, n._c_node)
+ self._map[key] = n
+
+ def __delitem__(self, key):
+ del self._map[key]
+ plist_dict_remove_item(self._c_node, key)
+
+cdef Dict Dict_factory(plist_t c_node, bool managed=True):
+ cdef Dict instance = Dict.__new__(Dict)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ instance._init()
+ return instance
+
+cdef plist_t create_array_plist(value=None):
+ cdef plist_t node = NULL
+ cdef plist_t c_node = NULL
+ node = plist_new_array()
+ if value is not None and (isinstance(value, list) or isinstance(value, tuple)):
+ for item in value:
+ c_node = native_to_plist_t(item)
+ plist_array_append_item(node, c_node)
+ c_node = NULL
+ return node
+
+cdef class Array(Node):
+ def __cinit__(self, value=None, *args, **kwargs):
+ self._c_node = create_array_plist(value)
+
+ def __init__(self, value=None, *args, **kwargs):
+ self._init()
+
+ cdef void _init(self):
+ cdef uint32_t size = plist_array_get_size(self._c_node)
+ cdef plist_t subnode = NULL
+
+ for i from 0 <= i < size:
+ subnode = plist_array_get_item(self._c_node, i)
+ self._array.append(plist_t_to_node(subnode, False))
+
+ def __richcmp__(self, other, op):
+ cdef list l = self.get_value()
+ if op == 0:
+ return l < other
+ if op == 1:
+ return l <= other
+ if op == 2:
+ return l == other
+ if op == 3:
+ return l != other
+ if op == 4:
+ return l > other
+ if op == 5:
+ return l >= other
+
+ def __len__(self):
+ return len(self._array)
+
+ def __repr__(self):
+ return '<Array: %s>' % self._array
+
+ cpdef list get_value(self):
+ return [i.get_value() for i in self]
+
+ cpdef set_value(self, value):
+ self._array = []
+ plist_free(self._c_node)
+ self._c_node = NULL
+ self._c_node = create_array_plist(value)
+ self._init()
+
+ def __iter__(self):
+ return self._array.__iter__()
+
+ def __getitem__(self, index):
+ return self._array[index]
+
+ def __setitem__(self, index, value):
+ cdef Node n
+ if isinstance(value, Node):
+ n = value.copy()
+ else:
+ n = plist_t_to_node(native_to_plist_t(value), False)
+
+ if index < 0:
+ index = len(self) + index
+
+ plist_array_set_item(self._c_node, n._c_node, index)
+ self._array[index] = n
+
+ def __delitem__(self, index):
+ if index < 0:
+ index = len(self) + index
+ del self._array[index]
+ plist_array_remove_item(self._c_node, index)
+
+ cpdef append(self, item):
+ cdef Node n
+
+ if isinstance(item, Node):
+ n = item.copy()
+ else:
+ n = plist_t_to_node(native_to_plist_t(item), False)
+
+ plist_array_append_item(self._c_node, n._c_node)
+ self._array.append(n)
+
+cdef Array Array_factory(plist_t c_node, bool managed=True):
+ cdef Array instance = Array.__new__(Array)
+ instance._c_managed = managed
+ instance._c_node = c_node
+ instance._init()
+ return instance
+
+cpdef object from_xml(xml):
+ cdef plist_t c_node = NULL
+ plist_from_xml(xml, len(xml), &c_node)
+ return plist_t_to_node(c_node)
+
+cpdef object from_bin(bytes bin):
+ cdef plist_t c_node = NULL
+ plist_from_bin(bin, len(bin), &c_node)
+ return plist_t_to_node(c_node)
+
+cdef plist_t native_to_plist_t(object native):
+ cdef plist_t c_node
+ cdef plist_t child_c_node
+ cdef int32_t secs = 0
+ cdef int32_t usecs = 0
+ cdef Node node
+ if isinstance(native, Node):
+ node = native
+ return plist_copy(node._c_node)
+ if isinstance(native, basestring):
+ return plist_new_string(native)
+ if isinstance(native, bool):
+ return plist_new_bool(native)
+ if isinstance(native, int) or isinstance(native, long):
+ return plist_new_uint(native)
+ if isinstance(native, float):
+ return plist_new_real(native)
+ if isinstance(native, dict):
+ return create_dict_plist(native)
+ if isinstance(native, list) or isinstance(native, tuple):
+ return create_array_plist(native)
+ if check_datetime(native):
+ return create_date_plist(native)
+
+cdef object plist_t_to_node(plist_t c_plist, bool managed=True):
+ cdef plist_type t = plist_get_node_type(c_plist)
+ if t == PLIST_BOOLEAN:
+ return Bool_factory(c_plist, managed)
+ if t == PLIST_UINT:
+ return Integer_factory(c_plist, managed)
+ if t == PLIST_REAL:
+ return Real_factory(c_plist, managed)
+ if t == PLIST_STRING:
+ return String_factory(c_plist, managed)
+ if t == PLIST_ARRAY:
+ return Array_factory(c_plist, managed)
+ if t == PLIST_DICT:
+ return Dict_factory(c_plist, managed)
+ if t == PLIST_DATE:
+ return Date_factory(c_plist, managed)
+ if t == PLIST_DATA:
+ return Data_factory(c_plist, managed)