Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / lib / tdb / tdb.i
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Swig interface to tdb.
5
6    Copyright (C) 2004-2006 Tim Potter <tpot@samba.org>
7    Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
8
9      ** NOTE! The following LGPL license applies to the tdb
10      ** library. This does NOT imply that all of Samba is released
11      ** under the LGPL
12    
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 3 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 */
26
27 %define DOCSTRING
28 "TDB is a simple key-value database similar to GDBM that supports multiple writers."
29 %enddef
30
31 %module(docstring=DOCSTRING) tdb
32
33 %{
34
35 /* This symbol is used in both includes.h and Python.h which causes an
36    annoying compiler warning. */
37
38 #ifdef HAVE_FSTAT
39 #undef HAVE_FSTAT
40 #endif
41
42 /* Include tdb headers */
43 #include <stdint.h>
44 #include <signal.h>
45 #include <tdb.h>
46 #include <fcntl.h>
47
48 typedef TDB_CONTEXT tdb;
49 %}
50
51 /* The tdb functions will crash if a NULL tdb context is passed */
52
53 %import exception.i
54 %import stdint.i
55
56 %typemap(check,noblock=1) TDB_CONTEXT* {
57         if ($1 == NULL)
58                 SWIG_exception(SWIG_ValueError, 
59                         "tdb context must be non-NULL");
60 }
61
62 /* In and out typemaps for the TDB_DATA structure.  This is converted to
63    and from the Python string type which can contain arbitrary binary
64    data.. */
65
66 %typemap(in,noblock=1) TDB_DATA {
67     if ($input == Py_None) {
68         $1.dsize = 0;
69         $1.dptr = NULL;
70     } else if (!PyString_Check($input)) {
71                 PyErr_SetString(PyExc_TypeError, "string arg expected");
72                 return NULL;
73         } else {
74         $1.dsize = PyString_Size($input);
75         $1.dptr = (uint8_t *)PyString_AsString($input);
76     }
77 }
78
79 %typemap(out,noblock=1) TDB_DATA {
80         if ($1.dptr == NULL && $1.dsize == 0) {
81                 $result = Py_None;
82         } else {
83                 $result = PyString_FromStringAndSize((const char *)$1.dptr, $1.dsize);
84                 free($1.dptr);
85     }
86 }
87
88 /* Treat a mode_t as an unsigned integer */
89 typedef int mode_t;
90
91 /* flags to tdb_store() */
92 %constant int REPLACE = TDB_REPLACE;
93 %constant int INSERT = TDB_INSERT;
94 %constant int MODIFY = TDB_MODIFY;
95
96 /* flags for tdb_open() */
97 %constant int DEFAULT = TDB_DEFAULT;
98 %constant int CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST;
99 %constant int INTERNAL = TDB_INTERNAL;
100 %constant int NOLOCK = TDB_NOLOCK;
101 %constant int NOMMAP = TDB_NOMMAP;
102 %constant int CONVERT = TDB_CONVERT;
103 %constant int BIGENDIAN = TDB_BIGENDIAN;
104
105 enum TDB_ERROR {
106      TDB_SUCCESS=0, 
107      TDB_ERR_CORRUPT, 
108      TDB_ERR_IO, 
109      TDB_ERR_LOCK, 
110      TDB_ERR_OOM, 
111      TDB_ERR_EXISTS, 
112      TDB_ERR_NOLOCK, 
113      TDB_ERR_LOCK_TIMEOUT,
114      TDB_ERR_NOEXIST, 
115      TDB_ERR_EINVAL, 
116      TDB_ERR_RDONLY
117 };
118
119 %rename(lock_all) tdb_context::lockall;
120 %rename(unlock_all) tdb_context::unlockall;
121
122 %rename(read_lock_all) tdb_context::lockall_read;
123 %rename(read_unlock_all) tdb_context::unlockall_read;
124
125 %typemap(default,noblock=1) int tdb_flags {
126     $1 = TDB_DEFAULT;
127 }
128
129 %typemap(default,noblock=1) int flags {
130     $1 = O_RDWR;
131 }
132
133 %typemap(default,noblock=1) int hash_size {
134     $1 = 0;
135 }
136
137 %typemap(default,noblock=1) mode_t mode {
138     $1 = 0600;
139 }
140
141 %typemap(default,noblock=1) int flag {
142     $1 = TDB_REPLACE;
143 }
144
145 %rename(Tdb) tdb_context;
146 %feature("docstring") tdb_context "A TDB file.";
147 %typemap(out,noblock=1) tdb * {
148     /* Throw an IOError exception from errno if tdb_open() returns NULL */
149     if ($1 == NULL) {
150         PyErr_SetFromErrno(PyExc_IOError);
151         SWIG_fail;
152     }
153     $result = SWIG_NewPointerObj($1, $1_descriptor, 0);
154 }
155
156 typedef struct tdb_context {
157     %extend {
158         %feature("docstring") tdb "S.__init__(name,hash_size=0,tdb_flags=TDB_DEFAULT,flags=O_RDWR,mode=0600)\n"
159                                   "Open a TDB file.";
160         tdb(const char *name, int hash_size, int tdb_flags, int flags, mode_t mode) {
161             return tdb_open(name, hash_size, tdb_flags, flags, mode);
162         }
163         %feature("docstring") error "S.error() -> int\n"
164                                     "Find last error number returned by operation on this TDB.";
165         enum TDB_ERROR error();
166         ~tdb() { tdb_close($self); }
167         %feature("docstring") close "S.close() -> None\n"
168                                     "Close the TDB file.";
169         int close();
170         int append(TDB_DATA key, TDB_DATA new_dbuf);
171         %feature("docstring") errorstr "S.errorstr() -> errorstring\n"
172                                         "Obtain last error message.";
173         const char *errorstr();
174         %rename(get) fetch;
175         %feature("docstring") fetch "S.fetch(key) -> value\n"
176                                         "Fetch a value.";
177         TDB_DATA fetch(TDB_DATA key);
178         %feature("docstring") delete "S.delete(key) -> None\n"
179                                         "Delete an entry.";
180         int delete(TDB_DATA key);
181         %feature("docstring") store "S.store(key, value, flag=TDB_REPLACE) -> None\n"
182                                         "Store an entry.";
183         int store(TDB_DATA key, TDB_DATA dbuf, int flag);
184         %feature("docstring") exists "S.exists(key) -> bool\n"
185                                         "Check whether key exists in this database.";
186         int exists(TDB_DATA key);
187         %feature("docstring") firstkey "S.firstkey() -> data\n"
188                                         "Return the first key in this database.";
189         TDB_DATA firstkey();
190         %feature("docstring") nextkey "S.nextkey(prev) -> data\n"
191                                         "Return the next key in this database.";
192         TDB_DATA nextkey(TDB_DATA key);
193         %feature("docstring") lockall "S.lockall() -> bool";
194         int lockall();
195         %feature("docstring") unlockall "S.unlockall() -> bool";
196         int unlockall();
197         %feature("docstring") unlockall "S.lockall_read() -> bool";
198         int lockall_read();
199         %feature("docstring") unlockall "S.unlockall_read() -> bool";
200         int unlockall_read();
201         %feature("docstring") reopen "S.reopen() -> bool\n"
202                                         "Reopen this file.";
203         int reopen();
204         %feature("docstring") transaction_start "S.transaction_start() -> None\n"
205                                         "Start a new transaction.";
206         int transaction_start();
207         %feature("docstring") transaction_commit "S.transaction_commit() -> None\n"
208                                         "Commit the currently active transaction.";
209         int transaction_commit();
210         %feature("docstring") transaction_cancel "S.transaction_cancel() -> None\n"
211                                         "Cancel the currently active transaction.";
212         int transaction_cancel();
213         int transaction_recover();
214         %feature("docstring") hash_size "S.hash_size() -> int";
215         int hash_size();
216         %feature("docstring") map_size "S.map_size() -> int";
217         size_t map_size();
218         %feature("docstring") get_flags "S.get_flags() -> int";
219         int get_flags();
220         %feature("docstring") set_max_dead "S.set_max_dead(int) -> None";
221         void set_max_dead(int max_dead);
222         %feature("docstring") name "S.name() -> path\n" \
223                                    "Return filename of this TDB file.";
224         const char *name();
225     }
226
227     %pythoncode {
228     def __repr__(self):
229         return "Tdb('%s')" % self.name()
230
231     # Random access to keys, values
232     def __getitem__(self, key):
233         result = self.get(key)
234         if result is None:
235             raise KeyError, '%s: %s' % (key, self.errorstr())
236         return result
237
238     def __setitem__(self, key, item):
239         if self.store(key, item) == -1:
240             raise IOError, self.errorstr()
241
242     def __delitem__(self, key):
243         if not self.exists(key):
244             raise KeyError, '%s: %s' % (key, self.errorstr())
245         self.delete(key)
246
247     def __contains__(self, key):
248         return self.exists(key) != 0
249
250     def has_key(self, key):
251         return self.exists(key) != 0
252
253     def fetch_uint32(self, key):
254         data = self.get(key)
255         if data is None:
256             return None
257         import struct
258         return struct.unpack("<L", data)[0]
259
260     def fetch_int32(self, key):
261         data = self.get(key)
262         if data is None:
263             return None
264         import struct
265         return struct.unpack("<l", data)[0]
266
267     # Tdb iterator
268     class TdbIterator:
269         def __init__(self, tdb):
270             self.tdb = tdb
271             self.key = None
272
273         def __iter__(self):
274             return self
275             
276         def next(self):
277             if self.key is None:
278                 self.key = self.tdb.firstkey()
279                 if self.key is None:
280                     raise StopIteration
281                 return self.key
282             else:
283                 self.key = self.tdb.nextkey(self.key)
284                 if self.key is None:
285                     raise StopIteration
286                 return self.key
287
288     def __iter__(self):
289         return self.TdbIterator(self)
290
291     # Implement other dict functions using TdbIterator
292
293     def keys(self):
294         return [k for k in iter(self)]
295
296     def values(self):
297         return [self[k] for k in iter(self)]
298
299     def items(self):
300         return [(k, self[k]) for k in iter(self)]
301
302     def __len__(self):
303         return len(self.keys())
304
305     def clear(self):
306         for k in iter(self):
307             del(self[k])
308
309     def iterkeys(self):
310         for k in iter(self):
311             yield k
312        
313     def itervalues(self):
314         for k in iter(self):
315             yield self[k]
316
317     def iteritems(self):
318         for k in iter(self):
319             yield (k, self[k])
320
321     # TODO: any other missing methods for container types
322     }
323 } tdb;
324
325 %pythoncode {
326 __docformat__ = 'restructuredText'
327 open = Tdb
328 }