summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cython/plist.pxd9
-rw-r--r--cython/plist.pyx106
2 files changed, 72 insertions, 43 deletions
diff --git a/cython/plist.pxd b/cython/plist.pxd
index daafd78..6a96817 100644
--- a/cython/plist.pxd
+++ b/cython/plist.pxd
@@ -1,25 +1,26 @@
1cdef extern from "plist/plist.h": 1cdef extern from "plist/plist.h":
2 ctypedef void *plist_t 2 ctypedef void *plist_t
3 ctypedef void *plist_dict_iter 3 ctypedef void *plist_dict_iter
4 void plist_free(plist_t node)
4 5
5cdef class Node: 6cdef class Node:
6 cdef plist_t _c_node 7 cdef plist_t _c_node
7 cdef bool _c_managed 8 cdef bool _c_managed
8 cpdef object __deepcopy__(self, memo=*) 9 cpdef object __deepcopy__(self, memo=*)
9 cpdef bytes to_xml(self) 10 cpdef unicode to_xml(self)
10 cpdef bytes to_bin(self) 11 cpdef bytes to_bin(self)
11 cpdef object copy(self) 12 cpdef object copy(self)
12 13
13cdef class Bool(Node): 14cdef class Bool(Node):
14 cpdef set_value(self, value) 15 cpdef set_value(self, object value)
15 cpdef bool get_value(self) 16 cpdef bool get_value(self)
16 17
17cdef class Integer(Node): 18cdef class Integer(Node):
18 cpdef set_value(self, value) 19 cpdef set_value(self, object value)
19 cpdef int get_value(self) 20 cpdef int get_value(self)
20 21
21cdef class Real(Node): 22cdef class Real(Node):
22 cpdef set_value(self, value) 23 cpdef set_value(self, object value)
23 cpdef float get_value(self) 24 cpdef float get_value(self)
24 25
25cdef class String(Node): 26cdef class String(Node):
diff --git a/cython/plist.pyx b/cython/plist.pyx
index f4e7dbb..c636f7d 100644
--- a/cython/plist.pyx
+++ b/cython/plist.pyx
@@ -10,6 +10,8 @@ ELSE:
10 ctypedef unsigned long long int uint64_t 10 ctypedef unsigned long long int uint64_t
11 11
12cimport python_unicode 12cimport python_unicode
13cimport python_string
14cimport stdlib
13 15
14cdef extern from *: 16cdef extern from *:
15 ctypedef enum plist_type: 17 ctypedef enum plist_type:
@@ -80,9 +82,6 @@ cdef extern from *:
80 void plist_from_xml(char *plist_xml, uint32_t length, plist_t * plist) 82 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) 83 void plist_from_bin(char *plist_bin, uint32_t length, plist_t * plist)
82 84
83cdef extern from *:
84 void free(void *ptr)
85
86cdef class Node: 85cdef class Node:
87 def __init__(self, *args, **kwargs): 86 def __init__(self, *args, **kwargs):
88 self._c_managed = True 87 self._c_managed = True
@@ -99,19 +98,27 @@ cdef class Node:
99 c_node = plist_copy(self._c_node) 98 c_node = plist_copy(self._c_node)
100 return plist_t_to_node(c_node) 99 return plist_t_to_node(c_node)
101 100
102 cpdef bytes to_xml(self): 101 cpdef unicode to_xml(self):
103 cdef char* out = NULL 102 cdef:
104 cdef uint32_t length 103 char* out = NULL
104 uint32_t length
105 plist_to_xml(self._c_node, &out, &length) 105 plist_to_xml(self._c_node, &out, &length)
106 106
107 return out[:length] 107 try:
108 return python_unicode.PyUnicode_DecodeUTF8(out, length, 'strict')
109 finally:
110 stdlib.free(out)
108 111
109 cpdef bytes to_bin(self): 112 cpdef bytes to_bin(self):
110 cdef char* out = NULL 113 cdef:
111 cdef uint32_t length 114 char* out = NULL
115 uint32_t length
112 plist_to_bin(self._c_node, &out, &length) 116 plist_to_bin(self._c_node, &out, &length)
113 117
114 return out[:length] 118 try:
119 return python_string.PyString_FromStringAndSize(out, length)
120 finally:
121 stdlib.free(out)
115 122
116 property parent: 123 property parent:
117 def __get__(self): 124 def __get__(self):
@@ -156,7 +163,7 @@ cdef class Bool(Node):
156 b = self.get_value() 163 b = self.get_value()
157 return '<Bool: %s>' % b 164 return '<Bool: %s>' % b
158 165
159 cpdef set_value(self, value): 166 cpdef set_value(self, object value):
160 plist_set_bool_val(self._c_node, bool(value)) 167 plist_set_bool_val(self._c_node, bool(value))
161 168
162 cpdef bool get_value(self): 169 cpdef bool get_value(self):
@@ -178,7 +185,7 @@ cdef class Integer(Node):
178 self._c_node = plist_new_uint(int(value)) 185 self._c_node = plist_new_uint(int(value))
179 186
180 def __repr__(self): 187 def __repr__(self):
181 i = self.get_value() 188 cdef int i = self.get_value()
182 return '<Integer: %s>' % i 189 return '<Integer: %s>' % i
183 190
184 def __int__(self): 191 def __int__(self):
@@ -202,7 +209,7 @@ cdef class Integer(Node):
202 if op == 5: 209 if op == 5:
203 return i >= other 210 return i >= other
204 211
205 cpdef set_value(self, value): 212 cpdef set_value(self, object value):
206 plist_set_uint_val(self._c_node, int(value)) 213 plist_set_uint_val(self._c_node, int(value))
207 214
208 cpdef int get_value(self): 215 cpdef int get_value(self):
@@ -248,7 +255,7 @@ cdef class Real(Node):
248 if op == 5: 255 if op == 5:
249 return f >= other 256 return f >= other
250 257
251 cpdef set_value(self, value): 258 cpdef set_value(self, object value):
252 plist_set_real_val(self._c_node, float(value)) 259 plist_set_real_val(self._c_node, float(value))
253 260
254 cpdef float get_value(self): 261 cpdef float get_value(self):
@@ -266,24 +273,28 @@ from python_version cimport PY_MAJOR_VERSION
266 273
267cdef class String(Node): 274cdef class String(Node):
268 def __cinit__(self, value=None, *args, **kwargs): 275 def __cinit__(self, value=None, *args, **kwargs):
276 cdef:
277 char* c_utf8_data = NULL
278 bytes utf8_data
269 if value is None: 279 if value is None:
270 self._c_node = plist_new_string("") 280 self._c_node = plist_new_string("")
271 else: 281 else:
272 if isinstance(value, unicode): 282 if isinstance(value, unicode):
273 utf8_data = value.encode('utf-8') 283 utf8_data = value.encode('utf-8')
274 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str): 284 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
275 value.decode('ascii') 285 value.decode('ascii') # trial decode
276 utf8_data = value 286 utf8_data = value.decode('ascii')
277 else: 287 else:
278 raise ValueError("requires text input, got %s" % type(value)) 288 raise ValueError("requires text input, got %s" % type(value))
279 self._c_node = plist_new_string(utf8_data) 289 c_utf8_data = utf8_data
290 self._c_node = plist_new_string(c_utf8_data)
280 291
281 def __repr__(self): 292 def __repr__(self):
282 s = self.get_value() 293 s = self.get_value()
283 return '<String: %s>' % s 294 return '<String: %s>' % s.encode('utf-8')
284 295
285 def __richcmp__(self, other, op): 296 def __richcmp__(self, other, op):
286 cdef str s = self.get_value() 297 cdef unicode s = self.get_value()
287 if op == 0: 298 if op == 0:
288 return s < other 299 return s < other
289 if op == 1: 300 if op == 1:
@@ -298,22 +309,30 @@ cdef class String(Node):
298 return s >= other 309 return s >= other
299 310
300 cpdef set_value(self, unicode value): 311 cpdef set_value(self, unicode value):
312 cdef:
313 char* c_utf8_data = NULL
314 bytes utf8_data
301 if value is None: 315 if value is None:
302 self._c_node = plist_new_string("") 316 plist_set_string_val(self._c_node, c_utf8_data)
303 else: 317 else:
304 if isinstance(value, unicode): 318 if isinstance(value, unicode):
305 utf8_data = value.encode('utf-8') 319 utf8_data = value.encode('utf-8')
306 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str): 320 elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
307 value.decode('ascii') 321 value.decode('ascii') # trial decode
308 utf8_data = value 322 utf8_data = value.decode('ascii')
309 else: 323 else:
310 raise ValueError("requires text input, got %s" % type(value)) 324 raise ValueError("requires text input, got %s" % type(value))
311 self._c_node = plist_new_string(utf8_data) 325 c_utf8_data = utf8_data
326 plist_set_string_val(self._c_node, c_utf8_data)
312 327
313 cpdef unicode get_value(self): 328 cpdef unicode get_value(self):
314 cdef char* value = NULL 329 cdef:
315 plist_get_string_val(self._c_node, &value) 330 char* c_value = NULL
316 return python_unicode.PyUnicode_DecodeUTF8(value, len(value), 'strict') 331 plist_get_string_val(self._c_node, &c_value)
332 try:
333 return python_unicode.PyUnicode_DecodeUTF8(c_value, stdlib.strlen(c_value), 'strict')
334 finally:
335 stdlib.free(c_value)
317 336
318cdef String String_factory(plist_t c_node, bool managed=True): 337cdef String String_factory(plist_t c_node, bool managed=True):
319 cdef String instance = String.__new__(String) 338 cdef String instance = String.__new__(String)
@@ -393,7 +412,7 @@ cdef class Data(Node):
393 return '<Data: %s>' % d 412 return '<Data: %s>' % d
394 413
395 def __richcmp__(self, other, op): 414 def __richcmp__(self, other, op):
396 cdef str d = self.get_value() 415 cdef bytes d = self.get_value()
397 if op == 0: 416 if op == 0:
398 return d < other 417 return d < other
399 if op == 1: 418 if op == 1:
@@ -408,11 +427,15 @@ cdef class Data(Node):
408 return d >= other 427 return d >= other
409 428
410 cpdef bytes get_value(self): 429 cpdef bytes get_value(self):
411 cdef char* val = NULL 430 cdef:
412 cdef uint64_t length = 0 431 char* val = NULL
432 uint64_t length = 0
413 plist_get_data_val(self._c_node, &val, &length) 433 plist_get_data_val(self._c_node, &val, &length)
414 434
415 return val[:length] 435 try:
436 return python_string.PyString_FromStringAndSize(val, length)
437 finally:
438 stdlib.free(val)
416 439
417 cpdef set_value(self, bytes value): 440 cpdef set_value(self, bytes value):
418 plist_set_data_val(self._c_node, value, len(value)) 441 plist_set_data_val(self._c_node, value, len(value))
@@ -434,6 +457,8 @@ cdef plist_t create_dict_plist(value=None):
434 c_node = NULL 457 c_node = NULL
435 return node 458 return node
436 459
460cimport python_dict
461
437cdef class Dict(Node): 462cdef class Dict(Node):
438 def __cinit__(self, value=None, *args, **kwargs): 463 def __cinit__(self, value=None, *args, **kwargs):
439 self._c_node = create_dict_plist(value) 464 self._c_node = create_dict_plist(value)
@@ -446,18 +471,18 @@ cdef class Dict(Node):
446 cdef char* key = NULL 471 cdef char* key = NULL
447 cdef plist_t subnode = NULL 472 cdef plist_t subnode = NULL
448 473
449 self._map = {} 474 self._map = python_dict.PyDict_New()
450 475
451 plist_dict_new_iter(self._c_node, &it); 476 plist_dict_new_iter(self._c_node, &it);
452 plist_dict_next_item(self._c_node, it, &key, &subnode); 477 plist_dict_next_item(self._c_node, it, &key, &subnode);
453 478
454 while subnode is not NULL: 479 while subnode is not NULL:
455 self._map[key] = plist_t_to_node(subnode, False) 480 python_dict.PyDict_SetItem(self._map, key, plist_t_to_node(subnode, False))
456 subnode = NULL 481 subnode = NULL
457 free(key) 482 stdlib.free(key)
458 key = NULL 483 key = NULL
459 plist_dict_next_item(self._c_node, it, &key, &subnode); 484 plist_dict_next_item(self._c_node, it, &key, &subnode);
460 free(it) 485 stdlib.free(it)
461 486
462 def __dealloc__(self): 487 def __dealloc__(self):
463 self._map = None 488 self._map = None
@@ -478,13 +503,15 @@ cdef class Dict(Node):
478 return d >= other 503 return d >= other
479 504
480 def __len__(self): 505 def __len__(self):
481 return len(self._map) 506 return python_dict.PyDict_Size(self._map)
482 507
483 def __repr__(self): 508 def __repr__(self):
484 return '<Dict: %s>' % self._map 509 return '<Dict: %s>' % self._map
485 510
486 cpdef dict get_value(self): 511 cpdef dict get_value(self):
512 cdef dict result = python_dict.PyDict_New()
487 return dict([(key, value.get_value()) for key, value in self.items()]) 513 return dict([(key, value.get_value()) for key, value in self.items()])
514 return result
488 515
489 cpdef set_value(self, dict value): 516 cpdef set_value(self, dict value):
490 plist_free(self._c_node) 517 plist_free(self._c_node)
@@ -503,18 +530,19 @@ cdef class Dict(Node):
503 return self._map.get(key, default) 530 return self._map.get(key, default)
504 531
505 cpdef list keys(self): 532 cpdef list keys(self):
506 return self._map.keys() 533 return python_dict.PyDict_Keys(self._map)
507 534
508 cpdef object iterkeys(self): 535 cpdef object iterkeys(self):
509 return self._map.iterkeys() 536 return self._map.iterkeys()
510 537
511 cpdef list items(self): 538 cpdef list items(self):
512 return self._map.items() 539 return python_dict.PyDict_Items(self._map)
513 540
514 cpdef object iteritems(self): 541 cpdef object iteritems(self):
515 return self._map.iteritems() 542 return self._map.iteritems()
516 543
517 cpdef list values(self): 544 cpdef list values(self):
545 return python_dict.PyDict_Values(self._map)
518 return self._map.values() 546 return self._map.values()
519 547
520 cpdef object itervalues(self): 548 cpdef object itervalues(self):
@@ -534,7 +562,7 @@ cdef class Dict(Node):
534 self._map[key] = n 562 self._map[key] = n
535 563
536 def __delitem__(self, key): 564 def __delitem__(self, key):
537 del self._map[key] 565 python_dict.PyDict_DelItem(self._map, key)
538 plist_dict_remove_item(self._c_node, key) 566 plist_dict_remove_item(self._c_node, key)
539 567
540cdef Dict Dict_factory(plist_t c_node, bool managed=True): 568cdef Dict Dict_factory(plist_t c_node, bool managed=True):
@@ -667,7 +695,7 @@ cdef plist_t native_to_plist_t(object native):
667 if isinstance(native, basestring): 695 if isinstance(native, basestring):
668 return plist_new_string(native) 696 return plist_new_string(native)
669 if isinstance(native, bool): 697 if isinstance(native, bool):
670 return plist_new_bool(native) 698 return plist_new_bool(<bint>native)
671 if isinstance(native, int) or isinstance(native, long): 699 if isinstance(native, int) or isinstance(native, long):
672 return plist_new_uint(native) 700 return plist_new_uint(native)
673 if isinstance(native, float): 701 if isinstance(native, float):