1 /*************************************************************************************************
2  * C language binding
3  *                                                      Copyright (C) 2009-2012 Mikio Hirabayashi
4  * This file is part of Kyoto Cabinet.
5  * This program is free software: you can redistribute it and/or modify it under the terms of
6  * the GNU General Public License as published by the Free Software Foundation, either version
7  * 3 of the License, or any later version.
8  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along with this program.
12  * If not, see <http://www.gnu.org/licenses/>.
13  *************************************************************************************************/
14 
15 
16 #include "kcpolydb.h"
17 #include "kcdbext.h"
18 #include "kclangc.h"
19 #include "myconf.h"
20 
21 using namespace kyotocabinet;
22 
23 extern "C" {
24 
25 
26 /** The package version. */
27 const char* const KCVERSION = VERSION;
28 
29 
30 /** Special pointer for no operation by the visiting function. */
31 const char* const KCVISNOP = DB::Visitor::NOP;
32 
33 
34 /** Special pointer to remove the record by the visiting function. */
35 const char* const KCVISREMOVE = DB::Visitor::REMOVE;
36 
37 
38 /**
39  * Allocate a region on memory.
40  */
kcmalloc(size_t size)41 void* kcmalloc(size_t size) {
42   _assert_(size > 0 && size <= MEMMAXSIZ);
43   return new char[size];
44 }
45 
46 
47 /**
48  * Release a region allocated in the library.
49  */
kcfree(void * ptr)50 void kcfree(void* ptr) {
51   _assert_(true);
52   delete[] (char*)ptr;
53 }
54 
55 
56 /**
57  * Get the time of day in seconds.
58  */
kctime(void)59 double kctime(void) {
60   _assert_(true);
61   return kyotocabinet::time();
62 }
63 
64 
65 /**
66  * Convert a string to an integer.
67  */
kcatoi(const char * str)68 int64_t kcatoi(const char* str) {
69   _assert_(str);
70   return kyotocabinet::atoi(str);
71 }
72 
73 
74 /**
75  * Convert a string with a metric prefix to an integer.
76  */
kcatoix(const char * str)77 int64_t kcatoix(const char* str) {
78   _assert_(str);
79   return kyotocabinet::atoix(str);
80 }
81 
82 
83 /**
84  * Convert a string to a real number.
85  */
kcatof(const char * str)86 double kcatof(const char* str) {
87   _assert_(str);
88   return kyotocabinet::atof(str);
89 }
90 
91 
92 /**
93  * Get the hash value by MurMur hashing.
94  */
kchashmurmur(const void * buf,size_t size)95 uint64_t kchashmurmur(const void* buf, size_t size) {
96   _assert_(buf && size <= MEMMAXSIZ);
97   return kyotocabinet::hashmurmur(buf, size);
98 }
99 
100 
101 /**
102  * Get the hash value by FNV hashing.
103  */
kchashfnv(const void * buf,size_t size)104 uint64_t kchashfnv(const void* buf, size_t size) {
105   _assert_(buf && size <= MEMMAXSIZ);
106   return kyotocabinet::hashfnv(buf, size);
107 }
108 
109 
110 /**
111  * Calculate the levenshtein distance of two regions.
112  */
kclevdist(const void * abuf,size_t asiz,const void * bbuf,size_t bsiz,int32_t utf)113 size_t kclevdist(const void* abuf, size_t asiz, const void* bbuf, size_t bsiz, int32_t utf) {
114   _assert_(abuf && asiz <= MEMMAXSIZ && bbuf && bsiz <= MEMMAXSIZ);
115   size_t dist;
116   if (utf) {
117     uint32_t astack[128];
118     uint32_t* aary = asiz > sizeof(astack) / sizeof(*astack) ? new uint32_t[asiz] : astack;
119     size_t anum;
120     strutftoucs((const char*)abuf, asiz, aary, &anum);
121     uint32_t bstack[128];
122     uint32_t* bary = bsiz > sizeof(bstack) / sizeof(*bstack) ? new uint32_t[bsiz] : bstack;
123     size_t bnum;
124     strutftoucs((const char*)bbuf, bsiz, bary, &bnum);
125     dist = strucsdist(aary, anum, bary, bnum);
126     if (bary != bstack) delete[] bary;
127     if (aary != astack) delete[] aary;
128   } else {
129     dist = memdist(abuf, asiz, bbuf, bsiz);
130   }
131   return dist;
132 }
133 
134 
135 /**
136  * Get the quiet Not-a-Number value.
137  */
kcnan()138 double kcnan() {
139   _assert_(true);
140   return kyotocabinet::nan();
141 }
142 
143 
144 /**
145  * Get the positive infinity value.
146  */
kcinf()147 double kcinf() {
148   _assert_(true);
149   return kyotocabinet::inf();
150 }
151 
152 
153 /**
154  * Check a number is a Not-a-Number value.
155  */
kcchknan(double num)156 int32_t kcchknan(double num) {
157   _assert_(true);
158   return kyotocabinet::chknan(num);
159 }
160 
161 
162 /**
163  * Check a number is an infinity value.
164  */
kcchkinf(double num)165 int32_t kcchkinf(double num) {
166   _assert_(true);
167   return kyotocabinet::chkinf(num);
168 }
169 
170 
171 /**
172  * Get the readable string of an error code.
173  */
kcecodename(int32_t code)174 const char* kcecodename(int32_t code) {
175   _assert_(true);
176   return BasicDB::Error::codename((BasicDB::Error::Code)code);
177 }
178 
179 
180 /**
181  * Create a database object.
182  */
kcdbnew(void)183 KCDB* kcdbnew(void) {
184   _assert_(true);
185   return (KCDB*)new PolyDB;
186 }
187 
188 
189 /**
190  * Destroy a database object.
191  */
kcdbdel(KCDB * db)192 void kcdbdel(KCDB* db) {
193   _assert_(db);
194   PolyDB* pdb = (PolyDB*)db;
195   delete pdb;
196 }
197 
198 
199 /**
200  * Open a database file.
201  */
kcdbopen(KCDB * db,const char * path,uint32_t mode)202 int32_t kcdbopen(KCDB* db, const char* path, uint32_t mode) {
203   _assert_(db && path);
204   PolyDB* pdb = (PolyDB*)db;
205   return pdb->open(path, mode);
206 }
207 
208 
209 /**
210  * Close the database file.
211  */
kcdbclose(KCDB * db)212 int32_t kcdbclose(KCDB* db) {
213   _assert_(db);
214   PolyDB* pdb = (PolyDB*)db;
215   return pdb->close();
216 }
217 
218 
219 /**
220  * Get the code of the last happened error.
221  */
kcdbecode(KCDB * db)222 int32_t kcdbecode(KCDB* db) {
223   _assert_(db);
224   PolyDB* pdb = (PolyDB*)db;
225   return pdb->error().code();
226 }
227 
228 
229 /**
230  * Get the supplement message of the last happened error.
231  */
kcdbemsg(KCDB * db)232 const char* kcdbemsg(KCDB* db) {
233   _assert_(db);
234   PolyDB* pdb = (PolyDB*)db;
235   return pdb->error().message();
236 }
237 
238 
239 /**
240  * Accept a visitor to a record.
241  */
kcdbaccept(KCDB * db,const char * kbuf,size_t ksiz,KCVISITFULL fullproc,KCVISITEMPTY emptyproc,void * opq,int32_t writable)242 int32_t kcdbaccept(KCDB* db, const char* kbuf, size_t ksiz,
243                    KCVISITFULL fullproc, KCVISITEMPTY emptyproc, void* opq, int32_t writable) {
244   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
245   PolyDB* pdb = (PolyDB*)db;
246   class VisitorImpl : public DB::Visitor {
247    public:
248     explicit VisitorImpl(KCVISITFULL fullproc, KCVISITEMPTY emptyproc, void* opq) :
249         fullproc_(fullproc), emptyproc_(emptyproc), opq_(opq) {}
250     const char* visit_full(const char* kbuf, size_t ksiz,
251                            const char* vbuf, size_t vsiz, size_t* sp) {
252       if (!fullproc_) return NOP;
253       return fullproc_(kbuf, ksiz, vbuf, vsiz, sp, opq_);
254     }
255     const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
256       if (!emptyproc_) return NOP;
257       return emptyproc_(kbuf, ksiz, sp, opq_);
258     }
259    private:
260     KCVISITFULL fullproc_;
261     KCVISITEMPTY emptyproc_;
262     void* opq_;
263   };
264   VisitorImpl visitor(fullproc, emptyproc, opq);
265   return pdb->accept(kbuf, ksiz, &visitor, writable);
266 }
267 
268 
269 /**
270  * Accept a visitor to multiple records at once.
271  */
kcdbacceptbulk(KCDB * db,const KCSTR * keys,size_t knum,KCVISITFULL fullproc,KCVISITEMPTY emptyproc,void * opq,int32_t writable)272 int32_t kcdbacceptbulk(KCDB* db, const KCSTR* keys, size_t knum,
273                        KCVISITFULL fullproc, KCVISITEMPTY emptyproc,
274                        void* opq, int32_t writable) {
275   _assert_(db && keys && knum <= MEMMAXSIZ);
276   PolyDB* pdb = (PolyDB*)db;
277   std::vector<std::string> xkeys;
278   xkeys.reserve(knum);
279   for (size_t i = 0; i < knum; i++) {
280     xkeys.push_back(std::string(keys[i].buf, keys[i].size));
281   }
282   class VisitorImpl : public DB::Visitor {
283    public:
284     explicit VisitorImpl(KCVISITFULL fullproc, KCVISITEMPTY emptyproc, void* opq) :
285         fullproc_(fullproc), emptyproc_(emptyproc), opq_(opq) {}
286     const char* visit_full(const char* kbuf, size_t ksiz,
287                            const char* vbuf, size_t vsiz, size_t* sp) {
288       if (!fullproc_) return NOP;
289       return fullproc_(kbuf, ksiz, vbuf, vsiz, sp, opq_);
290     }
291     const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
292       if (!emptyproc_) return NOP;
293       return emptyproc_(kbuf, ksiz, sp, opq_);
294     }
295    private:
296     KCVISITFULL fullproc_;
297     KCVISITEMPTY emptyproc_;
298     void* opq_;
299   };
300   VisitorImpl visitor(fullproc, emptyproc, opq);
301   return pdb->accept_bulk(xkeys, &visitor, writable);
302 }
303 
304 
305 /**
306  * Iterate to accept a visitor for each record.
307  */
kcdbiterate(KCDB * db,KCVISITFULL fullproc,void * opq,int32_t writable)308 int32_t kcdbiterate(KCDB* db, KCVISITFULL fullproc, void* opq, int32_t writable) {
309   _assert_(db);
310   PolyDB* pdb = (PolyDB*)db;
311   class VisitorImpl : public DB::Visitor {
312    public:
313     explicit VisitorImpl(KCVISITFULL fullproc, void* opq) : fullproc_(fullproc), opq_(opq) {}
314     const char* visit_full(const char* kbuf, size_t ksiz,
315                            const char* vbuf, size_t vsiz, size_t* sp) {
316       if (!fullproc_) return NOP;
317       return fullproc_(kbuf, ksiz, vbuf, vsiz, sp, opq_);
318     }
319    private:
320     KCVISITFULL fullproc_;
321     void* opq_;
322   };
323   VisitorImpl visitor(fullproc, opq);
324   return pdb->iterate(&visitor, writable);
325 }
326 
327 
328 /**
329  * Scan each record in parallel.
330  */
kcdbscanpara(KCDB * db,KCVISITFULL fullproc,void * opq,size_t thnum)331 int32_t kcdbscanpara(KCDB* db, KCVISITFULL fullproc, void* opq, size_t thnum) {
332   _assert_(db && thnum <= MEMMAXSIZ);
333   PolyDB* pdb = (PolyDB*)db;
334   class VisitorImpl : public DB::Visitor {
335    public:
336     explicit VisitorImpl(KCVISITFULL fullproc, void* opq) : fullproc_(fullproc), opq_(opq) {}
337     const char* visit_full(const char* kbuf, size_t ksiz,
338                            const char* vbuf, size_t vsiz, size_t* sp) {
339       if (!fullproc_) return NOP;
340       return fullproc_(kbuf, ksiz, vbuf, vsiz, sp, opq_);
341     }
342    private:
343     KCVISITFULL fullproc_;
344     void* opq_;
345   };
346   VisitorImpl visitor(fullproc, opq);
347   return pdb->scan_parallel(&visitor, thnum);
348 }
349 
350 
351 /**
352  * Set the value of a record.
353  */
kcdbset(KCDB * db,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)354 int32_t kcdbset(KCDB* db, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
355   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
356   PolyDB* pdb = (PolyDB*)db;
357   return pdb->set(kbuf, ksiz, vbuf, vsiz);
358 }
359 
360 
361 /**
362  * Add a record.
363  */
kcdbadd(KCDB * db,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)364 int32_t kcdbadd(KCDB* db, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
365   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
366   PolyDB* pdb = (PolyDB*)db;
367   return pdb->add(kbuf, ksiz, vbuf, vsiz);
368 }
369 
370 
371 /**
372  * Replace the value of a record.
373  */
kcdbreplace(KCDB * db,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)374 int32_t kcdbreplace(KCDB* db, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
375   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
376   PolyDB* pdb = (PolyDB*)db;
377   return pdb->replace(kbuf, ksiz, vbuf, vsiz);
378 }
379 
380 
381 /**
382  * Append the value of a record.
383  */
kcdbappend(KCDB * db,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)384 int32_t kcdbappend(KCDB* db, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
385   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
386   PolyDB* pdb = (PolyDB*)db;
387   return pdb->append(kbuf, ksiz, vbuf, vsiz);
388 }
389 
390 
391 /**
392  * Add a number to the numeric value of a record.
393  */
kcdbincrint(KCDB * db,const char * kbuf,size_t ksiz,int64_t num,int64_t orig)394 int64_t kcdbincrint(KCDB* db, const char* kbuf, size_t ksiz, int64_t num, int64_t orig) {
395   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
396   PolyDB* pdb = (PolyDB*)db;
397   return pdb->increment(kbuf, ksiz, num, orig);
398 }
399 
400 
401 /**
402  * Add a number to the numeric value of a record.
403  */
kcdbincrdouble(KCDB * db,const char * kbuf,size_t ksiz,double num,double orig)404 double kcdbincrdouble(KCDB* db, const char* kbuf, size_t ksiz, double num, double orig) {
405   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
406   PolyDB* pdb = (PolyDB*)db;
407   return pdb->increment_double(kbuf, ksiz, num, orig);
408 }
409 
410 
411 /**
412  * Perform compare-and-swap.
413  */
kcdbcas(KCDB * db,const char * kbuf,size_t ksiz,const char * ovbuf,size_t ovsiz,const char * nvbuf,size_t nvsiz)414 int32_t kcdbcas(KCDB* db, const char* kbuf, size_t ksiz,
415                 const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz) {
416   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
417   PolyDB* pdb = (PolyDB*)db;
418   return pdb->cas(kbuf, ksiz, ovbuf, ovsiz, nvbuf, nvsiz);
419 }
420 
421 
422 /**
423  * Remove a record.
424  */
kcdbremove(KCDB * db,const char * kbuf,size_t ksiz)425 int32_t kcdbremove(KCDB* db, const char* kbuf, size_t ksiz) {
426   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
427   PolyDB* pdb = (PolyDB*)db;
428   return pdb->remove(kbuf, ksiz);
429 }
430 
431 
432 /**
433  * Retrieve the value of a record.
434  */
kcdbget(KCDB * db,const char * kbuf,size_t ksiz,size_t * sp)435 char* kcdbget(KCDB* db, const char* kbuf, size_t ksiz, size_t* sp) {
436   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && sp);
437   PolyDB* pdb = (PolyDB*)db;
438   return pdb->get(kbuf, ksiz, sp);
439 }
440 
441 
442 /**
443  * Check the existence of a record.
444  */
kcdbcheck(KCDB * db,const char * kbuf,size_t ksiz)445 int32_t kcdbcheck(KCDB* db, const char* kbuf, size_t ksiz) {
446   _assert_(db && kbuf && ksiz <= MEMMAXSIZ);
447   PolyDB* pdb = (PolyDB*)db;
448   return pdb->check(kbuf, ksiz);
449 }
450 
451 
452 /**
453  * Retrieve the value of a record.
454  */
kcdbgetbuf(KCDB * db,const char * kbuf,size_t ksiz,char * vbuf,size_t max)455 int32_t kcdbgetbuf(KCDB* db, const char* kbuf, size_t ksiz, char* vbuf, size_t max) {
456   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && vbuf);
457   PolyDB* pdb = (PolyDB*)db;
458   return pdb->get(kbuf, ksiz, vbuf, max);
459 }
460 
461 
462 /**
463  * Retrieve the value of a record and remove it atomically.
464  */
kcdbseize(KCDB * db,const char * kbuf,size_t ksiz,size_t * sp)465 char* kcdbseize(KCDB* db, const char* kbuf, size_t ksiz, size_t* sp) {
466   _assert_(db && kbuf && ksiz <= MEMMAXSIZ && sp);
467   PolyDB* pdb = (PolyDB*)db;
468   return pdb->seize(kbuf, ksiz, sp);
469 }
470 
471 
472 /**
473  * Store records at once.
474  */
kcdbsetbulk(KCDB * db,const KCREC * recs,size_t rnum,int32_t atomic)475 int64_t kcdbsetbulk(KCDB* db, const KCREC* recs, size_t rnum, int32_t atomic) {
476   _assert_(db && recs && rnum <= MEMMAXSIZ);
477   PolyDB* pdb = (PolyDB*)db;
478   std::map<std::string, std::string> xrecs;
479   for (size_t i = 0; i < rnum; i++) {
480     const KCREC* rec = recs + i;
481     xrecs[std::string(rec->key.buf, rec->key.size)] =
482         std::string(rec->value.buf, rec->value.size);
483   }
484   return pdb->set_bulk(xrecs, atomic);
485 }
486 
487 
488 /**
489  * Remove records at once.
490  */
kcdbremovebulk(KCDB * db,const KCSTR * keys,size_t knum,int32_t atomic)491 int64_t kcdbremovebulk(KCDB* db, const KCSTR* keys, size_t knum, int32_t atomic) {
492   _assert_(db && keys && knum <= MEMMAXSIZ);
493   PolyDB* pdb = (PolyDB*)db;
494   std::vector<std::string> xkeys;
495   xkeys.reserve(knum);
496   for (size_t i = 0; i < knum; i++) {
497     const KCSTR* key = keys + i;
498     xkeys.push_back(std::string(key->buf, key->size));
499   }
500   return pdb->remove_bulk(xkeys, atomic);
501 }
502 
503 
504 /**
505  * Retrieve records at once.
506  */
kcdbgetbulk(KCDB * db,const KCSTR * keys,size_t knum,KCREC * recs,int32_t atomic)507 int64_t kcdbgetbulk(KCDB* db, const KCSTR* keys, size_t knum, KCREC* recs, int32_t atomic) {
508   _assert_(db && keys && knum <= MEMMAXSIZ && recs);
509   PolyDB* pdb = (PolyDB*)db;
510   std::vector<std::string> xkeys;
511   xkeys.reserve(knum);
512   for (size_t i = 0; i < knum; i++) {
513     const KCSTR* key = keys + i;
514     xkeys.push_back(std::string(key->buf, key->size));
515   }
516   std::map<std::string, std::string> xrecs;
517   if (pdb->get_bulk(xkeys, &xrecs, atomic) < 0) return -1;
518   std::map<std::string, std::string>::iterator it = xrecs.begin();
519   std::map<std::string, std::string>::iterator itend = xrecs.end();
520   size_t ridx = 0;
521   while (ridx < knum && it != itend) {
522     size_t ksiz = it->first.size();
523     char* kbuf = new char[ksiz+1];
524     std::memcpy(kbuf, it->first.data(), ksiz);
525     kbuf[ksiz] = '\0';
526     size_t vsiz = it->second.size();
527     char* vbuf = new char[vsiz+1];
528     std::memcpy(vbuf, it->second.data(), vsiz);
529     vbuf[vsiz] = '\0';
530     KCREC* rec = recs + (ridx++);
531     rec->key.buf = kbuf;
532     rec->key.size = ksiz;
533     rec->value.buf = vbuf;
534     rec->value.size = vsiz;
535     ++it;
536   }
537   return ridx;
538 }
539 
540 
541 /**
542  * Synchronize updated contents with the file and the device.
543  */
kcdbsync(KCDB * db,int32_t hard,KCFILEPROC proc,void * opq)544 int32_t kcdbsync(KCDB* db, int32_t hard, KCFILEPROC proc, void* opq) {
545   _assert_(db);
546   PolyDB* pdb = (PolyDB*)db;
547   class FileProcessorImpl : public BasicDB::FileProcessor {
548    public:
549     explicit FileProcessorImpl(KCFILEPROC proc, void* opq) : proc_(proc), opq_(opq) {}
550     bool process(const std::string& path, int64_t count, int64_t size) {
551       if (!proc_) return true;
552       return proc_(path.c_str(), count, size, opq_);
553     }
554    private:
555     KCFILEPROC proc_;
556     void* opq_;
557   };
558   FileProcessorImpl myproc(proc, opq);
559   return pdb->synchronize(hard, &myproc);
560 }
561 
562 
563 /**
564  * Occupy database by locking and do something meanwhile.
565  */
kcdboccupy(KCDB * db,int32_t writable,KCFILEPROC proc,void * opq)566 int32_t kcdboccupy(KCDB* db, int32_t writable, KCFILEPROC proc, void* opq) {
567   _assert_(db);
568   PolyDB* pdb = (PolyDB*)db;
569   class FileProcessorImpl : public BasicDB::FileProcessor {
570    public:
571     explicit FileProcessorImpl(KCFILEPROC proc, void* opq) : proc_(proc), opq_(opq) {}
572     bool process(const std::string& path, int64_t count, int64_t size) {
573       if (!proc_) return true;
574       return proc_(path.c_str(), count, size, opq_);
575     }
576    private:
577     KCFILEPROC proc_;
578     void* opq_;
579   };
580   FileProcessorImpl myproc(proc, opq);
581   return pdb->occupy(writable, &myproc);
582 }
583 
584 
585 /**
586  * Create a copy of the database file.
587  */
kcdbcopy(KCDB * db,const char * dest)588 int32_t kcdbcopy(KCDB* db, const char* dest) {
589   _assert_(db && dest);
590   PolyDB* pdb = (PolyDB*)db;
591   return pdb->copy(dest);
592 }
593 
594 
595 /**
596  * Begin transaction.
597  */
kcdbbegintran(KCDB * db,int32_t hard)598 int32_t kcdbbegintran(KCDB* db, int32_t hard) {
599   _assert_(db);
600   PolyDB* pdb = (PolyDB*)db;
601   return pdb->begin_transaction(hard);
602 }
603 
604 
605 /**
606  * Try to begin transaction.
607  */
kcdbbegintrantry(KCDB * db,int32_t hard)608 int32_t kcdbbegintrantry(KCDB* db, int32_t hard) {
609   _assert_(db);
610   PolyDB* pdb = (PolyDB*)db;
611   return pdb->begin_transaction_try(hard);
612 }
613 
614 
615 /**
616  * End transaction.
617  */
kcdbendtran(KCDB * db,int32_t commit)618 int32_t kcdbendtran(KCDB* db, int32_t commit) {
619   _assert_(db);
620   PolyDB* pdb = (PolyDB*)db;
621   return pdb->end_transaction(commit);
622 }
623 
624 
625 /**
626  * Remove all records.
627  */
kcdbclear(KCDB * db)628 int32_t kcdbclear(KCDB* db) {
629   _assert_(db);
630   PolyDB* pdb = (PolyDB*)db;
631   return pdb->clear();
632 }
633 
634 
635 /**
636  * Dump records into a file.
637  */
kcdbdumpsnap(KCDB * db,const char * dest)638 int32_t kcdbdumpsnap(KCDB* db, const char* dest) {
639   _assert_(db && dest);
640   PolyDB* pdb = (PolyDB*)db;
641   return pdb->dump_snapshot(dest);
642 }
643 
644 
645 /**
646  * Load records from a file.
647  */
kcdbloadsnap(KCDB * db,const char * src)648 int32_t kcdbloadsnap(KCDB* db, const char* src) {
649   _assert_(db && src);
650   PolyDB* pdb = (PolyDB*)db;
651   return pdb->load_snapshot(src);
652 }
653 
654 
655 /**
656  * Get the number of records.
657  */
kcdbcount(KCDB * db)658 int64_t kcdbcount(KCDB* db) {
659   _assert_(db);
660   PolyDB* pdb = (PolyDB*)db;
661   return pdb->count();
662 }
663 
664 
665 /**
666  * Get the size of the database file.
667  */
kcdbsize(KCDB * db)668 int64_t kcdbsize(KCDB* db) {
669   _assert_(db);
670   PolyDB* pdb = (PolyDB*)db;
671   return pdb->size();
672 }
673 
674 
675 /**
676  * Get the path of the database file.
677  */
kcdbpath(KCDB * db)678 char* kcdbpath(KCDB* db) {
679   _assert_(db);
680   PolyDB* pdb = (PolyDB*)db;
681   std::string path = pdb->path();
682   size_t psiz = path.size();
683   char* pbuf = new char[psiz+1];
684   std::memcpy(pbuf, path.c_str(), psiz + 1);
685   return pbuf;
686 }
687 
688 
689 /**
690  * Get the miscellaneous status information.
691  */
kcdbstatus(KCDB * db)692 char* kcdbstatus(KCDB* db) {
693   _assert_(db);
694   PolyDB* pdb = (PolyDB*)db;
695   std::map<std::string, std::string> status;
696   if (!pdb->status(&status)) return NULL;
697   std::ostringstream obuf;
698   std::map<std::string, std::string>::iterator it = status.begin();
699   std::map<std::string, std::string>::iterator itend = status.end();
700   while (it != itend) {
701     obuf << it->first << "\t" << it->second << "\n";
702     ++it;
703   }
704   std::string sstr = obuf.str();
705   size_t ssiz = sstr.size();
706   char* sbuf = new char[ssiz+1];
707   std::memcpy(sbuf, sstr.c_str(), ssiz + 1);
708   return sbuf;
709 }
710 
711 
712 /**
713  * Get keys matching a prefix string.
714  */
kcdbmatchprefix(KCDB * db,const char * prefix,char ** strary,size_t max)715 int64_t kcdbmatchprefix(KCDB* db, const char* prefix, char** strary, size_t max) {
716   _assert_(db && prefix && strary && max <= MEMMAXSIZ);
717   PolyDB* pdb = (PolyDB*)db;
718   std::vector<std::string> strvec;
719   if (pdb->match_prefix(prefix, &strvec, max) == -1) return -1;
720   int64_t cnt = 0;
721   std::vector<std::string>::iterator it = strvec.begin();
722   std::vector<std::string>::iterator itend = strvec.end();
723   while (it != itend) {
724     size_t ksiz = it->size();
725     char* kbuf = new char[ksiz+1];
726     std::memcpy(kbuf, it->data(), ksiz);
727     kbuf[ksiz] = '\0';
728     strary[cnt++] = kbuf;
729     ++it;
730   }
731   return cnt;
732 }
733 
734 
735 /**
736  * Get keys matching a regular expression string.
737  */
kcdbmatchregex(KCDB * db,const char * regex,char ** strary,size_t max)738 int64_t kcdbmatchregex(KCDB* db, const char* regex, char** strary, size_t max) {
739   _assert_(db && regex && strary && max <= MEMMAXSIZ);
740   PolyDB* pdb = (PolyDB*)db;
741   std::vector<std::string> strvec;
742   if (pdb->match_regex(regex, &strvec, max) == -1) return -1;
743   int64_t cnt = 0;
744   std::vector<std::string>::iterator it = strvec.begin();
745   std::vector<std::string>::iterator itend = strvec.end();
746   while (it != itend) {
747     size_t ksiz = it->size();
748     char* kbuf = new char[ksiz+1];
749     std::memcpy(kbuf, it->data(), ksiz);
750     kbuf[ksiz] = '\0';
751     strary[cnt++] = kbuf;
752     ++it;
753   }
754   return cnt;
755 }
756 
757 
758 /**
759  * Get keys similar to a string in terms of the levenshtein distance.
760  */
kcdbmatchsimilar(KCDB * db,const char * origin,uint32_t range,int32_t utf,char ** strary,size_t max)761 int64_t kcdbmatchsimilar(KCDB* db, const char* origin, uint32_t range, int32_t utf,
762                          char** strary, size_t max) {
763   _assert_(db && origin && strary && max <= MEMMAXSIZ);
764   PolyDB* pdb = (PolyDB*)db;
765   std::vector<std::string> strvec;
766   if (pdb->match_similar(origin, range, utf, &strvec, max) == -1) return -1;
767   int64_t cnt = 0;
768   std::vector<std::string>::iterator it = strvec.begin();
769   std::vector<std::string>::iterator itend = strvec.end();
770   while (it != itend) {
771     size_t ksiz = it->size();
772     char* kbuf = new char[ksiz+1];
773     std::memcpy(kbuf, it->data(), ksiz);
774     kbuf[ksiz] = '\0';
775     strary[cnt++] = kbuf;
776     ++it;
777   }
778   return cnt;
779 }
780 
781 
782 /**
783  * Merge records from other databases.
784  */
kcdbmerge(KCDB * db,KCDB ** srcary,size_t srcnum,uint32_t mode)785 int32_t kcdbmerge(KCDB* db, KCDB** srcary, size_t srcnum, uint32_t mode) {
786   _assert_(db && srcary && srcnum <= MEMMAXSIZ);
787   PolyDB* pdb = (PolyDB*)db;
788   return pdb->merge((BasicDB**)srcary, srcnum, (PolyDB::MergeMode)mode);
789 }
790 
791 
792 /**
793  * Create a cursor object.
794  */
kcdbcursor(KCDB * db)795 KCCUR* kcdbcursor(KCDB* db) {
796   _assert_(db);
797   PolyDB* pdb = (PolyDB*)db;
798   return (KCCUR*)pdb->cursor();
799 }
800 
801 
802 /**
803  * Destroy a cursor object.
804  */
kccurdel(KCCUR * cur)805 void kccurdel(KCCUR* cur) {
806   _assert_(cur);
807   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
808   delete pcur;
809 }
810 
811 
812 /**
813  * Accept a visitor to the current record.
814  */
kccuraccept(KCCUR * cur,KCVISITFULL fullproc,void * opq,int32_t writable,int32_t step)815 int32_t kccuraccept(KCCUR* cur, KCVISITFULL fullproc, void* opq,
816                     int32_t writable, int32_t step) {
817   _assert_(cur);
818   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
819   class VisitorImpl : public DB::Visitor {
820    public:
821     explicit VisitorImpl(KCVISITFULL fullproc, void* opq) : fullproc_(fullproc), opq_(opq) {}
822     const char* visit_full(const char* kbuf, size_t ksiz,
823                            const char* vbuf, size_t vsiz, size_t* sp) {
824       if (!fullproc_) return NOP;
825       return fullproc_(kbuf, ksiz, vbuf, vsiz, sp, opq_);
826     }
827    private:
828     KCVISITFULL fullproc_;
829     void* opq_;
830   };
831   VisitorImpl visitor(fullproc, opq);
832   return pcur->accept(&visitor, writable, step);
833 }
834 
835 
836 /**
837  * Set the value of the current record.
838  */
kccursetvalue(KCCUR * cur,const char * vbuf,size_t vsiz,int32_t step)839 int32_t kccursetvalue(KCCUR* cur, const char* vbuf, size_t vsiz, int32_t step) {
840   _assert_(cur && vbuf && vsiz <= MEMMAXSIZ);
841   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
842   return pcur->set_value(vbuf, vsiz, step);
843 }
844 
845 
846 /**
847  * Remove the current record.
848  */
kccurremove(KCCUR * cur)849 int32_t kccurremove(KCCUR* cur) {
850   _assert_(cur);
851   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
852   return pcur->remove();
853 }
854 
855 
856 /**
857  * Get the key of the current record.
858  */
kccurgetkey(KCCUR * cur,size_t * sp,int32_t step)859 char* kccurgetkey(KCCUR* cur, size_t* sp, int32_t step) {
860   _assert_(cur && sp);
861   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
862   return pcur->get_key(sp, step);
863 }
864 
865 
866 /**
867  * Get the value of the current record.
868  */
kccurgetvalue(KCCUR * cur,size_t * sp,int32_t step)869 char* kccurgetvalue(KCCUR* cur, size_t* sp, int32_t step) {
870   _assert_(cur && sp);
871   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
872   return pcur->get_value(sp, step);
873 }
874 
875 
876 /**
877  * Get a pair of the key and the value of the current record.
878  */
kccurget(KCCUR * cur,size_t * ksp,const char ** vbp,size_t * vsp,int32_t step)879 char* kccurget(KCCUR* cur, size_t* ksp, const char** vbp, size_t* vsp, int32_t step) {
880   _assert_(cur && ksp && vbp && vsp);
881   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
882   return pcur->get(ksp, vbp, vsp, step);
883 }
884 
885 
886 /**
887  * Get a pair of the key and the value of the current record and remove it atomically.
888  */
kccurseize(KCCUR * cur,size_t * ksp,const char ** vbp,size_t * vsp)889 char* kccurseize(KCCUR* cur, size_t* ksp, const char** vbp, size_t* vsp) {
890   _assert_(cur && ksp && vbp && vsp);
891   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
892   return pcur->seize(ksp, vbp, vsp);
893 }
894 
895 
896 /**
897  * Jump the cursor to the first record.
898  */
kccurjump(KCCUR * cur)899 int32_t kccurjump(KCCUR* cur) {
900   _assert_(cur);
901   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
902   return pcur->jump();
903 }
904 
905 
906 /**
907  * Jump the cursor to a record.
908  */
kccurjumpkey(KCCUR * cur,const char * kbuf,size_t ksiz)909 int32_t kccurjumpkey(KCCUR* cur, const char* kbuf, size_t ksiz) {
910   _assert_(cur && kbuf && ksiz <= MEMMAXSIZ);
911   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
912   return pcur->jump(kbuf, ksiz);
913 }
914 
915 
916 /**
917  * Jump the cursor to the last record for backward scan.
918  */
kccurjumpback(KCCUR * cur)919 int32_t kccurjumpback(KCCUR* cur) {
920   _assert_(cur);
921   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
922   return pcur->jump_back();
923 }
924 
925 
926 /**
927  * Jump the cursor to a record for backward scan.
928  */
kccurjumpbackkey(KCCUR * cur,const char * kbuf,size_t ksiz)929 int32_t kccurjumpbackkey(KCCUR* cur, const char* kbuf, size_t ksiz) {
930   _assert_(cur && kbuf && ksiz <= MEMMAXSIZ);
931   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
932   return pcur->jump_back(kbuf, ksiz);
933 }
934 
935 
936 /**
937  * Step the cursor to the next record.
938  */
kccurstep(KCCUR * cur)939 int32_t kccurstep(KCCUR* cur) {
940   _assert_(cur);
941   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
942   return pcur->step();
943 }
944 
945 
946 /**
947  * Step the cursor to the previous record.
948  */
kccurstepback(KCCUR * cur)949 int32_t kccurstepback(KCCUR* cur) {
950   _assert_(cur);
951   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
952   return pcur->step_back();
953 }
954 
955 
956 /**
957  * Get the database object.
958  */
kccurdb(KCCUR * cur)959 KCDB* kccurdb(KCCUR* cur) {
960   _assert_(cur);
961   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
962   return (KCDB*)pcur->db();
963 }
964 
965 
966 /**
967  * Get the code of the last happened error.
968  */
kccurecode(KCCUR * cur)969 int32_t kccurecode(KCCUR* cur) {
970   _assert_(cur);
971   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
972   return pcur->error().code();
973 }
974 
975 
976 /**
977  * Get the supplement message of the last happened error.
978  */
kccuremsg(KCCUR * cur)979 const char* kccuremsg(KCCUR* cur) {
980   _assert_(cur);
981   PolyDB::Cursor* pcur = (PolyDB::Cursor*)cur;
982   return pcur->error().message();
983 }
984 
985 
986 /**
987  * Create an index database object.
988  */
kcidxnew(void)989 KCIDX* kcidxnew(void) {
990   _assert_(true);
991   return (KCIDX*)new IndexDB;
992 }
993 
994 
995 /**
996  * Destroy a database object.
997  */
kcidxdel(KCIDX * idx)998 void kcidxdel(KCIDX* idx) {
999   _assert_(idx);
1000   IndexDB* idb = (IndexDB*)idx;
1001   delete idb;
1002 }
1003 
1004 
1005 /**
1006  * Open a database file.
1007  */
kcidxopen(KCIDX * idx,const char * path,uint32_t mode)1008 int32_t kcidxopen(KCIDX* idx, const char* path, uint32_t mode) {
1009   _assert_(idx && path);
1010   IndexDB* idb = (IndexDB*)idx;
1011   return idb->open(path, mode);
1012 }
1013 
1014 
1015 /**
1016  * Close the database file.
1017  */
kcidxclose(KCIDX * idx)1018 int32_t kcidxclose(KCIDX* idx) {
1019   _assert_(idx);
1020   IndexDB* idb = (IndexDB*)idx;
1021   return idb->close();
1022 }
1023 
1024 
1025 /**
1026  * Get the code of the last happened error.
1027  */
kcidxecode(KCIDX * idx)1028 int32_t kcidxecode(KCIDX* idx) {
1029   _assert_(idx);
1030   IndexDB* idb = (IndexDB*)idx;
1031   return idb->error().code();
1032 }
1033 
1034 
1035 /**
1036  * Get the supplement message of the last happened error.
1037  */
kcidxemsg(KCIDX * idx)1038 const char* kcidxemsg(KCIDX* idx) {
1039   _assert_(idx);
1040   IndexDB* idb = (IndexDB*)idx;
1041   return idb->error().message();
1042 }
1043 
1044 
1045 /**
1046  * Set the value of a record.
1047  */
kcidxset(KCIDX * idx,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1048 int32_t kcidxset(KCIDX* idx, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1049   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1050   IndexDB* idb = (IndexDB*)idx;
1051   return idb->set(kbuf, ksiz, vbuf, vsiz);
1052 }
1053 
1054 
1055 /**
1056  * Add a record.
1057  */
kcidxadd(KCIDX * idx,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1058 int32_t kcidxadd(KCIDX* idx, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1059   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1060   IndexDB* idb = (IndexDB*)idx;
1061   return idb->add(kbuf, ksiz, vbuf, vsiz);
1062 }
1063 
1064 
1065 /**
1066  * Replace the value of a record.
1067  */
kcidxreplace(KCIDX * idx,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1068 int32_t kcidxreplace(KCIDX* idx, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1069   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1070   IndexDB* idb = (IndexDB*)idx;
1071   return idb->replace(kbuf, ksiz, vbuf, vsiz);
1072 }
1073 
1074 
1075 /**
1076  * Append the value of a record.
1077  */
kcidxappend(KCIDX * idx,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1078 int32_t kcidxappend(KCIDX* idx, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1079   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1080   IndexDB* idb = (IndexDB*)idx;
1081   return idb->append(kbuf, ksiz, vbuf, vsiz);
1082 }
1083 
1084 
1085 /**
1086  * Remove a record.
1087  */
kcidxremove(KCIDX * idx,const char * kbuf,size_t ksiz)1088 int32_t kcidxremove(KCIDX* idx, const char* kbuf, size_t ksiz) {
1089   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ);
1090   IndexDB* idb = (IndexDB*)idx;
1091   return idb->remove(kbuf, ksiz);
1092 }
1093 
1094 
1095 /**
1096  * Retrieve the value of a record.
1097  */
kcidxget(KCIDX * idx,const char * kbuf,size_t ksiz,size_t * sp)1098 char* kcidxget(KCIDX* idx, const char* kbuf, size_t ksiz, size_t* sp) {
1099   _assert_(idx && kbuf && ksiz <= MEMMAXSIZ && sp);
1100   IndexDB* idb = (IndexDB*)idx;
1101   return idb->get(kbuf, ksiz, sp);
1102 }
1103 
1104 
1105 /**
1106  * Synchronize updated contents with the file and the device.
1107  */
kcidxsync(KCIDX * idx,int32_t hard,KCFILEPROC proc,void * opq)1108 int32_t kcidxsync(KCIDX* idx, int32_t hard, KCFILEPROC proc, void* opq) {
1109   _assert_(idx);
1110   IndexDB* idb = (IndexDB*)idx;
1111   class FileProcessorImpl : public BasicDB::FileProcessor {
1112    public:
1113     explicit FileProcessorImpl(KCFILEPROC proc, void* opq) : proc_(proc), opq_(opq) {}
1114     bool process(const std::string& path, int64_t count, int64_t size) {
1115       if (!proc_) return true;
1116       return proc_(path.c_str(), count, size, opq_);
1117     }
1118    private:
1119     KCFILEPROC proc_;
1120     void* opq_;
1121   };
1122   FileProcessorImpl myproc(proc, opq);
1123   return idb->synchronize(hard, &myproc);
1124 }
1125 
1126 
1127 /**
1128  * Remove all records.
1129  */
kcidxclear(KCIDX * idx)1130 int32_t kcidxclear(KCIDX* idx) {
1131   _assert_(idx);
1132   IndexDB* idb = (IndexDB*)idx;
1133   return idb->clear();
1134 }
1135 
1136 
1137 /**
1138  * Get the number of records.
1139  */
kcidxcount(KCIDX * idx)1140 int64_t kcidxcount(KCIDX* idx) {
1141   _assert_(idx);
1142   IndexDB* idb = (IndexDB*)idx;
1143   return idb->count();
1144 }
1145 
1146 
1147 /**
1148  * Get the size of the database file.
1149  */
kcidxsize(KCIDX * idx)1150 int64_t kcidxsize(KCIDX* idx) {
1151   _assert_(idx);
1152   IndexDB* idb = (IndexDB*)idx;
1153   return idb->size();
1154 }
1155 
1156 
1157 /**
1158  * Get the path of the database file.
1159  */
kcidxpath(KCIDX * idx)1160 char* kcidxpath(KCIDX* idx) {
1161   _assert_(idx);
1162   IndexDB* idb = (IndexDB*)idx;
1163   std::string path = idb->path();
1164   size_t psiz = path.size();
1165   char* pbuf = new char[psiz+1];
1166   std::memcpy(pbuf, path.c_str(), psiz + 1);
1167   return pbuf;
1168 }
1169 
1170 
1171 /**
1172  * Get the miscellaneous status information.
1173  */
kcidxstatus(KCIDX * idx)1174 char* kcidxstatus(KCIDX* idx) {
1175   _assert_(idx);
1176   IndexDB* idb = (IndexDB*)idx;
1177   std::map<std::string, std::string> status;
1178   if (!idb->status(&status)) return NULL;
1179   std::ostringstream obuf;
1180   std::map<std::string, std::string>::iterator it = status.begin();
1181   std::map<std::string, std::string>::iterator itend = status.end();
1182   while (it != itend) {
1183     obuf << it->first << "\t" << it->second << "\n";
1184     ++it;
1185   }
1186   std::string sstr = obuf.str();
1187   size_t ssiz = sstr.size();
1188   char* sbuf = new char[ssiz+1];
1189   std::memcpy(sbuf, sstr.c_str(), ssiz + 1);
1190   return sbuf;
1191 }
1192 
1193 
1194 /**
1195  * Reveal the inner database object.
1196  */
kcidxrevealinnerdb(KCIDX * idx)1197 KCDB* kcidxrevealinnerdb(KCIDX* idx) {
1198   _assert_(idx);
1199   IndexDB* idb = (IndexDB*)idx;
1200   return (KCDB*)idb->reveal_inner_db();
1201 }
1202 
1203 
1204 /**
1205  * Create a string hash map object.
1206  */
kcmapnew(size_t bnum)1207 KCMAP* kcmapnew(size_t bnum) {
1208   _assert_(true);
1209   return (KCMAP*)new TinyHashMap(bnum);
1210 }
1211 
1212 
1213 /**
1214  * Destroy a map object.
1215  */
kcmapdel(KCMAP * map)1216 void kcmapdel(KCMAP* map) {
1217   _assert_(map);
1218   TinyHashMap* thm = (TinyHashMap*)map;
1219   delete thm;
1220 }
1221 
1222 
1223 /**
1224  * Set the value of a record.
1225  */
kcmapset(KCMAP * map,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1226 void kcmapset(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1227   _assert_(map && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1228   TinyHashMap* thm = (TinyHashMap*)map;
1229   thm->set(kbuf, ksiz, vbuf, vsiz);
1230 }
1231 
1232 
1233 /**
1234  * Add a record.
1235  */
kcmapadd(KCMAP * map,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1236 int32_t kcmapadd(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1237   _assert_(map && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1238   TinyHashMap* thm = (TinyHashMap*)map;
1239   return thm->add(kbuf, ksiz, vbuf, vsiz);
1240 }
1241 
1242 
1243 /**
1244  * Replace the value of a record.
1245  */
kcmapreplace(KCMAP * map,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1246 int32_t kcmapreplace(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1247   _assert_(map && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1248   TinyHashMap* thm = (TinyHashMap*)map;
1249   return thm->replace(kbuf, ksiz, vbuf, vsiz);
1250 }
1251 
1252 
1253 /**
1254  * Append the value of a record.
1255  */
kcmapappend(KCMAP * map,const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)1256 void kcmapappend(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
1257   _assert_(map && kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
1258   TinyHashMap* thm = (TinyHashMap*)map;
1259   thm->append(kbuf, ksiz, vbuf, vsiz);
1260 }
1261 
1262 
1263 /**
1264  * Remove a record.
1265  */
kcmapremove(KCMAP * map,const char * kbuf,size_t ksiz)1266 int32_t kcmapremove(KCMAP* map, const char* kbuf, size_t ksiz) {
1267   _assert_(map && kbuf && ksiz <= MEMMAXSIZ);
1268   TinyHashMap* thm = (TinyHashMap*)map;
1269   return thm->remove(kbuf, ksiz);
1270 }
1271 
1272 
1273 /**
1274  * Retrieve the value of a record.
1275  */
kcmapget(KCMAP * map,const char * kbuf,size_t ksiz,size_t * sp)1276 const char* kcmapget(KCMAP* map, const char* kbuf, size_t ksiz, size_t* sp) {
1277   _assert_(map && kbuf && ksiz <= MEMMAXSIZ && sp);
1278   TinyHashMap* thm = (TinyHashMap*)map;
1279   return thm->get(kbuf, ksiz, sp);
1280 }
1281 
1282 
1283 /**
1284  * Remove all records.
1285  */
kcmapclear(KCMAP * map)1286 void kcmapclear(KCMAP* map) {
1287   _assert_(map);
1288   TinyHashMap* thm = (TinyHashMap*)map;
1289   thm->clear();
1290 }
1291 
1292 
1293 /**
1294  * Get the number of records.
1295  */
kcmapcount(KCMAP * map)1296 size_t kcmapcount(KCMAP* map) {
1297   _assert_(map);
1298   TinyHashMap* thm = (TinyHashMap*)map;
1299   return thm->count();
1300 }
1301 
1302 
1303 /**
1304  * Create a string hash map iterator object.
1305  */
kcmapiterator(KCMAP * map)1306 KCMAPITER* kcmapiterator(KCMAP* map) {
1307   _assert_(map);
1308   TinyHashMap* thm = (TinyHashMap*)map;
1309   return (KCMAPITER*)new TinyHashMap::Iterator(thm);
1310 }
1311 
1312 
1313 /**
1314  * Destroy an iterator object.
1315  */
kcmapiterdel(KCMAPITER * iter)1316 void kcmapiterdel(KCMAPITER* iter) {
1317   _assert_(iter);
1318   TinyHashMap::Iterator* thmi = (TinyHashMap::Iterator*)iter;
1319   delete thmi;
1320 }
1321 
1322 
1323 /**
1324  * Get the key of the current record.
1325  */
kcmapitergetkey(KCMAPITER * iter,size_t * sp)1326 const char* kcmapitergetkey(KCMAPITER* iter, size_t* sp) {
1327   _assert_(iter && sp);
1328   TinyHashMap::Iterator* thmi = (TinyHashMap::Iterator*)iter;
1329   return thmi->get_key(sp);
1330 }
1331 
1332 
1333 /**
1334  * Get the value of the current record.
1335  */
kcmapitergetvalue(KCMAPITER * iter,size_t * sp)1336 const char* kcmapitergetvalue(KCMAPITER* iter, size_t* sp) {
1337   _assert_(iter && sp);
1338   TinyHashMap::Iterator* thmi = (TinyHashMap::Iterator*)iter;
1339   return thmi->get_value(sp);
1340 }
1341 
1342 
1343 /**
1344  * Get a pair of the key and the value of the current record.
1345  */
kcmapiterget(KCMAPITER * iter,size_t * ksp,const char ** vbp,size_t * vsp)1346 const char* kcmapiterget(KCMAPITER* iter, size_t* ksp, const char** vbp, size_t* vsp) {
1347   _assert_(iter && ksp && vbp && vsp);
1348   TinyHashMap::Iterator* thmi = (TinyHashMap::Iterator*)iter;
1349   return thmi->get(ksp, vbp, vsp);
1350 }
1351 
1352 
1353 /**
1354  * Step the cursor to the next record.
1355  */
kcmapiterstep(KCMAPITER * iter)1356 void kcmapiterstep(KCMAPITER* iter) {
1357   _assert_(iter);
1358   TinyHashMap::Iterator* thmi = (TinyHashMap::Iterator*)iter;
1359   return thmi->step();
1360 }
1361 
1362 
1363 /**
1364  * Create a string hash map sorter object.
1365  */
kcmapsorter(KCMAP * map)1366 KCMAPSORT* kcmapsorter(KCMAP* map) {
1367   _assert_(map);
1368   TinyHashMap* thm = (TinyHashMap*)map;
1369   return (KCMAPSORT*)new TinyHashMap::Sorter(thm);
1370 }
1371 
1372 
1373 /**
1374  * Destroy an sorter object.
1375  */
kcmapsortdel(KCMAPSORT * sort)1376 void kcmapsortdel(KCMAPSORT* sort) {
1377   _assert_(sort);
1378   TinyHashMap::Sorter* thms = (TinyHashMap::Sorter*)sort;
1379   delete thms;
1380 }
1381 
1382 
1383 /**
1384  * Get the key of the current record.
1385  */
kcmapsortgetkey(KCMAPSORT * sort,size_t * sp)1386 const char* kcmapsortgetkey(KCMAPSORT* sort, size_t* sp) {
1387   _assert_(sort && sp);
1388   TinyHashMap::Sorter* thms = (TinyHashMap::Sorter*)sort;
1389   return thms->get_key(sp);
1390 }
1391 
1392 
1393 /**
1394  * Get the value of the current record.
1395  */
kcmapsortgetvalue(KCMAPSORT * sort,size_t * sp)1396 const char* kcmapsortgetvalue(KCMAPSORT* sort, size_t* sp) {
1397   _assert_(sort && sp);
1398   TinyHashMap::Sorter* thms = (TinyHashMap::Sorter*)sort;
1399   return thms->get_value(sp);
1400 }
1401 
1402 
1403 /**
1404  * Get a pair of the key and the value of the current record.
1405  */
kcmapsortget(KCMAPSORT * sort,size_t * ksp,const char ** vbp,size_t * vsp)1406 const char* kcmapsortget(KCMAPSORT* sort, size_t* ksp, const char** vbp, size_t* vsp) {
1407   _assert_(sort && ksp && vbp && vsp);
1408   TinyHashMap::Sorter* thms = (TinyHashMap::Sorter*)sort;
1409   return thms->get(ksp, vbp, vsp);
1410 }
1411 
1412 
1413 /**
1414  * Step the cursor to the next record.
1415  */
kcmapsortstep(KCMAPSORT * sort)1416 void kcmapsortstep(KCMAPSORT* sort) {
1417   _assert_(sort);
1418   TinyHashMap::Sorter* thms = (TinyHashMap::Sorter*)sort;
1419   return thms->step();
1420 }
1421 
1422 
1423 /**
1424  * Create a string array list object.
1425  */
kclistnew()1426 KCLIST* kclistnew() {
1427   _assert_(true);
1428   return (KCLIST*)new TinyArrayList();
1429 }
1430 
1431 
1432 /**
1433  * Destroy a list object.
1434  */
kclistdel(KCLIST * list)1435 void kclistdel(KCLIST* list) {
1436   _assert_(list);
1437   TinyArrayList* tal = (TinyArrayList*)list;
1438   delete tal;
1439 }
1440 
1441 
1442 /**
1443  * Insert a record at the bottom of the list.
1444  */
kclistpush(KCLIST * list,const char * buf,size_t size)1445 void kclistpush(KCLIST* list, const char* buf, size_t size) {
1446   _assert_(list && buf && size <= MEMMAXSIZ);
1447   TinyArrayList* tal = (TinyArrayList*)list;
1448   tal->push(buf, size);
1449 }
1450 
1451 
1452 /**
1453  * Remove a record at the bottom of the list.
1454  */
kclistpop(KCLIST * list)1455 int32_t kclistpop(KCLIST* list) {
1456   _assert_(list);
1457   TinyArrayList* tal = (TinyArrayList*)list;
1458   return tal->pop();
1459 }
1460 
1461 
1462 /**
1463  * Insert a record at the top of the list.
1464  */
kclistunshift(KCLIST * list,const char * buf,size_t size)1465 void kclistunshift(KCLIST* list, const char* buf, size_t size) {
1466   _assert_(list && buf && size <= MEMMAXSIZ);
1467   TinyArrayList* tal = (TinyArrayList*)list;
1468   tal->unshift(buf, size);
1469 }
1470 
1471 
1472 /**
1473  * Remove a record at the top of the list.
1474  */
kclistshift(KCLIST * list)1475 int32_t kclistshift(KCLIST* list) {
1476   _assert_(list);
1477   TinyArrayList* tal = (TinyArrayList*)list;
1478   return tal->shift();
1479 }
1480 
1481 
1482 /**
1483  * Insert a record at the position of the given index of the list.
1484  */
kclistinsert(KCLIST * list,const char * buf,size_t size,size_t idx)1485 void kclistinsert(KCLIST* list, const char* buf, size_t size, size_t idx) {
1486   _assert_(list && buf && size <= MEMMAXSIZ);
1487   TinyArrayList* tal = (TinyArrayList*)list;
1488   tal->insert(buf, size, idx);
1489 }
1490 
1491 
1492 /**
1493  * Remove a record at the position of the given index of the list.
1494  */
kclistremove(KCLIST * list,size_t idx)1495 void kclistremove(KCLIST* list, size_t idx) {
1496   _assert_(list);
1497   TinyArrayList* tal = (TinyArrayList*)list;
1498   return tal->remove(idx);
1499 }
1500 
1501 
1502 /**
1503  * Retrieve a record at the position of the given index of the list.
1504  */
kclistget(KCLIST * list,size_t idx,size_t * sp)1505 const char* kclistget(KCLIST* list, size_t idx, size_t* sp) {
1506   _assert_(list && sp);
1507   TinyArrayList* tal = (TinyArrayList*)list;
1508   return tal->get(idx, sp);
1509 }
1510 
1511 
1512 /**
1513  * Remove all records.
1514  */
kclistclear(KCLIST * list)1515 void kclistclear(KCLIST* list) {
1516   _assert_(list);
1517   TinyArrayList* tal = (TinyArrayList*)list;
1518   tal->clear();
1519 }
1520 
1521 
1522 /**
1523  * Get the number of records.
1524  */
kclistcount(KCLIST * list)1525 size_t kclistcount(KCLIST* list) {
1526   _assert_(list);
1527   TinyArrayList* tal = (TinyArrayList*)list;
1528   return tal->count();
1529 }
1530 
1531 
1532 }
1533 
1534 // END OF FILE
1535