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 @@
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)