r26080: Import updated LDB bindings.
authorJelmer Vernooij <jelmer@samba.org>
Wed, 21 Nov 2007 11:31:47 +0000 (12:31 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 21 Dec 2007 04:45:56 +0000 (05:45 +0100)
(This used to be commit 19342e66a7279805daf9f810b9dc808247110a8a)

source4/lib/ldb/ldb.i

index cdf1d66de1f4db2432329ac105c6d16346567e86..9a55327a07528805e4454168f1de436f10f18cc6 100644 (file)
@@ -1,10 +1,11 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    Swig interface to ldb.
 
    Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
    Copyright (C) 2006 Simo Sorce <idra@samba.org>
+   Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
 
      ** NOTE! The following LGPL license applies to the ldb
      ** library. This does NOT imply that all of Samba is released
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
-%module ldb
+%module(package="ldb") ldb
 
 %{
 
-/* Some typedefs to help swig along */
-
-typedef unsigned char uint8_t;
-typedef unsigned long long uint64_t;
-typedef long long int64_t;
-
 /* Include headers */
 
+#include <stdint.h>
 #include <stdbool.h>
 #include "talloc.h"
 #include "ldb.h"
+#include "ldb_errors.h"
+
+typedef struct ldb_message ldb_msg;
+typedef struct ldb_context ldb;
+typedef struct ldb_dn ldb_dn;
+typedef struct ldb_ldif ldb_ldif;
+typedef struct ldb_message_element ldb_msg_element;
+typedef int ldb_error;
 
 %}
 
-%include "carrays.i"
+%import "carrays.i"
+%import "typemaps.i"
 %include "exception.i"
+%import "stdint.i"
 
-/*
- * Constants
- */
+%constant int SCOPE_DEFAULT = LDB_SCOPE_DEFAULT;
+%constant int SCOPE_BASE = LDB_SCOPE_BASE;
+%constant int SCOPE_ONELEVEL = LDB_SCOPE_ONELEVEL;
+%constant int SCOPE_SUBTREE = LDB_SCOPE_SUBTREE;
 
-#define LDB_SUCCESS                            0
-#define LDB_ERR_OPERATIONS_ERROR               1
-#define LDB_ERR_PROTOCOL_ERROR                 2
-#define LDB_ERR_TIME_LIMIT_EXCEEDED            3
-#define LDB_ERR_SIZE_LIMIT_EXCEEDED            4
-#define LDB_ERR_COMPARE_FALSE                  5
-#define LDB_ERR_COMPARE_TRUE                   6
-#define LDB_ERR_AUTH_METHOD_NOT_SUPPORTED      7
-#define LDB_ERR_STRONG_AUTH_REQUIRED           8
-/* 9 RESERVED */
-#define LDB_ERR_REFERRAL                       10
-#define LDB_ERR_ADMIN_LIMIT_EXCEEDED           11
-#define LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION 12
-#define LDB_ERR_CONFIDENTIALITY_REQUIRED       13
-#define LDB_ERR_SASL_BIND_IN_PROGRESS          14
-#define LDB_ERR_NO_SUCH_ATTRIBUTE              16
-#define LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE       17
-#define LDB_ERR_INAPPROPRIATE_MATCHING         18
-#define LDB_ERR_CONSTRAINT_VIOLATION           19
-#define LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS      20
-#define LDB_ERR_INVALID_ATTRIBUTE_SYNTAX       21
-/* 22-31 unused */
-#define LDB_ERR_NO_SUCH_OBJECT                 32
-#define LDB_ERR_ALIAS_PROBLEM                  33
-#define LDB_ERR_INVALID_DN_SYNTAX              34
-/* 35 RESERVED */
-#define LDB_ERR_ALIAS_DEREFERENCING_PROBLEM    36
-/* 37-47 unused */
-#define LDB_ERR_INAPPROPRIATE_AUTHENTICATION   48
-#define LDB_ERR_INVALID_CREDENTIALS            49
-#define LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS     50
-#define LDB_ERR_BUSY                           51
-#define LDB_ERR_UNAVAILABLE                    52
-#define LDB_ERR_UNWILLING_TO_PERFORM           53
-#define LDB_ERR_LOOP_DETECT                    54
-/* 55-63 unused */
-#define LDB_ERR_NAMING_VIOLATION               64
-#define LDB_ERR_OBJECT_CLASS_VIOLATION         65
-#define LDB_ERR_NOT_ALLOWED_ON_NON_LEAF                66
-#define LDB_ERR_NOT_ALLOWED_ON_RDN             67
-#define LDB_ERR_ENTRY_ALREADY_EXISTS           68
-#define LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED   69
-/* 70 RESERVED FOR CLDAP */
-#define LDB_ERR_AFFECTS_MULTIPLE_DSAS          71
-/* 72-79 unused */
-#define LDB_ERR_OTHER                          80
-
-enum ldb_scope {LDB_SCOPE_DEFAULT=-1, 
-               LDB_SCOPE_BASE=0, 
-               LDB_SCOPE_ONELEVEL=1,
-               LDB_SCOPE_SUBTREE=2};
+%constant int CHANGETYPE_NONE = LDB_CHANGETYPE_NONE;
+%constant int CHANGETYPE_ADD = LDB_CHANGETYPE_ADD;
+%constant int CHANGETYPE_DELETE = LDB_CHANGETYPE_DELETE;
+%constant int CHANGETYPE_MODIFY = LDB_CHANGETYPE_MODIFY;
 
 /* 
  * Wrap struct ldb_context
@@ -114,16 +74,16 @@ enum ldb_scope {LDB_SCOPE_DEFAULT=-1,
                        "ldb context must be non-NULL");
 }
 
+%typemap(check) ldb_msg * {
+       if ($1 == NULL)
+               SWIG_exception(SWIG_ValueError, 
+                       "Message can not be None");
+}
+
 /* 
  * Wrap a small bit of talloc
  */
 
-/* Use talloc_init() to create a parameter to pass to ldb_init().  Don't
-   forget to free it using talloc_free() afterwards. */
-
-TALLOC_CTX *talloc_init(char *name);
-int talloc_free(TALLOC_CTX *ptr);
-
 /*
  * Wrap struct ldb_val
  */
@@ -139,103 +99,470 @@ int talloc_free(TALLOC_CTX *ptr);
 }
 
 %typemap(out) struct ldb_val {
-       $result = PyString_FromStringAndSize($1.data, $1.length);
+       $result = PyString_FromStringAndSize((const char *)$1.data, $1.length);
 }
 
