summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt17
-rw-r--r--cmake/modules/FindCython.cmake10
-rw-r--r--cython/CMakeLists.txt30
-rw-r--r--cython/plist.pxd62
-rw-r--r--cython/plist.pyx699
-rw-r--r--cython/plist_util.c41
-rw-r--r--cython/plist_util.h5
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)
17 17
18FIND_PACKAGE( LibXml2 REQUIRED ) 18FIND_PACKAGE( LibXml2 REQUIRED )
19 19
20OPTION(ENABLE_PYTHON "Enable Python bindings (needs Swig)" ON) 20OPTION(ENABLE_SWIG "Enable SWIG Python bindings (needs Swig)" ON)
21OPTION(ENABLE_CYTHON "Enable Cython Python bindings (needs Cython)" ON)
21 22
22IF(ENABLE_PYTHON) 23IF(ENABLE_SWIG)
23 FIND_PACKAGE( SWIG ) 24 FIND_PACKAGE( SWIG )
25ENDIF(ENABLE_SWIG)
26
27IF(ENABLE_CYTHON)
28 FIND_PACKAGE( Cython )
29ENDIF(ENABLE_CYTHON)
30
31IF(ENABLE_SWIG OR ENABLE_CYTHON)
24 FIND_PACKAGE( PythonInterp ) 32 FIND_PACKAGE( PythonInterp )
25 FIND_PACKAGE( PythonLibs ) 33 FIND_PACKAGE( PythonLibs )
26ENDIF(ENABLE_PYTHON) 34ENDIF(ENABLE_SWIG OR ENABLE_CYTHON)
27 35
28INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include 36INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include
29 ${CMAKE_INCLUDE_PATH}) 37 ${CMAKE_INCLUDE_PATH})
@@ -52,6 +60,9 @@ ADD_SUBDIRECTORY( test )
52IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) 60IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )
53 ADD_SUBDIRECTORY( swig ) 61 ADD_SUBDIRECTORY( swig )
54ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) 62ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )
63IF ( CYTHON_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )
64 ADD_SUBDIRECTORY( cython )
65ENDIF ( CYTHON_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND )
55 66
56# add uninstall target 67# add uninstall target
57CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) 68CONFIGURE_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 @@
1FIND_PROGRAM(CYTHON_EXECUTABLE cython)
2
3INCLUDE(FindPackageHandleStandardArgs)
4FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython DEFAULT_MSG CYTHON_EXECUTABLE)
5
6MARK_AS_ADVANCED(CYTHON_EXECUTABLE)
7
8IF(CYTHON_FOUND)
9 SET(CYTHON_USE_FILE ${CMAKE_SOURCE_DIR}/cmake/modules/UseCython.cmake)
10ENDIF(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 @@
1
2INCLUDE_DIRECTORIES( ${PYTHON_INCLUDE_PATH} ${CMAKE_CURRENT_SOURCE_DIR} )
3
4
5SET(plist_SRC
6 ${CMAKE_CURRENT_BINARY_DIR}/plist.c )
7
8SET(plist_HDR
9 ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd )
10
11ADD_CUSTOM_COMMAND(
12 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/plist.c
13 COMMAND ${CYTHON_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/plist.c ${CMAKE_CURRENT_SOURCE_DIR}/plist.pyx
14 DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/plist.pyx ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd
15)
16
17
18EXEC_PROGRAM("${PYTHON_EXECUTABLE}"
19 ARGS "-c 'try:\n import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1,0,\"${CMAKE_INSTALL_PREFIX}\")\nexcept: pass\n'"
20 OUTPUT_VARIABLE DISTUTILS_PYTHON_ILIBRARY_PATH
21 )
22
23PYTHON_ADD_MODULE(cython_plist plist.c plist_util.c)
24SET_TARGET_PROPERTIES(cython_plist PROPERTIES PREFIX "" OUTPUT_NAME plist)
25TARGET_LINK_LIBRARIES(cython_plist plist ${PYTHON_LIBRARIES})
26
27INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/plist${CMAKE_SHARED_MODULE_SUFFIX}
28 DESTINATION ${DISTUTILS_PYTHON_ILIBRARY_PATH} )
29INSTALL( FILES ${CMAKE_CURRENT_SOURCE_DIR}/plist.pxd
30 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 @@
1cdef extern from "plist/plist.h":
2 ctypedef void *plist_t
3 ctypedef void *plist_dict_iter
4
5cdef class Node:
6 cdef plist_t _c_node
7 cdef bool _c_managed
8 cpdef object __deepcopy__(self, memo=*)
9 cpdef bytes to_xml(self)
10 cpdef bytes to_bin(self)
11 cpdef object copy(self)
12
13cdef class Bool(Node):
14 cpdef set_value(self, value)
15 cpdef bool get_value(self)
16
17cdef class Integer(Node):
18 cpdef set_value(self, value)
19 cpdef int get_value(self)
20
21cdef class Real(Node):
22 cpdef set_value(self, value)
23 cpdef float get_value(self)
24
25cdef class String(Node):
26 cpdef set_value(self, unicode value)
27 cpdef unicode get_value(self)
28
29cdef class Date(Node):
30 cpdef set_value(self, value)
31 cpdef object get_value(self)
32
33cdef class Data(Node):
34 cpdef set_value(self, bytes value)
35 cpdef bytes get_value(self)
36
37cdef class Dict(Node):
38 cdef dict _map
39 cdef void _init(self)
40 cpdef set_value(self, dict value)
41 cpdef dict get_value(self)
42 cpdef bool has_key(self, key)
43 cpdef object get(self, key, default=*)
44 cpdef list keys(self)
45 cpdef list items(self)
46 cpdef list values(self)
47 cpdef object iterkeys(self)
48 cpdef object iteritems(self)
49 cpdef object itervalues(self)
50
51cdef class Array(Node):
52 cdef list _array
53 cdef void _init(self)
54 cpdef set_value(self, value)
55 cpdef list get_value(self)
56 cpdef append(self, item)
57
58cpdef object from_xml(xml)
59cpdef object from_bin(bytes bin)
60
61cdef object plist_t_to_node(plist_t c_plist, bool managed=*)
62cdef 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 @@
1cdef extern from *:
2 ctypedef unsigned char uint8_t
3 ctypedef short int int16_t
4 ctypedef unsigned short int uint16_t
5 ctypedef unsigned int uint32_t
6 ctypedef int int32_t
7IF UNAME_MACHINE == 'x86_64':
8 ctypedef unsigned long int uint64_t
9ELSE:
10 ctypedef unsigned long long int uint64_t
11
12cimport python_unicode
13
14cdef extern from *:
15 ctypedef enum plist_type:
16 PLIST_BOOLEAN,
17 PLIST_UINT,
18 PLIST_REAL,
19 PLIST_STRING,
20 PLIST_ARRAY,
21 PLIST_DICT,
22 PLIST_DATE,
23 PLIST_DATA,
24 PLIST_KEY,
25 PLIST_NONE
26
27 plist_t plist_new_bool(uint8_t val)
28 void plist_get_bool_val(plist_t node, uint8_t *val)
29 void plist_set_bool_val(plist_t node, uint8_t val)
30
31 plist_t plist_new_uint(uint64_t val)
32 void plist_get_uint_val(plist_t node, uint64_t *val)
33 void plist_set_uint_val(plist_t node, uint64_t val)
34
35 plist_t plist_new_real(double val)
36 void plist_get_real_val(plist_t node, double *val)
37 void plist_set_real_val(plist_t node, double val)
38
39 plist_t plist_new_date(int32_t sec, int32_t usec)
40 void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec)
41 void plist_set_date_val(plist_t node, int32_t sec, int32_t usec)
42
43 plist_t plist_new_string(char *val)
44 void plist_get_string_val(plist_t node, char **val)
45 void plist_set_string_val(plist_t node, char *val)
46
47 plist_t plist_new_data(char *val, uint64_t length)
48 void plist_get_data_val(plist_t node, char **val, uint64_t * length)
49 void plist_set_data_val(plist_t node, char *val, uint64_t length)
50
51 plist_t plist_new_dict()
52 int plist_dict_get_size(plist_t node)
53 plist_t plist_dict_get_item(plist_t node, char* key)
54 void plist_dict_set_item(plist_t node, char* key, plist_t item)
55 void plist_dict_insert_item(plist_t node, char* key, plist_t item)
56 void plist_dict_remove_item(plist_t node, char* key)
57
58 void plist_dict_new_iter(plist_t node, plist_dict_iter *iter)
59 void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val)
60
61 plist_t plist_new_array()
62 uint32_t plist_array_get_size(plist_t node)
63 plist_t plist_array_get_item(plist_t node, uint32_t n)
64 uint32_t plist_array_get_item_index(plist_t node)
65 void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
66 void plist_array_append_item(plist_t node, plist_t item)
67 void plist_array_insert_item(plist_t node, plist_t item, uint32_t n)
68 void plist_array_remove_item(plist_t node, uint32_t n)
69
70 void plist_free(plist_t plist)
71 plist_t plist_copy(plist_t plist)
72 void plist_to_xml(plist_t plist, char **plist_xml, uint32_t *length)
73 void plist_to_bin(plist_t plist, char **plist_bin, uint32_t *length)
74
75 plist_t plist_get_parent(plist_t node)
76 plist_type plist_get_node_type(plist_t node)
77
78 void plist_set_type(plist_t node, plist_type type)
79
80 void plist_from_xml(char *plist_xml, uint32_t length, plist_t * plist)
81 void plist_from_bin(char *plist_bin, uint32_t length, plist_t * plist)
82
83cdef extern from *:
84 void free(void *ptr)
85
86cdef class Node:
87 def __init__(self, *args, **kwargs):
88 self._c_managed = True
89
90 def __dealloc__(self):
91 if self._c_node is not NULL and self._c_managed:
92 plist_free(self._c_node)
93
94 cpdef object __deepcopy__(self, memo={}):
95 return plist_t_to_node(plist_copy(self._c_node))
96
97 cpdef object copy(self):
98 cdef plist_t c_node = NULL
99 c_node = plist_copy(self._c_node)
100 return plist_t_to_node(c_node)
101
102 cpdef bytes to_xml(self):
103 cdef char* out = NULL
104 cdef uint32_t length
105 plist_to_xml(self._c_node, &out, &length)
106
107 return out[:length]
108
109 cpdef bytes to_bin(self):
110 cdef char* out = NULL
111 cdef uint32_t length
112 plist_to_bin(self._c_node, &out, &length)
113
114 return out[:length]
115
116 property parent:
117 def __get__(self):
118 cdef plist_t c_parent = NULL
119 cdef Node node
120
121 c_parent = plist_get_parent(self._c_node)
122 if c_parent == NULL:
123 return None
124
125 return plist_t_to_node(c_parent)
126
127 def __str__(self):
128 return str(self.get_value())
129
130cdef class Bool(Node):
131 def __cinit__(self, value=None, *args, **kwargs):
132 if value is None:
133 self._c_node = plist_new_bool(0)
134 else:
135 self._c_node = plist_new_bool(bool(value))
136
137 def __nonzero__(self):
138 return self.get_value()
139
140 def __richcmp__(self, other, op):
141 cdef bool b = self.get_value()
142 if op == 0:
143 return b < other
144 if op == 1:
145 return b <= other
146 if op == 2:
147 return b == other
148 if op == 3:
149 return b != other
150 if op == 4:
151 return b > other
152 if op == 5:
153 return b >= other
154
155 def __repr__(self):
156 b = self.get_value()
157 return '<Bool: %s>' % b
158
159 cpdef set_value(self, value):
160 plist_set_bool_val(self._c_node, bool(value))
161
162 cpdef bool get_value(self):
163 cdef uint8_t value
164 plist_get_bool_val(self._c_node, &value)
165 return bool(value)
166
167cdef Bool Bool_factory(plist_t c_node, bool managed=True):
168 cdef Bool instance = Bool.__new__(Bool)
169 instance._c_managed = managed
170 instance._c_node = c_node
171 return instance
172
173cdef class Integer(Node):
174 def __cinit__(self, value=None, *args, **kwargs):
175 if value is None:
176 self._c_node = plist_new_uint(0)
177 else:
178 self._c_node = plist_new_uint(int(value))
179
180 def __repr__(self):
181 i = self.get_value()
182 return '<Integer: %s>' % i
183
184 def __int__(self):
185 return self.get_value()
186
187 def __float__(self):
188 return float(self.get_value())
189
190 def __richcmp__(self, other, op):
191 cdef int i = self.get_value()
192 if op == 0:
193 return i < other
194 if op == 1:
195 return i <= other
196 if op == 2:
197 return i == other
198 if op == 3:
199 return i != other
200 if op == 4:
201 return i > other
202 if op == 5:
203 return i >= other
204
205 cpdef set_value(self, value):
206 plist_set_uint_val(self._c_node, int(value))
207
208 cpdef int get_value(self):
209 cdef uint64_t value
210 plist_get_uint_val(self._c_node, &value)
211 return value
212
213cdef Integer Integer_factory(plist_t c_node, bool managed=True):
214 cdef Integer instance = Integer.__new__(Integer)
215 instance._c_managed = managed
216 instance._c_node = c_node
217 return instance
218
219cdef class Real(Node):
220 def __cinit__(self, value=None, *args, **kwargs):
221 if value is None:
222 self._c_node = plist_new_real(0.0)
223 else:
224 self._c_node = plist_new_real(float(value))
225
226 def __repr__(self):
227 r = self.get_value()
228 return '<Real: %s>' % r
229
230 def __float__(self):
231 return self.get_value()
232
233 def __int__(self):
234 return int(self.get_value())
235
236 def __richcmp__(self, other, op):
237 cdef float f = self.get_value()
238 if op == 0:
239 return f < other
240 if op == 1:
241 return f <= other
242 if op == 2:
243 return f == other
244 if op == 3:
245 return f != other
246 if op == 4:
247 return f > other
248 if op == 5:
249 return f >= other
250
251 cpdef set_value(self, value):
252 plist_set_real_val(self._c_node, float(value))
253
254 cpdef float get_value(self):
255 cdef double value
256 plist_get_real_val(self._c_node, &value)
257 return value
258
259cdef Real Real_factory(plist_t c_node, bool managed=True):
260 cdef Real instance = Real.__new__(Real)
261 instance._c_managed = managed
262 instance._c_node = c_node
263 return instance
264
265from python_version cimport PY_MAJOR_VERSION
266
267cdef class String(Node):
268 def __cinit__(self, value=None, *args, **kwargs):
269 if value is None:
270 self._c_node = plist_new_string("")
271 else:
272 if isinstance(value, unicode):
273 utf8_data = value.encode('utf-8')
274 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
275 value.decode('ascii')
276 utf8_data = value
277 else:
278 raise ValueError("requires text input, got %s" % type(value))
279 self._c_node = plist_new_string(utf8_data)
280
281 def __repr__(self):
282 s = self.get_value()
283 return '<String: %s>' % s
284
285 def __richcmp__(self, other, op):
286 cdef str s = self.get_value()
287 if op == 0:
288 return s < other
289 if op == 1:
290 return s <= other
291 if op == 2:
292 return s == other
293 if op == 3:
294 return s != other
295 if op == 4:
296 return s > other
297 if op == 5:
298 return s >= other
299
300 cpdef set_value(self, unicode value):
301 if value is None:
302 self._c_node = plist_new_string("")
303 else:
304 if isinstance(value, unicode):
305 utf8_data = value.encode('utf-8')
306 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
307 value.decode('ascii')
308 utf8_data = value
309 else:
310 raise ValueError("requires text input, got %s" % type(value))
311 self._c_node = plist_new_string(utf8_data)
312
313 cpdef unicode get_value(self):
314 cdef char* value = NULL
315 plist_get_string_val(self._c_node, &value)
316 return python_unicode.PyUnicode_DecodeUTF8(value, len(value), 'strict')
317
318cdef String String_factory(plist_t c_node, bool managed=True):
319 cdef String instance = String.__new__(String)
320 instance._c_managed = managed
321 instance._c_node = c_node
322 return instance
323
324cdef extern from "plist_util.h":
325 void datetime_to_ints(object obj, int32_t* sec, int32_t* usec)
326 object ints_to_datetime(int32_t sec, int32_t usec)
327 int check_datetime(object obj)
328
329cdef plist_t create_date_plist(value=None):
330 cdef plist_t node = NULL
331 cdef int32_t secs
332 cdef int32_t usecs
333 if value is None:
334 node = plist_new_date(0, 0)
335 elif check_datetime(value):
336 datetime_to_ints(value, &secs, &usecs)
337 node = plist_new_date(secs, usecs)
338 return node
339
340cdef class Date(Node):
341 def __cinit__(self, value=None, *args, **kwargs):
342 self._c_node = create_date_plist(value)
343
344 def __repr__(self):
345 d = self.get_value()
346 return '<Date: %s>' % d.ctime()
347
348 def __richcmp__(self, other, op):
349 d = self.get_value()
350 if op == 0:
351 return d < other
352 if op == 1:
353 return d <= other
354 if op == 2:
355 return d == other
356 if op == 3:
357 return d != other
358 if op == 4:
359 return d > other
360 if op == 5:
361 return d >= other
362
363 cpdef object get_value(self):
364 cdef int32_t secs = 0
365 cdef int32_t usecs = 0
366 cdef object result
367 plist_get_date_val(self._c_node, &secs, &usecs)
368 return ints_to_datetime(secs, usecs)
369
370 cpdef set_value(self, value):
371 cdef int32_t secs
372 cdef int32_t usecs
373 if not check_datetime(value):
374 raise ValueError("Expected a datetime")
375 datetime_to_ints(value, &secs, &usecs)
376 plist_set_date_val(self._c_node, secs, usecs)
377
378cdef Date Date_factory(plist_t c_node, bool managed=True):
379 cdef Date instance = Date.__new__(Date)
380 instance._c_managed = managed
381 instance._c_node = c_node
382 return instance
383
384cdef class Data(Node):
385 def __cinit__(self, value=None, *args, **kwargs):
386 if value is None:
387 self._c_node = plist_new_data(NULL, 0)
388 else:
389 self._c_node = plist_new_data(value, len(value))
390
391 def __repr__(self):
392 d = self.get_value()
393 return '<Data: %s>' % d
394
395 def __richcmp__(self, other, op):
396 cdef str d = self.get_value()
397 if op == 0:
398 return d < other
399 if op == 1:
400 return d <= other
401 if op == 2:
402 return d == other
403 if op == 3:
404 return d != other
405 if op == 4:
406 return d > other
407 if op == 5:
408 return d >= other
409
410 cpdef bytes get_value(self):
411 cdef char* val = NULL
412 cdef uint64_t length = 0
413 plist_get_data_val(self._c_node, &val, &length)
414
415 return val[:length]
416
417 cpdef set_value(self, bytes value):
418 plist_set_data_val(self._c_node, value, len(value))
419
420cdef Data Data_factory(plist_t c_node, bool managed=True):
421 cdef Data instance = Data.__new__(Data)
422 instance._c_managed = managed
423 instance._c_node = c_node
424 return instance
425
426cdef plist_t create_dict_plist(value=None):
427 cdef plist_t node = NULL
428 cdef plist_t c_node = NULL
429 node = plist_new_dict()
430 if value is not None and isinstance(value, dict):
431 for key, item in value.items():
432 c_node = native_to_plist_t(item)
433 plist_dict_insert_item(node, key, c_node)
434 c_node = NULL
435 return node
436
437cdef class Dict(Node):
438 def __cinit__(self, value=None, *args, **kwargs):
439 self._c_node = create_dict_plist(value)
440
441 def __init__(self, value=None, *args, **kwargs):
442 self._init()
443
444 cdef void _init(self):
445 cdef plist_dict_iter it = NULL
446 cdef char* key = NULL
447 cdef plist_t subnode = NULL
448
449 self._map = {}
450
451 plist_dict_new_iter(self._c_node, &it);
452 plist_dict_next_item(self._c_node, it, &key, &subnode);
453
454 while subnode is not NULL:
455 self._map[key] = plist_t_to_node(subnode, False)
456 subnode = NULL
457 free(key)
458 key = NULL
459 plist_dict_next_item(self._c_node, it, &key, &subnode);
460 free(it)
461
462 def __dealloc__(self):
463 self._map = None
464 Node.__dealloc__(self)
465
466 def __richcmp__(self, other, op):
467 cdef dict d = self.get_value()
468 if op == 0:
469 return d < other
470 if op == 1:
471 return d <= other
472 if op == 2:
473 return d == other
474 if op == 3:
475 return d != other
476 if op == 4:
477 return d > other
478 if op == 5:
479 return d >= other
480
481 def __len__(self):
482 return len(self._map)
483
484 def __repr__(self):
485 return '<Dict: %s>' % self._map
486
487 cpdef dict get_value(self):
488 return dict([(key, value.get_value()) for key, value in self.items()])
489
490 cpdef set_value(self, dict value):
491 plist_free(self._c_node)
492 self._map = {}
493 self._c_node = NULL
494 self._c_node = create_dict_plist(value)
495 self._init()
496
497 def __iter__(self):
498 return self._map.__iter__()
499
500 cpdef bool has_key(self, key):
501 return self._map.has_key(key)
502
503 cpdef object get(self, key, default=None):
504 return self._map.get(key, default)
505
506 cpdef list keys(self):
507 return self._map.keys()
508
509 cpdef object iterkeys(self):
510 return self._map.iterkeys()
511
512 cpdef list items(self):
513 return self._map.items()
514
515 cpdef object iteritems(self):
516 return self._map.iteritems()
517
518 cpdef list values(self):
519 return self._map.values()
520
521 cpdef object itervalues(self):
522 return self._map.itervalues()
523
524 def __getitem__(self, key):
525 return self._map[key]
526
527 def __setitem__(self, key, value):
528 cdef Node n
529 if isinstance(value, Node):
530 n = value.copy()
531 else:
532 n = plist_t_to_node(native_to_plist_t(value), False)
533
534 plist_dict_insert_item(self._c_node, key, n._c_node)
535 self._map[key] = n
536
537 def __delitem__(self, key):
538 del self._map[key]
539 plist_dict_remove_item(self._c_node, key)
540
541cdef Dict Dict_factory(plist_t c_node, bool managed=True):
542 cdef Dict instance = Dict.__new__(Dict)
543 instance._c_managed = managed
544 instance._c_node = c_node
545 instance._init()
546 return instance
547
548cdef plist_t create_array_plist(value=None):
549 cdef plist_t node = NULL
550 cdef plist_t c_node = NULL
551 node = plist_new_array()
552 if value is not None and (isinstance(value, list) or isinstance(value, tuple)):
553 for item in value:
554 c_node = native_to_plist_t(item)
555 plist_array_append_item(node, c_node)
556 c_node = NULL
557 return node
558
559cdef class Array(Node):
560 def __cinit__(self, value=None, *args, **kwargs):
561 self._c_node = create_array_plist(value)
562
563 def __init__(self, value=None, *args, **kwargs):
564 self._init()
565
566 cdef void _init(self):
567 cdef uint32_t size = plist_array_get_size(self._c_node)
568 cdef plist_t subnode = NULL
569
570 for i from 0 <= i < size:
571 subnode = plist_array_get_item(self._c_node, i)
572 self._array.append(plist_t_to_node(subnode, False))
573
574 def __richcmp__(self, other, op):
575 cdef list l = self.get_value()
576 if op == 0:
577 return l < other
578 if op == 1:
579 return l <= other
580 if op == 2:
581 return l == other
582 if op == 3:
583 return l != other
584 if op == 4:
585 return l > other
586 if op == 5:
587 return l >= other
588
589 def __len__(self):
590 return len(self._array)
591
592 def __repr__(self):
593 return '<Array: %s>' % self._array
594
595 cpdef list get_value(self):
596 return [i.get_value() for i in self]
597
598 cpdef set_value(self, value):
599 self._array = []
600 plist_free(self._c_node)
601 self._c_node = NULL
602 self._c_node = create_array_plist(value)
603 self._init()
604
605 def __iter__(self):
606 return self._array.__iter__()
607
608 def __getitem__(self, index):
609 return self._array[index]
610
611 def __setitem__(self, index, value):
612 cdef Node n
613 if isinstance(value, Node):
614 n = value.copy()
615 else:
616 n = plist_t_to_node(native_to_plist_t(value), False)
617
618 if index < 0:
619 index = len(self) + index
620
621 plist_array_set_item(self._c_node, n._c_node, index)
622 self._array[index] = n
623
624 def __delitem__(self, index):
625 if index < 0:
626 index = len(self) + index
627 del self._array[index]
628 plist_array_remove_item(self._c_node, index)
629
630 cpdef append(self, item):
631 cdef Node n
632
633 if isinstance(item, Node):
634 n = item.copy()
635 else:
636 n = plist_t_to_node(native_to_plist_t(item), False)
637
638 plist_array_append_item(self._c_node, n._c_node)
639 self._array.append(n)
640
641cdef Array Array_factory(plist_t c_node, bool managed=True):
642 cdef Array instance = Array.__new__(Array)
643 instance._c_managed = managed
644 instance._c_node = c_node
645 instance._init()
646 return instance
647
648cpdef object from_xml(xml):
649 cdef plist_t c_node = NULL
650 plist_from_xml(xml, len(xml), &c_node)
651 return plist_t_to_node(c_node)
652
653cpdef object from_bin(bytes bin):
654 cdef plist_t c_node = NULL
655 plist_from_bin(bin, len(bin), &c_node)
656 return plist_t_to_node(c_node)
657
658cdef plist_t native_to_plist_t(object native):
659 cdef plist_t c_node
660 cdef plist_t child_c_node
661 cdef int32_t secs = 0
662 cdef int32_t usecs = 0
663 cdef Node node
664 if isinstance(native, Node):
665 node = native
666 return plist_copy(node._c_node)
667 if isinstance(native, basestring):
668 return plist_new_string(native)
669 if isinstance(native, bool):
670 return plist_new_bool(native)
671 if isinstance(native, int) or isinstance(native, long):
672 return plist_new_uint(native)
673 if isinstance(native, float):
674 return plist_new_real(native)
675 if isinstance(native, dict):
676 return create_dict_plist(native)
677 if isinstance(native, list) or isinstance(native, tuple):
678 return create_array_plist(native)
679 if check_datetime(native):
680 return create_date_plist(native)
681
682cdef object plist_t_to_node(plist_t c_plist, bool managed=True):
683 cdef plist_type t = plist_get_node_type(c_plist)
684 if t == PLIST_BOOLEAN:
685 return Bool_factory(c_plist, managed)
686 if t == PLIST_UINT:
687 return Integer_factory(c_plist, managed)
688 if t == PLIST_REAL:
689 return Real_factory(c_plist, managed)
690 if t == PLIST_STRING:
691 return String_factory(c_plist, managed)
692 if t == PLIST_ARRAY:
693 return Array_factory(c_plist, managed)
694 if t == PLIST_DICT:
695 return Dict_factory(c_plist, managed)
696 if t == PLIST_DATE:
697 return Date_factory(c_plist, managed)
698 if t == PLIST_DATA:
699 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 @@
1#include "plist_util.h"
2
3#include <time.h>
4#include <datetime.h>
5
6void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec) {
7 PyDateTime_IMPORT;
8 if (!PyDateTime_Check(obj)) {
9 PyErr_SetString(PyExc_ValueError,"Expected a datetime");
10 sec = NULL;
11 usec = NULL;
12 return;
13 }
14 struct tm t = {
15 PyDateTime_DATE_GET_SECOND(obj),
16 PyDateTime_DATE_GET_MINUTE(obj),
17 PyDateTime_DATE_GET_HOUR(obj),
18 PyDateTime_GET_DAY(obj),
19 PyDateTime_GET_MONTH(obj)-1,
20 PyDateTime_GET_YEAR(obj)-1900,
21 0,0,0
22 };
23 *sec = (int32_t)mktime(&t);
24 *usec = PyDateTime_DATE_GET_MICROSECOND(obj);
25}
26PyObject* ints_to_datetime(int32_t sec, int32_t usec) {
27 time_t sec_tt = sec;
28 struct tm* t = gmtime(&sec_tt);
29 if(t){
30 PyDateTime_IMPORT;
31 return PyDateTime_FromDateAndTime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, usec);
32 }
33 return NULL;
34}
35int check_datetime(PyObject* ob) {
36 if(ob){
37 PyDateTime_IMPORT;
38 return PyDateTime_Check(ob);
39 }
40 return 0;
41}
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 @@
1#include <Python.h>
2
3void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec);
4PyObject* ints_to_datetime(int32_t sec, int32_t usec);
5int check_datetime(PyObject* obj);