diff options
| -rw-r--r-- | CMakeLists.txt | 17 | ||||
| -rw-r--r-- | cmake/modules/FindCython.cmake | 10 | ||||
| -rw-r--r-- | cython/CMakeLists.txt | 30 | ||||
| -rw-r--r-- | cython/plist.pxd | 62 | ||||
| -rw-r--r-- | cython/plist.pyx | 699 | ||||
| -rw-r--r-- | cython/plist_util.c | 41 | ||||
| -rw-r--r-- | cython/plist_util.h | 5 | 
7 files changed, 861 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a1d34e8..3ce3b7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,13 +17,21 @@ ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR)  FIND_PACKAGE( LibXml2 REQUIRED ) -OPTION(ENABLE_PYTHON "Enable Python bindings (needs Swig)" ON) +OPTION(ENABLE_SWIG "Enable SWIG Python bindings (needs Swig)" ON) +OPTION(ENABLE_CYTHON "Enable Cython Python bindings (needs Cython)" ON) -IF(ENABLE_PYTHON) +IF(ENABLE_SWIG)  	FIND_PACKAGE( SWIG ) +ENDIF(ENABLE_SWIG) + +IF(ENABLE_CYTHON) +	FIND_PACKAGE( Cython ) +ENDIF(ENABLE_CYTHON) + +IF(ENABLE_SWIG OR ENABLE_CYTHON)  	FIND_PACKAGE( PythonInterp )  	FIND_PACKAGE( PythonLibs ) -ENDIF(ENABLE_PYTHON) +ENDIF(ENABLE_SWIG OR ENABLE_CYTHON)  INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include  		     ${CMAKE_INCLUDE_PATH}) @@ -52,6 +60,9 @@ ADD_SUBDIRECTORY( test )  IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )  	ADD_SUBDIRECTORY( swig )  ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) +IF ( CYTHON_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) +	ADD_SUBDIRECTORY( cython ) +ENDIF ( CYTHON_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )  # add uninstall target  CONFIGURE_FILE(	"${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) diff --git a/cmake/modules/FindCython.cmake b/cmake/modules/FindCython.cmake new file mode 100644 index 0000000..89005b7 --- /dev/null +++ b/cmake/modules/FindCython.cmake @@ -0,0 +1,10 @@ +FIND_PROGRAM(CYTHON_EXECUTABLE cython) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython DEFAULT_MSG CYTHON_EXECUTABLE) + +MARK_AS_ADVANCED(CYTHON_EXECUTABLE) + +IF(CYTHON_FOUND) +      SET(CYTHON_USE_FILE ${CMAKE_SOURCE_DIR}/cmake/modules/UseCython.cmake) +ENDIF(CYTHON_FOUND) diff --git a/cython/CMakeLists.txt b/cython/CMakeLists.txt new file mode 100644 index 0000000..eac6bee --- /dev/null +++ b/cython/CMakeLists.txt @@ -0,0 +1,30 @@ + +INCLUDE_DIRECTORIES( ${PYTHON_INCLUDE_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ) + + +SET(plist_SRC +    ${CMAKE_CURRENT_BINARY_DIR}/plist.c ) + +SET(plist_HDR +    ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd ) + +ADD_CUSTOM_COMMAND( +    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/plist.c +    COMMAND ${CYTHON_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/plist.c ${CMAKE_CURRENT_SOURCE_DIR}/plist.pyx +    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/plist.pyx ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd +) + + +EXEC_PROGRAM("${PYTHON_EXECUTABLE}" +    ARGS "-c 'try:\n import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1,0,\"${CMAKE_INSTALL_PREFIX}\")\nexcept: pass\n'" +    OUTPUT_VARIABLE DISTUTILS_PYTHON_ILIBRARY_PATH +    ) + +PYTHON_ADD_MODULE(cython_plist plist.c plist_util.c) +SET_TARGET_PROPERTIES(cython_plist PROPERTIES PREFIX "" OUTPUT_NAME plist) +TARGET_LINK_LIBRARIES(cython_plist plist ${PYTHON_LIBRARIES}) + +INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/plist${CMAKE_SHARED_MODULE_SUFFIX} +   DESTINATION ${DISTUTILS_PYTHON_ILIBRARY_PATH} ) +INSTALL( FILES ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd +   DESTINATION include/plist/cython COMPONENT dev) diff --git a/cython/plist.pxd b/cython/plist.pxd new file mode 100644 index 0000000..daafd78 --- /dev/null +++ b/cython/plist.pxd @@ -0,0 +1,62 @@ +cdef extern from "plist/plist.h": +    ctypedef void *plist_t +    ctypedef void *plist_dict_iter + +cdef class Node: +    cdef plist_t _c_node +    cdef bool _c_managed +    cpdef object __deepcopy__(self, memo=*) +    cpdef bytes to_xml(self) +    cpdef bytes to_bin(self) +    cpdef object copy(self) + +cdef class Bool(Node): +    cpdef set_value(self, value) +    cpdef bool get_value(self) +     +cdef class Integer(Node): +    cpdef set_value(self, value) +    cpdef int get_value(self) + +cdef class Real(Node): +    cpdef set_value(self, value) +    cpdef float get_value(self) + +cdef class String(Node): +    cpdef set_value(self, unicode value) +    cpdef unicode get_value(self) + +cdef class Date(Node): +    cpdef set_value(self, value) +    cpdef object get_value(self) + +cdef class Data(Node): +    cpdef set_value(self, bytes value) +    cpdef bytes get_value(self) + +cdef class Dict(Node): +    cdef dict _map +    cdef void _init(self) +    cpdef set_value(self, dict value) +    cpdef dict get_value(self) +    cpdef bool has_key(self, key) +    cpdef object get(self, key, default=*) +    cpdef list keys(self) +    cpdef list items(self) +    cpdef list values(self) +    cpdef object iterkeys(self) +    cpdef object iteritems(self) +    cpdef object itervalues(self) + +cdef class Array(Node): +    cdef list _array +    cdef void _init(self) +    cpdef set_value(self, value) +    cpdef list get_value(self) +    cpdef append(self, item) + +cpdef object from_xml(xml) +cpdef object from_bin(bytes bin) + +cdef object plist_t_to_node(plist_t c_plist, bool managed=*) +cdef plist_t native_to_plist_t(object native) 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) diff --git a/cython/plist_util.c b/cython/plist_util.c new file mode 100644 index 0000000..70c5be3 --- /dev/null +++ b/cython/plist_util.c @@ -0,0 +1,41 @@ +#include "plist_util.h" + +#include <time.h> +#include <datetime.h> + +void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec) { +    PyDateTime_IMPORT; +    if (!PyDateTime_Check(obj)) { +		PyErr_SetString(PyExc_ValueError,"Expected a datetime"); +		sec = NULL; +		usec = NULL; +		return; +    } +    struct tm t = { +		PyDateTime_DATE_GET_SECOND(obj), +		PyDateTime_DATE_GET_MINUTE(obj), +		PyDateTime_DATE_GET_HOUR(obj), +		PyDateTime_GET_DAY(obj), +		PyDateTime_GET_MONTH(obj)-1, +		PyDateTime_GET_YEAR(obj)-1900, +		0,0,0 +    }; +	*sec = (int32_t)mktime(&t); +	*usec = PyDateTime_DATE_GET_MICROSECOND(obj); +} +PyObject* ints_to_datetime(int32_t sec, int32_t usec) { +	time_t sec_tt = sec; +    struct tm* t = gmtime(&sec_tt); +    if(t){ +		PyDateTime_IMPORT; +		return PyDateTime_FromDateAndTime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, usec); +    } +	return NULL; +} +int check_datetime(PyObject* ob) { +	if(ob){ +		PyDateTime_IMPORT; +		return PyDateTime_Check(ob); +	} +	return 0; +} diff --git a/cython/plist_util.h b/cython/plist_util.h new file mode 100644 index 0000000..fbf56b6 --- /dev/null +++ b/cython/plist_util.h @@ -0,0 +1,5 @@ +#include <Python.h> + +void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec); +PyObject* ints_to_datetime(int32_t sec, int32_t usec); +int check_datetime(PyObject* obj);  | 