-/*
- * Wrap struct ldb_result
- */
-
-%typemap(in, numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) {
-       $1 = &temp_ldb_result;
+%typemap(in) ldb_msg *add_msg (int dict_pos, int msg_pos, PyObject *key, 
+                               PyObject *value, ldb_msg_element *msgel) {
+    if (PyDict_Check($input)) {
+        $1 = ldb_msg_new(NULL);
+        $1->num_elements = PyDict_Size($input) - 1; /* dn isn't in there */
+        $1->elements = talloc_zero_array($1, struct ldb_message_element, $1->num_elements+1);
+        msg_pos = dict_pos = 0;
+        while (PyDict_Next($input, &dict_pos, &key, &value)) {
+            if (!strcmp(PyString_AsString(key), "dn")) {
+                if (ldb_dn_from_pyobject(value, &$1->dn) != 0)
+                    SWIG_exception(SWIG_TypeError, "unable to convert dn");
+            } else {
+                msgel = ldb_msg_element_from_pyobject(value, 0, PyString_AsString(key));
+                memcpy(&$1->elements[msg_pos], msgel, sizeof(*msgel));
+                msg_pos++;
+            }
+            dict_pos++;
+        }
+
+        if ($1->dn == NULL)
+            SWIG_exception(SWIG_TypeError, "no dn set");
+    } else {
+        if (SWIG_ConvertPtr($input, &$1, SWIGTYPE_p_ldb_message, 0) != 0)
+            return NULL;
+    }
 }
 
-%typemap(argout) struct ldb_result ** {
-       resultobj = SWIG_NewPointerObj(*$1, SWIGTYPE_p_ldb_result, 0);
-}      
-
-%types(struct ldb_result *);
-
-/*
- * Wrap struct ldb_message_element
- */
-
-%array_functions(struct ldb_val, ldb_val_array);
+%typemap(freearg) ldb_msg *add_msg {
+//talloc_free($1);
+}
 
-struct ldb_message_element {
-       unsigned int flags;
-       const char *name;
-       unsigned int num_values;
-       struct ldb_val *values;
-};
 
 /*
- * Wrap struct ldb_message
+ * Wrap struct ldb_result
  */
 
-%array_functions(struct ldb_message_element, ldb_message_element_array);
+%typemap(in, numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) {
+       $1 = &temp_ldb_result;
+}
 
-struct ldb_message {
-       struct ldb_dn *dn;
-       unsigned int num_elements;
-       struct ldb_message_element *elements;
-};
+#ifdef SWIGPYTHON
+%typemap(argout) struct ldb_result ** (int i) {
+       $result = PyList_New((*$1)->count);
+    for (i = 0; i < (*$1)->count; i++) {
+        PyList_SetItem($result, i, 
+            SWIG_NewPointerObj((*$1)->msgs[i], SWIGTYPE_p_ldb_message, 0)
+        );
+    }
+}
 
-/*
- * Wrap struct ldb_result
- */
+%typemap(in, numinputs=1) const char * const *attrs {
+    if ($input == Py_None) {
+        $1 = NULL;
+    } else if (PySequence_Check($input)) {
+        int i;
+        $1 = talloc_array(NULL, char *, PySequence_Size($input)+1);
+        for(i = 0; i < PySequence_Size($input); i++)
+            $1[i] = PyString_AsString(PySequence_GetItem($input, i));
+        $1[i] = NULL;
+    } else {
+        SWIG_exception(SWIG_TypeError, "expected sequence");
+    }
+}
 
-%array_functions(struct ldb_message *, ldb_message_ptr_array);
+%typemap(freearg) const char * const *attrs {
+    talloc_free($1);
+}
+#endif
 
-struct ldb_result {
-       unsigned int count;
-       struct ldb_message **msgs;
-       char **refs;
-       struct ldb_control **controls;
-};
+%types(struct ldb_result *);
 
 /*
- * Wrap ldb functions 
+ * Wrap struct ldb_dn
  */
 
-/* Initialisation */
+%rename(__str__) ldb_dn::get_linearized;
+%rename(__cmp__) ldb_dn::compare;
+%rename(__len__) ldb_dn::get_comp_num;
+%rename(Dn) ldb_dn;
+typedef struct ldb_dn {
+    %extend {
+        ldb_dn(ldb *ldb, const char *str)
+        {
+            ldb_dn *ret = ldb_dn_new(ldb, ldb, str);
+            /* ldb_dn_new() doesn't accept NULL as memory context, so 
+               we do it this way... */
+            talloc_steal(NULL, ret);
+
+            if (ret == NULL)
+                SWIG_exception(SWIG_ValueError, 
+                                "unable to parse dn string");
+fail:
+            return ret;
+        }
+        ~ldb_dn() { talloc_free($self); }
+        bool validate();
+        const char *get_casefold();
+        const char *get_linearized();
+        ldb_dn *parent() { return ldb_dn_get_parent(NULL, $self); }
+        int compare(ldb_dn *other);
+        bool is_valid();
+        bool is_special();
+        bool is_null();
+        bool check_special(const char *name);
+        int get_comp_num();
+        bool add_child(ldb_dn *child);
+        bool add_base(ldb_dn *base);
+        const char *canonical_str() {
+            return ldb_dn_canonical_string($self, $self);
+        }
+        const char *canonical_ex_str() {
+            return ldb_dn_canonical_ex_string($self, $self);
+        }
+#ifdef SWIGPYTHON
+        ldb_dn *__add__(ldb_dn *other)
+        {
+            ldb_dn *ret = ldb_dn_copy(NULL, $self);
+            ldb_dn_add_child(ret, other);
+            return ret;
+        }
+
+        /* FIXME: implement __getslice__ */
+#endif
+    }
+} ldb_dn;
+
+#ifdef SWIGPYTHON
+%inline {
+int ldb_dn_from_pyobject(PyObject *object, ldb_dn **dn)
+{
+    return SWIG_ConvertPtr(object, dn, SWIGTYPE_p_ldb_dn, 0);
+}
 
-int ldb_global_init(void);
-struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx);
+ldb_msg_element *ldb_msg_element_from_pyobject(PyObject *set_obj, int flags,
+                                               const char *attr_name)
+{
+    struct ldb_message_element *me = talloc(NULL, struct ldb_message_element);
+    me->name = attr_name;
+    me->flags = flags;
+    if (PyString_Check(set_obj)) {
+        me->num_values = 1;
+        me->values = talloc_array(me, struct ldb_val, me->num_values);
+        me->values[0].length = PyString_Size(set_obj);
+        me->values[0].data = (uint8_t *)talloc_strdup(me->values, 
+                                           PyString_AsString(set_obj));
+    } else if (PySequence_Check(set_obj)) {
+        int i;
+        me->num_values = PySequence_Size(set_obj);
+        me->values = talloc_array(me, struct ldb_val, me->num_values);
+        for (i = 0; i < me->num_values; i++) {
+            PyObject *obj = PySequence_GetItem(set_obj, i);
+            me->values[i].length = PyString_Size(obj);
+            me->values[i].data = (uint8_t *)PyString_AsString(obj);
+        }
+    } else {
+        talloc_free(me);
+        me = NULL;
+    }
+
+    return me;
+}
 
-/* Error handling */
+PyObject *ldb_msg_element_to_set(ldb_msg_element *me)
+{
+    int i;
+    PyObject *result;
 
-const char *ldb_errstring(struct ldb_context *ldb);
-const char *ldb_strerror(int ldb_err);
+    /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
+    result = PyList_New(me->num_values);
 
-/* Top-level ldb operations */
+    for (i = 0; i < me->num_values; i++) {
+        PyList_SetItem(result, i,
+            PyString_FromStringAndSize((const char *)me->values[i].data, 
+                                       me->values[i].length));
+    }
 
-int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]);
+    return result;
+}
 
