933bfc7bb75d7d56a3a4ba729b9fea0f0f5da9d9
[ira/wip.git] / source / 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 %module tdb
28
29 %{
30
31 /* This symbol is used in both includes.h and Python.h which causes an
32    annoying compiler warning. */
33
34 #ifdef HAVE_FSTAT
35 #undef HAVE_FSTAT
36 #endif
37
38 /* Include tdb headers */
39 #include <stdint.h>
40 #include <signal.h>
41 #include <tdb.h>
42 #include <fcntl.h>
43
44 typedef TDB_CONTEXT tdb;
45 %}
46
47 /* The tdb functions will crash if a NULL tdb context is passed */
48
49 %import exception.i
50 %import stdint.i
51
52 %typemap(check,noblock=1) TDB_CONTEXT* {
53         if ($1 == NULL)
54                 SWIG_exception(SWIG_ValueError, 
55                         "tdb context must be non-NULL");
56 }
57
58 /* In and out typemaps for the TDB_DATA structure.  This is converted to
59    and from the Python string type which can contain arbitrary binary
60    data.. */
61
62 %typemap(in,noblock=1) TDB_DATA {
63     if ($input == Py_None) {
64         $1.dsize = 0;
65         $1.dptr = NULL;
66     } else if (!PyString_Check($input)) {
67                 PyErr_SetString(PyExc_TypeError, "string arg expected");
68                 return NULL;
69         } else {
70         $1.dsize = PyString_Size($input);
71         $1.dptr = (uint8_t *)PyString_AsString($input);
72     }
73 }
74
75 %typemap(out,noblock=1) TDB_DATA {
76         if ($1.dptr == NULL && $1.dsize == 0) {
77                 $result = Py_None;
78         } else {
79                 $result = PyString_FromStringAndSize((const char *)$1.dptr, $1.dsize);
80                 free($1.dptr);
81     }
82 }
83
84 /* Treat a mode_t as an unsigned integer */
85 typedef int mode_t;
86
87 /* flags to tdb_store() */
88 %constant int REPLACE = TDB_REPLACE;
89 %constant int INSERT = TDB_INSERT;
90 %constant int MODIFY = TDB_MODIFY;
91
92 /* flags for tdb_open() */
93 %constant int DEFAULT = TDB_DEFAULT;
94 %constant int CLEAR_IF_FIRST = TDB_CLEAR_IF_FIRST;
95 %constant int INTERNAL = TDB_INTERNAL;
96 %constant int NOLOCK = TDB_NOLOCK;
97 %constant int NOMMAP = TDB_NOMMAP;
98 %constant int CONVERT = TDB_CONVERT;
99 %constant int BIGENDIAN = TDB_BIGENDIAN;
100
101 enum TDB_ERROR {
102      TDB_SUCCESS=0, 
103      TDB_ERR_CORRUPT, 
104      TDB_ERR_IO, 
105      TDB_ERR_LOCK, 
106      TDB_ERR_OOM, 
107      TDB_ERR_EXISTS, 
108      TDB_ERR_NOLOCK, 
109      TDB_ERR_LOCK_TIMEOUT,
110      TDB_ERR_NOEXIST, 
111      TDB_ERR_EINVAL, 
112      TDB_ERR_RDONLY
113 };
114
115 %rename(lock_all) tdb_context::lockall;
116 %rename(unlock_all) tdb_context::unlockall;
117
118 %rename(read_lock_all) tdb_context::lockall_read;
119 %rename(read_unlock_all) tdb_context::unlockall_read;
120
121 %typemap(default,noblock=1) int tdb_flags {
122     $1 = TDB_DEFAULT;
123 }
124
125 %typemap(default,noblock=1) int open_flags {
126     $1 = O_RDWR;
127 }
128
129 %typemap(default,noblock=1) int hash_size {
130     $1 = 0;
131 }
132
133 %typemap(default,noblock=1) mode_t mode {
134     $1 = 0600;
135 }
136
137 %typemap(default,noblock=1) int flag {
138     $1 = TDB_REPLACE;
139 }
140
141 %rename(Tdb) tdb;
142 %typemap(out,noblock=1) tdb * {
143     /* Throw an IOError exception from errno if tdb_open() returns NULL */
144     if ($1 == NULL) {
145         PyErr_SetFromErrno(PyExc_IOError);
146         SWIG_fail;
147     }
148     $result = SWIG_NewPointerObj($1, $1_descriptor, 0);
149 }
150
151 typedef struct tdb_context {
152     %extend {
153         tdb(const char *name, int hash_size, int tdb_flags, int flags, mode_t mode) {
154             return tdb_open(name, hash_size, tdb_flags, flags, mode);
155         }
156         enum TDB_ERROR error();
157         ~tdb() { tdb_close($self); }
158         int close();
159         int append(TDB_DATA key, TDB_DATA new_dbuf);
160         const char *errorstr();
161         TDB_DATA fetch(TDB_DATA key);
162         int delete(TDB_DATA key);
163         int store(TDB_DATA key, TDB_DATA dbuf, int flag);
164         int exists(TDB_DATA key);
165         TDB_DATA firstkey();
166         TDB_DATA nextkey(TDB_DATA key);
167         int lockall();
168         int unlockall();
169         int lockall_read();
170         int unlockall_read();
171         int reopen();
172         int transaction_start();
173         int transaction_commit();
174         int transaction_cancel();
175         int transaction_recover();
176         int hash_size();
177         size_t map_size();
178         int get_flags();
179         void set_max_dead(int max_dead);
180         const char *name();
181     }
182
183     %pythoncode {
184     def __str__(self):
185         return self.name()
186
187     # Random access to keys, values
188     def __getitem__(self, key):
189         result = self.fetch(key)
190         if result is None:
191             raise KeyError, '%s: %s' % (key, self.errorstr())
192         return result
193
194     def __setitem__(self, key, item):
195         if self.store(key, item) == -1:
196             raise IOError, self.errorstr()
197
198     def __delitem__(self, key):
199         if not self.exists(key):
200             raise KeyError, '%s: %s' % (key, self.errorstr())
201         self.delete(key)
202
203     def __contains__(self, key):
204         return self.exists(key) != 0
205
206     def has_key(self, key):
207         return self.exists(key) != 0
208
209     def fetch_uint32(self, key):
210         data = self.fetch(key)
211         if data is None:
212             return None
213         import struct
214         return struct.unpack("<L", data)[0]
215
216     def fetch_int32(self, key):
217         data = self.fetch(key)
218         if data is None:
219             return None
220         import struct
221         return struct.unpack("<l", data)[0]
222
223     # Tdb iterator
224     class TdbIterator:
225         def __init__(self, tdb):
226             self.tdb = tdb
227             self.key = None
228
229         def __iter__(self):
230             return self
231             
232         def next(self):
233             if self.key is None:
234                 self.key = self.tdb.firstkey()
235                 if self.key is None:
236                     raise StopIteration
237                 return self.key
238             else:
239                 self.key = self.tdb.nextkey(self.key)
240                 if self.key is None:
241                     raise StopIteration
242                 return self.key
243
244     def __iter__(self):
245         return self.TdbIterator(self)
246
247     # Implement other dict functions using TdbIterator
248
249     def keys(self):
250         return [k for k in iter(self)]
251
252     def values(self):
253         return [self[k] for k in iter(self)]
254
255     def items(self):
256         return [(k, self[k]) for k in iter(self)]
257
258     def __len__(self):
259         return len(self.keys())
260
261     def clear(self):
262         for k in iter(self):
263             del(self[k])
264
265     # TODO: iterkeys, itervalues, iteritems
266
267     # TODO: any other missing methods for container types
268     }
269 } tdb;