This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 5.000
[perl5.git] / ext / DB_File / DB_File.xs
CommitLineData
a0d0e21e
LW
1/*
2
3 DB_File.xs -- Perl 5 interface to Berkeley DB
4
5 written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
6 last modified 23rd June 1994
7 version 0.1
8
9 All comments/suggestions/problems are welcome
10
11*/
12
13#include "EXTERN.h"
14#include "perl.h"
15#include "XSUB.h"
16
17#include <db.h>
18
19#include <fcntl.h>
20
21#ifndef DBXS_HASH_TYPE
22#define DBXS_HASH_TYPE u_int32_t
23#endif
24
25#ifndef DBXS_PREFIX_TYPE
26#define DBXS_PREFIX_TYPE size_t
27#endif
28
29typedef DB * DB_File;
30typedef DBT DBTKEY ;
31
32union INFO {
33 HASHINFO hash ;
34 RECNOINFO recno ;
35 BTREEINFO btree ;
36 } ;
37
38typedef struct {
39 SV * sub ;
40 } CallBackInfo ;
41
42
43/* #define TRACE */
44
45#define db_DESTROY(db) (db->close)(db)
46#define db_DELETE(db, key, flags) (db->del)(db, &key, flags)
47#define db_STORE(db, key, value, flags) (db->put)(db, &key, &value, flags)
48#define db_FETCH(db, key, flags) (db->get)(db, &key, &value, flags)
49
50#define db_close(db) (db->close)(db)
51#define db_del(db, key, flags) (db->del)(db, &key, flags)
52#define db_fd(db) (db->fd)(db)
53#define db_put(db, key, value, flags) (db->put)(db, &key, &value, flags)
54#define db_get(db, key, value, flags) (db->get)(db, &key, &value, flags)
55#define db_seq(db, key, value, flags) (db->seq)(db, &key, &value, flags)
56#define db_sync(db, flags) (db->sync)(db, flags)
57
58
59#define OutputValue(arg, name) \
60 { if (RETVAL == 0) sv_setpvn(arg, name.data, name.size) ; }
61
62#define OutputKey(arg, name) \
63 { if (RETVAL == 0) \
64 { \
65 if (db->close != DB_recno_close) \
66 sv_setpvn(arg, name.data, name.size); \
67 else \
68 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
69 } \
70 }
71
72/* Internal Global Data */
73
74static recno_t Value ;
75static int (*DB_recno_close)() = NULL ;
76
77static CallBackInfo hash_callback = { 0 } ;
78static CallBackInfo compare_callback = { 0 } ;
79static CallBackInfo prefix_callback = { 0 } ;
80
81
82static int
83btree_compare(key1, key2)
84const DBT * key1 ;
85const DBT * key2 ;
86{
87 dSP ;
88 void * data1, * data2 ;
89 int retval ;
90 int count ;
91
92 data1 = key1->data ;
93 data2 = key2->data ;
94
95 /* As newSVpv will assume that the data pointer is a null terminated C
96 string if the size parameter is 0, make sure that data points to an
97 empty string if the length is 0
98 */
99 if (key1->size == 0)
100 data1 = "" ;
101 if (key2->size == 0)
102 data2 = "" ;
103
104 ENTER ;
105 SAVETMPS;
106
107 PUSHMARK(sp) ;
108 EXTEND(sp,2) ;
109 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
110 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
111 PUTBACK ;
112
113 count = perl_call_sv(compare_callback.sub, G_SCALAR);
114
115 SPAGAIN ;
116
117 if (count != 1)
118 croak ("DB_File btree_compare: expected 1 return value from %s, got %d\n", count) ;
119
120 retval = POPi ;
121
122 PUTBACK ;
123 FREETMPS ;
124 LEAVE ;
125 return (retval) ;
126
127}
128
129static DBXS_PREFIX_TYPE
130btree_prefix(key1, key2)
131const DBT * key1 ;
132const DBT * key2 ;
133{
134 dSP ;
135 void * data1, * data2 ;
136 int retval ;
137 int count ;
138
139 data1 = key1->data ;
140 data2 = key2->data ;
141
142 /* As newSVpv will assume that the data pointer is a null terminated C
143 string if the size parameter is 0, make sure that data points to an
144 empty string if the length is 0
145 */
146 if (key1->size == 0)
147 data1 = "" ;
148 if (key2->size == 0)
149 data2 = "" ;
150
151 ENTER ;
152 SAVETMPS;
153
154 PUSHMARK(sp) ;
155 EXTEND(sp,2) ;
156 PUSHs(sv_2mortal(newSVpv(data1,key1->size)));
157 PUSHs(sv_2mortal(newSVpv(data2,key2->size)));
158 PUTBACK ;
159
160 count = perl_call_sv(prefix_callback.sub, G_SCALAR);
161
162 SPAGAIN ;
163
164 if (count != 1)
165 croak ("DB_File btree_prefix: expected 1 return value from %s, got %d\n", count) ;
166
167 retval = POPi ;
168
169 PUTBACK ;
170 FREETMPS ;
171 LEAVE ;
172
173 return (retval) ;
174}
175
176static DBXS_HASH_TYPE
177hash_cb(data, size)
178const void * data ;
179size_t size ;
180{
181 dSP ;
182 int retval ;
183 int count ;
184
185 if (size == 0)
186 data = "" ;
187
188 PUSHMARK(sp) ;
189 XPUSHs(sv_2mortal(newSVpv((char*)data,size)));
190 PUTBACK ;
191
192 count = perl_call_sv(hash_callback.sub, G_SCALAR);
193
194 SPAGAIN ;
195
196 if (count != 1)
197 croak ("DB_File hash_cb: expected 1 return value from %s, got %d\n", count) ;
198
199 retval = POPi ;
200
201 PUTBACK ;
202 FREETMPS ;
203 LEAVE ;
204
205 return (retval) ;
206}
207
208
209#ifdef TRACE
210
211static void
212PrintHash(hash)
213HASHINFO hash ;
214{
215 printf ("HASH Info\n") ;
216 printf (" hash = %s\n", (hash.hash != NULL ? "redefined" : "default")) ;
217 printf (" bsize = %d\n", hash.bsize) ;
218 printf (" ffactor = %d\n", hash.ffactor) ;
219 printf (" nelem = %d\n", hash.nelem) ;
220 printf (" cachesize = %d\n", hash.cachesize) ;
221 printf (" lorder = %d\n", hash.lorder) ;
222
223}
224
225static void
226PrintRecno(recno)
227RECNOINFO recno ;
228{
229 printf ("RECNO Info\n") ;
230 printf (" flags = %d\n", recno.flags) ;
231 printf (" cachesize = %d\n", recno.cachesize) ;
232 printf (" psize = %d\n", recno.psize) ;
233 printf (" lorder = %d\n", recno.lorder) ;
234 printf (" reclen = %d\n", recno.reclen) ;
235 printf (" bval = %d\n", recno.bval) ;
236 printf (" bfname = %s\n", recno.bfname) ;
237}
238
239PrintBtree(btree)
240BTREEINFO btree ;
241{
242 printf ("BTREE Info\n") ;
243 printf (" compare = %s\n", (btree.compare ? "redefined" : "default")) ;
244 printf (" prefix = %s\n", (btree.prefix ? "redefined" : "default")) ;
245 printf (" flags = %d\n", btree.flags) ;
246 printf (" cachesize = %d\n", btree.cachesize) ;
247 printf (" psize = %d\n", btree.psize) ;
248 printf (" maxkeypage = %d\n", btree.maxkeypage) ;
249 printf (" minkeypage = %d\n", btree.minkeypage) ;
250 printf (" lorder = %d\n", btree.lorder) ;
251}
252
253#else
254
255#define PrintRecno(recno)
256#define PrintHash(hash)
257#define PrintBtree(btree)
258
259#endif /* TRACE */
260
261
262static I32
263GetArrayLength(db)
264DB_File db ;
265{
266 DBT key ;
267 DBT value ;
268 int RETVAL ;
269
270 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
271 if (RETVAL == 0)
272 RETVAL = *(I32 *)key.data ;
273 else if (RETVAL == 1) /* No key means empty file */
274 RETVAL = 0 ;
275
276 return (RETVAL) ;
277}
278
279static DB_File
280ParseOpenInfo(name, flags, mode, sv, string)
281char * name ;
282int flags ;
283int mode ;
284SV * sv ;
285char * string ;
286{
287 SV ** svp;
288 HV * action ;
289 union INFO info ;
290 DB_File RETVAL ;
291 void * openinfo = NULL ;
292 DBTYPE type = DB_HASH ;
293
294
295 if (sv)
296 {
297 if (! SvROK(sv) )
298 croak ("type parameter is not a reference") ;
299
300 action = (HV*)SvRV(sv);
301 if (sv_isa(sv, "DB_File::HASHINFO"))
302 {
303 type = DB_HASH ;
304 openinfo = (void*)&info ;
305
306 svp = hv_fetch(action, "hash", 4, FALSE);
307
308 if (svp && SvOK(*svp))
309 {
310 info.hash.hash = hash_cb ;
311 hash_callback.sub = *svp ;
312 }
313 else
314 info.hash.hash = NULL ;
315
316 svp = hv_fetch(action, "bsize", 5, FALSE);
317 info.hash.bsize = svp ? SvIV(*svp) : 0;
318
319 svp = hv_fetch(action, "ffactor", 7, FALSE);
320 info.hash.ffactor = svp ? SvIV(*svp) : 0;
321
322 svp = hv_fetch(action, "nelem", 5, FALSE);
323 info.hash.nelem = svp ? SvIV(*svp) : 0;
324
325 svp = hv_fetch(action, "cachesize", 9, FALSE);
326 info.hash.cachesize = svp ? SvIV(*svp) : 0;
327
328 svp = hv_fetch(action, "lorder", 6, FALSE);
329 info.hash.lorder = svp ? SvIV(*svp) : 0;
330
331 PrintHash(info) ;
332 }
333 else if (sv_isa(sv, "DB_File::BTREEINFO"))
334 {
335 type = DB_BTREE ;
336 openinfo = (void*)&info ;
337
338 svp = hv_fetch(action, "compare", 7, FALSE);
339 if (svp && SvOK(*svp))
340 {
341 info.btree.compare = btree_compare ;
342 compare_callback.sub = *svp ;
343 }
344 else
345 info.btree.compare = NULL ;
346
347 svp = hv_fetch(action, "prefix", 6, FALSE);
348 if (svp && SvOK(*svp))
349 {
350 info.btree.prefix = btree_prefix ;
351 prefix_callback.sub = *svp ;
352 }
353 else
354 info.btree.prefix = NULL ;
355
356 svp = hv_fetch(action, "flags", 5, FALSE);
357 info.btree.flags = svp ? SvIV(*svp) : 0;
358
359 svp = hv_fetch(action, "cachesize", 9, FALSE);
360 info.btree.cachesize = svp ? SvIV(*svp) : 0;
361
362 svp = hv_fetch(action, "minkeypage", 10, FALSE);
363 info.btree.minkeypage = svp ? SvIV(*svp) : 0;
364
365 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
366 info.btree.maxkeypage = svp ? SvIV(*svp) : 0;
367
368 svp = hv_fetch(action, "psize", 5, FALSE);
369 info.btree.psize = svp ? SvIV(*svp) : 0;
370
371 svp = hv_fetch(action, "lorder", 6, FALSE);
372 info.btree.lorder = svp ? SvIV(*svp) : 0;
373
374 PrintBtree(info) ;
375
376 }
377 else if (sv_isa(sv, "DB_File::RECNOINFO"))
378 {
379 type = DB_RECNO ;
380 openinfo = (void *)&info ;
381
382 svp = hv_fetch(action, "flags", 5, FALSE);
383 info.recno.flags = (u_long) svp ? SvIV(*svp) : 0;
384
385 svp = hv_fetch(action, "cachesize", 9, FALSE);
386 info.recno.cachesize = (u_int) svp ? SvIV(*svp) : 0;
387
388 svp = hv_fetch(action, "psize", 5, FALSE);
389 info.recno.psize = (int) svp ? SvIV(*svp) : 0;
390
391 svp = hv_fetch(action, "lorder", 6, FALSE);
392 info.recno.lorder = (int) svp ? SvIV(*svp) : 0;
393
394 svp = hv_fetch(action, "reclen", 6, FALSE);
395 info.recno.reclen = (size_t) svp ? SvIV(*svp) : 0;
396
397 svp = hv_fetch(action, "bval", 4, FALSE);
398 if (svp && SvOK(*svp))
399 {
400 if (SvPOK(*svp))
401 info.recno.bval = (u_char)*SvPV(*svp, na) ;
402 else
403 info.recno.bval = (u_char)(unsigned long) SvIV(*svp) ;
404 }
405 else
406 {
407 if (info.recno.flags & R_FIXEDLEN)
408 info.recno.bval = (u_char) ' ' ;
409 else
410 info.recno.bval = (u_char) '\n' ;
411 }
412
413 svp = hv_fetch(action, "bfname", 6, FALSE);
414 info.recno.bfname = (char *) svp ? SvPV(*svp,na) : 0;
415
416 PrintRecno(info) ;
417 }
418 else
419 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
420 }
421
422
423 RETVAL = dbopen(name, flags, mode, type, openinfo) ;
424
425 if (RETVAL == 0)
426 croak("DB_File::%s failed, reason: %s", string, Strerror(errno)) ;
427
428 /* kludge mode on: RETVAL->type for DB_RECNO is set to DB_BTREE
429 so remember a DB_RECNO by saving the address
430 of one of it's internal routines
431 */
432 if (type == DB_RECNO)
433 DB_recno_close = RETVAL->close ;
434
435
436 return (RETVAL) ;
437}
438
439
440static int
441not_here(s)
442char *s;
443{
444 croak("DB_File::%s not implemented on this architecture", s);
445 return -1;
446}
447
448static double
449constant(name, arg)
450char *name;
451int arg;
452{
453 errno = 0;
454 switch (*name) {
455 case 'A':
456 break;
457 case 'B':
458 if (strEQ(name, "BTREEMAGIC"))
459#ifdef BTREEMAGIC
460 return BTREEMAGIC;
461#else
462 goto not_there;
463#endif
464 if (strEQ(name, "BTREEVERSION"))
465#ifdef BTREEVERSION
466 return BTREEVERSION;
467#else
468 goto not_there;
469#endif
470 break;
471 case 'C':
472 break;
473 case 'D':
474 if (strEQ(name, "DB_LOCK"))
475#ifdef DB_LOCK
476 return DB_LOCK;
477#else
478 goto not_there;
479#endif
480 if (strEQ(name, "DB_SHMEM"))
481#ifdef DB_SHMEM
482 return DB_SHMEM;
483#else
484 goto not_there;
485#endif
486 if (strEQ(name, "DB_TXN"))
487#ifdef DB_TXN
488 return (U32)DB_TXN;
489#else
490 goto not_there;
491#endif
492 break;
493 case 'E':
494 break;
495 case 'F':
496 break;
497 case 'G':
498 break;
499 case 'H':
500 if (strEQ(name, "HASHMAGIC"))
501#ifdef HASHMAGIC
502 return HASHMAGIC;
503#else
504 goto not_there;
505#endif
506 if (strEQ(name, "HASHVERSION"))
507#ifdef HASHVERSION
508 return HASHVERSION;
509#else
510 goto not_there;
511#endif
512 break;
513 case 'I':
514 break;
515 case 'J':
516 break;
517 case 'K':
518 break;
519 case 'L':
520 break;
521 case 'M':
522 if (strEQ(name, "MAX_PAGE_NUMBER"))
523#ifdef MAX_PAGE_NUMBER
524 return (U32)MAX_PAGE_NUMBER;
525#else
526 goto not_there;
527#endif
528 if (strEQ(name, "MAX_PAGE_OFFSET"))
529#ifdef MAX_PAGE_OFFSET
530 return MAX_PAGE_OFFSET;
531#else
532 goto not_there;
533#endif
534 if (strEQ(name, "MAX_REC_NUMBER"))
535#ifdef MAX_REC_NUMBER
536 return (U32)MAX_REC_NUMBER;
537#else
538 goto not_there;
539#endif
540 break;
541 case 'N':
542 break;
543 case 'O':
544 break;
545 case 'P':
546 break;
547 case 'Q':
548 break;
549 case 'R':
550 if (strEQ(name, "RET_ERROR"))
551#ifdef RET_ERROR
552 return RET_ERROR;
553#else
554 goto not_there;
555#endif
556 if (strEQ(name, "RET_SPECIAL"))
557#ifdef RET_SPECIAL
558 return RET_SPECIAL;
559#else
560 goto not_there;
561#endif
562 if (strEQ(name, "RET_SUCCESS"))
563#ifdef RET_SUCCESS
564 return RET_SUCCESS;
565#else
566 goto not_there;
567#endif
568 if (strEQ(name, "R_CURSOR"))
569#ifdef R_CURSOR
570 return R_CURSOR;
571#else
572 goto not_there;
573#endif
574 if (strEQ(name, "R_DUP"))
575#ifdef R_DUP
576 return R_DUP;
577#else
578 goto not_there;
579#endif
580 if (strEQ(name, "R_FIRST"))
581#ifdef R_FIRST
582 return R_FIRST;
583#else
584 goto not_there;
585#endif
586 if (strEQ(name, "R_FIXEDLEN"))
587#ifdef R_FIXEDLEN
588 return R_FIXEDLEN;
589#else
590 goto not_there;
591#endif
592 if (strEQ(name, "R_IAFTER"))
593#ifdef R_IAFTER
594 return R_IAFTER;
595#else
596 goto not_there;
597#endif
598 if (strEQ(name, "R_IBEFORE"))
599#ifdef R_IBEFORE
600 return R_IBEFORE;
601#else
602 goto not_there;
603#endif
604 if (strEQ(name, "R_LAST"))
605#ifdef R_LAST
606 return R_LAST;
607#else
608 goto not_there;
609#endif
610 if (strEQ(name, "R_NEXT"))
611#ifdef R_NEXT
612 return R_NEXT;
613#else
614 goto not_there;
615#endif
616 if (strEQ(name, "R_NOKEY"))
617#ifdef R_NOKEY
618 return R_NOKEY;
619#else
620 goto not_there;
621#endif
622 if (strEQ(name, "R_NOOVERWRITE"))
623#ifdef R_NOOVERWRITE
624 return R_NOOVERWRITE;
625#else
626 goto not_there;
627#endif
628 if (strEQ(name, "R_PREV"))
629#ifdef R_PREV
630 return R_PREV;
631#else
632 goto not_there;
633#endif
634 if (strEQ(name, "R_RECNOSYNC"))
635#ifdef R_RECNOSYNC
636 return R_RECNOSYNC;
637#else
638 goto not_there;
639#endif
640 if (strEQ(name, "R_SETCURSOR"))
641#ifdef R_SETCURSOR
642 return R_SETCURSOR;
643#else
644 goto not_there;
645#endif
646 if (strEQ(name, "R_SNAPSHOT"))
647#ifdef R_SNAPSHOT
648 return R_SNAPSHOT;
649#else
650 goto not_there;
651#endif
652 break;
653 case 'S':
654 break;
655 case 'T':
656 break;
657 case 'U':
658 break;
659 case 'V':
660 break;
661 case 'W':
662 break;
663 case 'X':
664 break;
665 case 'Y':
666 break;
667 case 'Z':
668 break;
669 case '_':
670 if (strEQ(name, "__R_UNUSED"))
671#ifdef __R_UNUSED
672 return __R_UNUSED;
673#else
674 goto not_there;
675#endif
676 break;
677 }
678 errno = EINVAL;
679 return 0;
680
681not_there:
682 errno = ENOENT;
683 return 0;
684}
685
686MODULE = DB_File PACKAGE = DB_File PREFIX = db_
687
688double
689constant(name,arg)
690 char * name
691 int arg
692
693
694DB_File
695db_TIEHASH(dbtype, name=undef, flags=O_RDWR, mode=0640, type=DB_HASH)
696 char * dbtype
697 int flags
698 int mode
699 CODE:
700 {
701 char * name = (char *) NULL ;
702 SV * sv = (SV *) NULL ;
703
704 if (items >= 2 && SvOK(ST(1)))
705 name = (char*) SvPV(ST(1), na) ;
706
707 if (items == 5)
708 sv = ST(4) ;
709
710 RETVAL = ParseOpenInfo(name, flags, mode, sv, "new") ;
711 }
712 OUTPUT:
713 RETVAL
714
715BOOT:
716 newXS("DB_File::TIEARRAY", XS_DB_File_db_TIEHASH, file);
717
718int
719db_DESTROY(db)
720 DB_File db
721
722
723int
724db_DELETE(db, key, flags=0)
725 DB_File db
726 DBTKEY key
727 u_int flags
728
729int
730db_FETCH(db, key, flags=0)
731 DB_File db
732 DBTKEY key
733 u_int flags
734 CODE:
735 {
736 DBT value ;
737
738 RETVAL = (db->get)(db, &key, &value, flags) ;
739 ST(0) = sv_newmortal();
740 if (RETVAL == 0)
741 sv_setpvn(ST(0), value.data, value.size);
742 }
743
744int
745db_STORE(db, key, value, flags=0)
746 DB_File db
747 DBTKEY key
748 DBT value
749 u_int flags
750
751
752int
753db_FIRSTKEY(db)
754 DB_File db
755 CODE:
756 {
757 DBTKEY key ;
758 DBT value ;
759
760 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
761 ST(0) = sv_newmortal();
762 if (RETVAL == 0)
763 {
764 if (db->type != DB_RECNO)
765 sv_setpvn(ST(0), key.data, key.size);
766 else
767 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
768 }
769 }
770
771int
772db_NEXTKEY(db, key)
773 DB_File db
774 DBTKEY key
775 CODE:
776 {
777 DBT value ;
778
779 RETVAL = (db->seq)(db, &key, &value, R_NEXT) ;
780 ST(0) = sv_newmortal();
781 if (RETVAL == 0)
782 {
783 if (db->type != DB_RECNO)
784 sv_setpvn(ST(0), key.data, key.size);
785 else
786 sv_setiv(ST(0), (I32)*(I32*)key.data - 1);
787 }
788 }
789
790#
791# These would be nice for RECNO
792#
793
794int
795unshift(db, ...)
796 DB_File db
797 CODE:
798 {
799 DBTKEY key ;
800 DBT value ;
801 int i ;
802 int One ;
803
804 RETVAL = -1 ;
805 for (i = items-1 ; i > 0 ; --i)
806 {
807 value.data = SvPV(ST(i), na) ;
808 value.size = na ;
809 One = 1 ;
810 key.data = &One ;
811 key.size = sizeof(int) ;
812 RETVAL = (db->put)(db, &key, &value, R_IBEFORE) ;
813 if (RETVAL != 0)
814 break;
815 }
816 }
817 OUTPUT:
818 RETVAL
819
820I32
821pop(db)
822 DB_File db
823 CODE:
824 {
825 DBTKEY key ;
826 DBT value ;
827
828 /* First get the final value */
829 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
830 ST(0) = sv_newmortal();
831 /* Now delete it */
832 if (RETVAL == 0)
833 {
834 RETVAL = (db->del)(db, &key, R_CURSOR) ;
835 if (RETVAL == 0)
836 sv_setpvn(ST(0), value.data, value.size);
837 }
838 }
839
840I32
841shift(db)
842 DB_File db
843 CODE:
844 {
845 DBTKEY key ;
846 DBT value ;
847
848 /* get the first value */
849 RETVAL = (db->seq)(db, &key, &value, R_FIRST) ;
850 ST(0) = sv_newmortal();
851 /* Now delete it */
852 if (RETVAL == 0)
853 {
854 RETVAL = (db->del)(db, &key, R_CURSOR) ;
855 if (RETVAL == 0)
856 sv_setpvn(ST(0), value.data, value.size);
857 }
858 }
859
860
861I32
862push(db, ...)
863 DB_File db
864 CODE:
865 {
866 DBTKEY key ;
867 DBT value ;
868 int i ;
869
870 /* Set the Cursor to the Last element */
871 RETVAL = (db->seq)(db, &key, &value, R_LAST) ;
872 if (RETVAL == 0)
873 {
874 /* for (i = 1 ; i < items ; ++i) */
875 for (i = items - 1 ; i > 0 ; --i)
876 {
877 value.data = SvPV(ST(i), na) ;
878 value.size = na ;
879 RETVAL = (db->put)(db, &key, &value, R_IAFTER) ;
880 if (RETVAL != 0)
881 break;
882 }
883 }
884 }
885 OUTPUT:
886 RETVAL
887
888
889I32
890length(db)
891 DB_File db
892 CODE:
893 RETVAL = GetArrayLength(db) ;
894 OUTPUT:
895 RETVAL
896
897
898#
899# Now provide an interface to the rest of the DB functionality
900#
901
902int
903db_del(db, key, flags=0)
904 DB_File db
905 DBTKEY key
906 u_int flags
907
908
909int
910db_get(db, key, value, flags=0)
911 DB_File db
912 DBTKEY key
913 DBT value
914 u_int flags
915 OUTPUT:
916 value
917
918int
919db_put(db, key, value, flags=0)
920 DB_File db
921 DBTKEY key
922 DBT value
923 u_int flags
924 OUTPUT:
925 key if (flags & (R_IAFTER|R_IBEFORE)) OutputKey(ST(1), key);
926
927int
928db_fd(db)
929 DB_File db
930
931int
932db_sync(db, flags=0)
933 DB_File db
934 u_int flags
935
936
937int
938db_seq(db, key, value, flags)
939 DB_File db
940 DBTKEY key
941 DBT value
942 u_int flags
943 OUTPUT:
944 key
945 value