-int ldb_search(struct ldb_context *ldb, struct ldb_dn *base, enum ldb_scope scope, const char *expression, const char * const *attrs, struct ldb_result **OUT);
+}
+#endif
+
+/* ldb_message_element */
+%rename(__cmp__) ldb_message_element::compare;
+%rename(MessageElement) ldb_msg_element;
+typedef struct ldb_message_element {
+    %extend {
+#ifdef SWIGPYTHON
+        PyObject *__iter__(void)
+        {
+            return PyObject_GetIter(ldb_msg_element_to_set($self));
+        }
+
+        PyObject *__set__(void)
+        {
+            return ldb_msg_element_to_set($self);
+        }
+
+        ldb_msg_element(PyObject *set_obj, int flags=0, const char *name = NULL)
+        {
+            return ldb_msg_element_from_pyobject(set_obj, flags, name);
+        }
+#endif
+        ~ldb_msg_element() { talloc_free($self); }
+        int compare(ldb_msg_element *);
+    }
+} ldb_msg_element;
+
+/* ldb_message */
+
+%rename(Message) ldb_message;
+#ifdef SWIGPYTHON
+%rename(__delitem__) ldb_message::remove_attr;
+%typemap(out) ldb_msg_element * {
+       if ($1 == NULL)
+               PyErr_SetString(PyExc_KeyError, "no such element");
+    else
+        $result = SWIG_NewPointerObj($1, SWIGTYPE_p_ldb_message_element, 0);
+}
+%rename(__getitem__) ldb_message::find_element;
+//%typemap(out) ldb_msg_element *;
+
+
+%inline {
+    PyObject *ldb_msg_list_elements(ldb_msg *msg)
+    {
+        int i;
+        PyObject *obj = PyList_New(msg->num_elements);
+        for (i = 0; i < msg->num_elements; i++)
+            PyList_SetItem(obj, i, PyString_FromString(msg->elements[i].name));
+        return obj;
+    }
+}
 
