cython: Implement dump()/dumps() to match up with plistlib (Python 3.4)
diff --git a/cython/plist.pxd b/cython/plist.pxd
index 99dcca5..b11d80d 100644
--- a/cython/plist.pxd
+++ b/cython/plist.pxd
@@ -71,6 +71,8 @@
 
 cpdef object load(fp, fmt=*, use_builtin_types=*, dict_type=*)
 cpdef object loads(data, fmt=*, use_builtin_types=*, dict_type=*)
+cpdef object dump(value, fp, fmt=*, sort_keys=*, skipkeys=*)
+cpdef object dumps(value, fmt=*, sort_keys=*, skipkeys=*)
 
 cdef object plist_t_to_node(plist_t c_plist, bint managed=*)
 cdef plist_t native_to_plist_t(object native)
diff --git a/cython/plist.pyx b/cython/plist.pyx
index 573f17f..3c6389c 100644
--- a/cython/plist.pyx
+++ b/cython/plist.pyx
@@ -907,3 +907,38 @@
         raise ValueError('Cannot parse XML property list as binary')
 
     return cb(data)
+
+cpdef object dump(value, fp, fmt=FMT_XML, sort_keys=True, skipkeys=False):
+    fp.write(dumps(value, fmt=fmt))
+
+cpdef object dumps(value, fmt=FMT_XML, sort_keys=True, skipkeys=False):
+    if fmt not in (FMT_XML, FMT_BINARY):
+        raise ValueError('Format must be constant FMT_XML or FMT_BINARY')
+
+    if check_datetime(value):
+        node = Date(value)
+    elif isinstance(value, unicode):
+        node = String(value)
+    elif PY_MAJOR_VERSION >= 3 and isinstance(value, bytes):
+        node = Data(value)
+    elif isinstance(value, str):
+        # See if this is binary
+        try:
+            node = String(value)
+        except ValueError:
+            node = Data(value)
+    elif isinstance(value, bool):
+        node = Bool(value)
+    elif isinstance(value, int):
+        node = Integer(value)
+    elif isinstance(value, float):
+        node = Real(value)
+    elif isinstance(value, dict):
+        node = Dict(value)
+    elif type(value) in (list, set, tuple):
+        node = Array(value)
+
+    if fmt == FMT_XML:
+        return node.to_xml()
+
+    return node.to_bin()