From 6f452968bc8dde9736754930097b3bcef3d50bb3 Mon Sep 17 00:00:00 2001
From: hofmockel <dreagonfly@gmx.de>
Date: Sun, 19 Jan 2014 12:53:57 +0100
Subject: [PATCH] PySliceTransfrom to bridge python and c++

---
 rocksdb/_rocksdb.pyx        | 60 +++++++++++++++++++++++++++++++++++++
 rocksdb/interfaces.py       | 19 ++++++++++++
 rocksdb/slice_transform.pxd | 20 +++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 rocksdb/slice_transform.pxd

diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx
index 0f37b79..04e7fd3 100644
--- a/rocksdb/_rocksdb.pyx
+++ b/rocksdb/_rocksdb.pyx
@@ -15,6 +15,7 @@ cimport options
 cimport merge_operator
 cimport filter_policy
 cimport comparator
+cimport slice_transform
 cimport cache
 cimport logger
 cimport snapshot
@@ -29,6 +30,7 @@ from interfaces import MergeOperator as IMergeOperator
 from interfaces import AssociativeMergeOperator as IAssociativeMergeOperator
 from interfaces import FilterPolicy as IFilterPolicy
 from interfaces import Comparator as IComparator
+from interfaces import SliceTransform as ISliceTransform
 import traceback
 import errors
 
@@ -426,7 +428,65 @@ cdef class PyLRUCache(PyCache):
 LRUCache = PyLRUCache
 ###############################
 
+### Here comes the stuff for SliceTransform
+@cython.internal
+cdef class PySliceTransform(object):
+    cdef slice_transform.SliceTransform* transfomer
+    cdef object ob
+
+    def __cinit__(self, object ob):
+        if not isinstance(ob, ISliceTransform):
+            raise TypeError("%s is not of type %s" % (ob, ISliceTransform))
+
+        self.ob = ob
+        self.transfomer = <slice_transform.SliceTransform*>(
+            new slice_transform.SliceTransformWrapper(
+                bytes_to_string(ob.name()),
+                <void*>ob,
+                slice_transform_callback,
+                slice_in_domain_callback,
+                slice_in_range_callback))
+
+    def __dealloc__(self):
+        del self.transfomer
+
+    cdef object get_ob(self):
+        return self.ob
+
+    cdef slice_transform.SliceTransform* get_transformer(self):
+        return self.transfomer
+
+cdef Slice slice_transform_callback(void* ctx, const Slice& src) with gil:
+    cdef size_t offset
+    cdef size_t size
+
+    try:
+        ret = (<object>ctx).transform(slice_to_bytes(src))
+        offset = ret[0]
+        size = ret[1]
+        return Slice(src.data() + offset, size)
+    except Exception as error:
+        print error
+        # TODO: Use the rocksdb logger
+        return src
+
+cdef cpp_bool slice_in_domain_callback(void* ctx, const Slice& src) with gil:
+    try:
+        return (<object>ctx).in_domain(slice_to_bytes(src))
+    except Exception as error:
+        print error
+        # TODO: Use the rocksdb logger
+        return False
+
+cdef cpp_bool slice_in_range_callback(void* ctx, const Slice& src) with gil:
+    try:
+        return (<object>ctx).in_range(slice_to_bytes(src))
+    except Exception as error:
+        print error
+        # TODO: Use rocksdb logger
+        return False
 
+###########################################
 cdef class CompressionType(object):
     no_compression = u'no_compression'
     snappy_compression = u'snappy_compression'
diff --git a/rocksdb/interfaces.py b/rocksdb/interfaces.py
index 19bf658..d9812a7 100644
--- a/rocksdb/interfaces.py
+++ b/rocksdb/interfaces.py
@@ -56,3 +56,22 @@ class FilterPolicy:
     @abstractmethod
     def key_may_match(self, key, filter_):
         pass
+
+class SliceTransform:
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def name(self):
+        pass
+
+    @abstractmethod
+    def transform(self, src):
+        pass
+
+    @abstractmethod
+    def in_domain(self, src):
+        pass
+
+    @abstractmethod
+    def in_range(self, dst):
+        pass
diff --git a/rocksdb/slice_transform.pxd b/rocksdb/slice_transform.pxd
new file mode 100644
index 0000000..7a26a84
--- /dev/null
+++ b/rocksdb/slice_transform.pxd
@@ -0,0 +1,20 @@
+from slice_ cimport Slice
+from libcpp.string cimport string
+from libcpp cimport bool as cpp_bool
+
+cdef extern from "rocksdb/slice_transform.h" namespace "rocksdb":
+    cdef cppclass SliceTransform:
+        pass
+
+ctypedef Slice (*transform_func)(void*, const Slice&)
+ctypedef cpp_bool (*in_domain_func)(void*, const Slice&)
+ctypedef cpp_bool (*in_range_func)(void*, const Slice&)
+
+cdef extern from "cpp/slice_transform_wrapper.hpp" namespace "py_rocks":
+    cdef cppclass SliceTransformWrapper:
+        SliceTransformWrapper(
+                string name,
+                void*,
+                transform_func,
+                in_domain_func,
+                in_range_func) nogil except+
-- 
GitLab