-int ldb_delete(struct ldb_context *ldb, struct ldb_dn *dn);
+#endif
+
+typedef struct ldb_message {
+       ldb_dn *dn;
+
+    %extend {
+        ldb_msg(ldb_dn *dn = NULL) { 
+            ldb_msg *ret = ldb_msg_new(NULL); 
+            ret->dn = talloc_reference(ret, dn);
+            return ret;
+        }
+        ~ldb_msg() { talloc_free($self); }
+
+        ldb_msg_element *find_element(const char *name);
+        
+#ifdef SWIGPYTHON
+        void __setitem__(const char *attr_name, ldb_msg_element *val)
+        {
+            struct ldb_message_element *el;
+            
+            ldb_msg_remove_attr($self, attr_name);
+
+            el = talloc($self, struct ldb_message_element);
+            el->name = talloc_strdup(el, attr_name);
+            el->num_values = val->num_values;
+            el->values = talloc_reference(el, val->values);
+
+            ldb_msg_add($self, el, val->flags);
+        }
+
+        void __setitem__(const char *attr_name, PyObject *val)
+        {
+            struct ldb_message_element *el = ldb_msg_element_from_pyobject(
+                                                val, 0, attr_name);
+            talloc_steal($self, el);
+            ldb_msg_remove_attr($self, attr_name);
+            ldb_msg_add($self, el, el->flags);
+        }
+
+        unsigned int __len__() { return $self->num_elements; }
+
+        PyObject *keys(void)
+        {
+            return ldb_msg_list_elements($self);
+        }
+
+        PyObject *__iter__(void)
+        {
+            return PyObject_GetIter(ldb_msg_list_elements($self));
+        }
+#endif
+        void remove_attr(const char *name);
+    }
+} ldb_msg;
+
+/* FIXME: Convert ldb_result to 3-tuple:
+   (msgs, refs, controls)
+ */
 
-int ldb_rename(struct ldb_context *ldb, struct ldb_dn *olddn, struct ldb_dn *newdn);
+typedef struct ldb_ldif ldb_ldif;
 
-int ldb_add(struct ldb_context *ldb, const struct ldb_message *message);
+#ifdef SWIGPYTHON
+%{
+static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
+{
+    char *text;
+    PyObject *fn = context;
+
+    vasprintf(&text, fmt, ap);
+    PyObject_CallFunction(fn, "(i,s)", level, text);
+    free(text);
+}
+%}
 
-/* Ldb message operations */
+%typemap(in,numinputs=1) (void (*debug)(void *context, enum ldb_debug_level level, const char *fmt, va_list ap),
+                            void *context) {
+    $1 = py_ldb_debug;
+    /* FIXME: Should be decreased somewhere as well. Perhaps register a destructor and 
+       tie it to the ldb context ? */
+    Py_INCREF($input);
+    $2 = $input;
+}
+#endif
+
+%inline {
+    static PyObject *ldb_ldif_to_pyobject(ldb_ldif *ldif)
+    {
+        if (ldif == NULL) {
+            return Py_None;
+        } else {
+            return Py_BuildValue("(iO)", ldif->changetype, 
+                   SWIG_NewPointerObj(ldif->msg, SWIGTYPE_p_ldb_message, 0));
+        }
+    }
+}
 
-struct ldb_message *ldb_msg_new(void *mem_ctx);
+/*
+ * Wrap ldb errors
+ */
 
-struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, const char *attr_name);
+%{
+PyObject *PyExc_LdbError;
+%}
 
-int ldb_msg_add_value(struct ldb_message *msg, const char *attr_name, const struct ldb_val *val, struct ldb_message_element **return_el);
+%pythoncode %{
+    LdbError = _ldb.LdbError
+%}
 
-void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr);
+%init %{
+    PyExc_LdbError = PyErr_NewException("_ldb.LdbError", NULL, NULL);
+    PyDict_SetItemString(d, "LdbError", PyExc_LdbError);
+%}
 
-int ldb_msg_sanity_check(struct ldb_context *ldb, const struct ldb_message *msg);
+%ignore _LDB_ERRORS_H_;
+%ignore LDB_SUCCESS;
+%include "include/ldb_errors.h"
 
-/* DN operations */
+/*
+ * Wrap ldb functions 
+ */
 
-/* struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn); */
+%rename(Ldb) ldb;
+/* Top-level ldb operations */
+typedef struct ldb_context {
+    %typemap(out) ldb_error {
+        if ($1 != LDB_SUCCESS) {
+            PyErr_SetObject(PyExc_LdbError, Py_BuildValue("(i,s)", $1, ldb_strerror($1)));
+            SWIG_fail;
+        }
+        $result = Py_None;
+    };
+    %extend {
+        ldb(const char *url=NULL, unsigned int flags = 0, 
+            const char *options[] = NULL)
+        {
+            ldb *ldb = ldb_init(NULL);
+            
+            if (url != NULL) {
+                int ret;
+
+                ret = ldb_connect(ldb, url, flags, options);
+                if (ret != LDB_SUCCESS)
+                    SWIG_exception(SWIG_ValueError, ldb_errstring(ldb));
+            }
+
+            return ldb;
+
+fail:
+            talloc_free(ldb);
+            return NULL;
+        }
+
+        ldb_error connect(const char *url, unsigned int flags = 0, 
+            const char *options[] = NULL);
+
+        ~ldb() { talloc_free($self); }
+        ldb_error search(ldb_dn *base = NULL, 
+                   enum ldb_scope scope = LDB_SCOPE_DEFAULT, 
+                   const char *expression = NULL, 
+                   const char * const *attrs = NULL, 
+                   struct ldb_result **OUT);
+        ldb_error delete(ldb_dn *dn);
+        ldb_error rename(ldb_dn *olddn, ldb_dn *newdn);
+        ldb_error add(ldb_msg *add_msg);
+        ldb_error modify(ldb_msg *message);
+        ldb_dn *get_config_basedn();
+        ldb_dn *get_root_basedn();
+        ldb_dn *get_schema_basedn();
+        ldb_dn *get_default_basedn();
+        const char *errstring();
+        void set_create_perms(unsigned int perms);
+        void set_modules_dir(const char *path);
+        ldb_error set_debug(void (*debug)(void *context, enum ldb_debug_level level, 
+                                          const char *fmt, va_list ap),
+                            void *context);
+        ldb_error set_opaque(const char *name, void *value);
+        void *get_opaque(const char *name);
+        ldb_error transaction_start();
+        ldb_error transaction_commit();
+        ldb_error transaction_cancel();
+
+#ifdef SWIGPYTHON
+        bool __contains__(ldb_dn *dn)
+        {
+            struct ldb_result *result;
+            
+            int ret = ldb_search($self, dn, LDB_SCOPE_BASE, NULL, NULL, 
+                             &result);
+
+            /* FIXME: Check ret and set exception if necessary */
+
+            return result->count > 0;
+        }
+
+        PyObject *parse_ldif(const char *s)
+        {
+            PyObject *list = PyList_New(0);
+            struct ldb_ldif *ldif;
+            while ((ldif = ldb_ldif_read_string($self, &s)) != NULL) {
+                PyList_Append(list, ldb_ldif_to_pyobject(ldif));
+            }
+            return PyObject_GetIter(list);
+        }
+
+#endif
+    }
+} ldb;
+
+%nodefault ldb_message;
+%nodefault Ldb;
+%nodefault Dn;
+
+%rename(valid_attr_name) ldb_valid_attr_name;
+int ldb_valid_attr_name(const char *s);
+
+typedef unsigned long time_t;
 
-/* char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *dn); */
+%{
+char *timestring(time_t t)
+{
+    char *tresult = ldb_timestring(NULL, t);
+    char *result = strdup(tresult);
+    talloc_free(tresult);
+    return result; 
+}
+%}
+char *timestring(time_t t);
 
-%rename(ldb_context) Ldb;
+%rename(string_to_time) ldb_string_to_time;
+time_t ldb_string_to_time(const char *s);