improvement: path limit in URL works without full result display
[webpac] / openisis / openisis.h
1 /*
2         openisis - an open implementation of the CDS/ISIS database
3         Version 0.8.x (patchlevel see file Version)
4         Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5
6         This library is free software; you can redistribute it and/or
7         modify it under the terms of the GNU Lesser General Public
8         License as published by the Free Software Foundation; either
9         version 2.1 of the License, or (at your option) any later version.
10
11         This library is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14         Lesser General Public License for more details.
15
16         You should have received a copy of the GNU Lesser General Public
17         License along with this library; if not, write to the Free Software
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20         see README for more information
21 EOH */
22 #ifndef OPENISIS_H
23
24 /*
25         $Id: openisis.h,v 1.91 2003/06/30 09:50:45 kripke Exp $
26         public interface of the openisis lib.
27         usage samples of most calls are found in openisis.c
28 */
29
30 #define OPENISIS_VERSION "0.9.0"
31
32 #ifndef __STDC__
33 #       ifndef const
34 #               define const
35 #       endif
36 #endif
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 /* ************************************************************
43         record structure
44 */
45
46 /** cooked version of an ISIS field.
47         * values are *NOT* terminated by a 0 byte.
48 */
49 typedef struct OpenIsisField {
50         int         tag;
51         const char *val;
52         int         len;
53 } OpenIsisField;
54
55
56 /** cooked version of an ISIS Record.
57 */
58 typedef struct OpenIsisRec {
59         int           dbid;
60         int           rowid;
61         int           bytes; /* total avail bytes */
62         int           used; /* total used bytes (originally BWB) */
63         int           fields;  /* avail number of fields (originally BWP) */
64         int           base; /* byte offset of contents area (after fields) */
65         int           len;      /* used number of fields */
66         int           state;
67         OpenIsisField field[1];
68 } OpenIsisRec;
69
70 /* compute base from fields (for both raw and cooked record) */
71 #define OPENISIS_BASESZ( nfields ) ((int)sizeof(int)*(8 + 3*(nfields)))
72
73 /* initialise record of f fields, n bytes */
74 #define OPENISIS_INITREC( r, n, f ) \
75         do { \
76                 memset( r, 0, n ); \
77                 (r)->bytes = (n); \
78                 (r)->fields = (f); \
79                 (r)->used = (r)->base = OPENISIS_BASESZ( (r)->fields ); \
80         }       while (0)
81
82 /* init with std 1 field per 100 bytes */
83 #define OPENISIS_INITSTD( r, n ) OPENISIS_INITREC( r, n, (n)/100 )
84 /* init a buffer structure which has a member r */
85 #define OPENISIS_INITBUF( x ) OPENISIS_INITSTD( &x.r, sizeof(x) )
86 #define OPENISIS_CLRREC( r ) \
87         do { \
88                 (r)->len = (r)->state = 0; \
89                 (r)->used = (r)->base = OPENISIS_BASESZ( (r)->fields ); \
90         }       while (0)
91
92 /* check some invariants (for both raw and cooked record) */
93 #define OPENISIS_RECOK( r ) \
94         ( (r)->base <= (r)->used \
95         && (r)->used <= (r)->bytes \
96         && (r)->len <= (r)->fields \
97         && (r)->base == OPENISIS_BASESZ( (r)->fields ) )
98
99
100 /** field description.
101 */
102 enum { /* field types */
103         OPENISIS_FTX =  0, /* alphanum */
104         OPENISIS_FTA =  1, /* STRICTLY alpha */
105         OPENISIS_FTN =  2, /* numeric */
106         OPENISIS_FTP =  3, /* pattern */
107         OPENISIS_FTB =  4, /* bool */
108         OPENISIS_FTE =  5, /* enum */
109         OPENISIS_FTI =  8, /* ISO (unused) */
110         OPENISIS_FTT =  9, /* table (unused) */
111         OPENISIS_FTO = 13, /* structure: operator */
112         OPENISIS_FTR = 14, /* structure: record */
113         OPENISIS_FTS = 15, /* structure: sequence */
114         OPENISIS_FTV = 16, /* enum value */
115         OPENISIS_FTF = 16  /* subfield (unused) */
116 };
117
118 #define OPENISIS_FD_NAMELEN  32
119 typedef struct OpenIsisFd {
120         int   id; /* tag */
121         char  subf; /* subfield char or 0 */
122         char  type; /* type */
123         char  rep; /* !0 for repeated */
124         char  slen; /* length of childs */
125         short len; /* max length or enum value */
126         char  name[OPENISIS_FD_NAMELEN]; /* name, 0 terminated, max 30 */
127         char  desc[OPENISIS_FD_NAMELEN]; /* 0 terminated description */
128         char *pat; /* 0 terminated pattern */
129         char *dflt; /* 0 terminated default value */
130         OpenIsisRec *info; /* additional application dependent attributes */
131         struct OpenIsisFd **subs; /* subfield childs */
132 }       OpenIsisFd;
133
134
135 /** field description table.
136 */
137 typedef struct {
138         int          len;
139         OpenIsisFd  *fd;
140         OpenIsisRec *rec; /* additional fields like formats, worksheets ... */
141         /* additional internal data like a hash might follow */
142 }       OpenIsisFdt;
143
144
145 typedef struct { /* where a key has a hit */
146
147         unsigned       mfn;
148         unsigned short tag;
149         unsigned short occ; /* hit is in occ'th occurence of field tag in row mfn */
150         unsigned short pos; /* ... as the pos'th word */
151         unsigned short dbn; /* for multi-db index; ignored by now */
152 }       OpenIsisHit;
153
154 typedef struct {
155         unsigned char len;
156         unsigned char byt[23];
157 }       OpenIsisVal;
158
159 typedef struct {
160         OpenIsisVal   val;
161         unsigned char len;
162         unsigned char byt[255];
163 }       OpenIsisKey;
164
165
166 /** Writex tags, see doc/Inverted.
167         Non-negative tags add (or delete) themselves.
168         Negative control indexing.
169 */
170 enum {
171         OPENISIS_XCTL = -1, /* the "index" control field */
172         OPENISIS_XFST = -2, /* fst view line */
173         OPENISIS_XHIT = -3, /* dotted decimal hit plus val */
174         OPENISIS_XADD = -4, /* (prefix of) binary OpenIsisKey to add */
175         OPENISIS_XDEL = -5  /* (prefix of) binary OpenIsisKey to del */
176 };
177
178
179 /**
180         get occurence of field.
181         @param pos if given, the first occ starting at pos is searched
182                 and pos is set to one after the found position (or after end).
183                 may be used to loop all on an int var initialized to 0.
184         @return the field or 0
185 */
186 extern OpenIsisField *openIsisRGet ( OpenIsisRec *r, int tag, int *pos );
187
188 extern OpenIsisField *openIsisROccurence ( OpenIsisRec *r, int tag, int occ );
189
190 /** similar to atoi/strtol, but
191         - string needs not be 0 terminated (unless l < 0)
192         - cares for hex 0x, but not octal 0.
193 */
194 extern int openIsisA2i ( const char *p, int l );
195 /** similar to openIsisA2i but
196         - return number of parsed characters
197         - put result in *res
198 */
199 extern int openIsisA2il ( const char *p, int l, int *res );
200 /**     similar to openIsisA2i but
201         - return dflt if less than l characters of p has been successfully parsed
202 */
203 extern int openIsisA2id ( const char *p, int l, int dflt );
204 /** print 0 terminated int.
205         p must have 12 bytes space
206         @return number of chars (up to 10 digits + minus sign)
207 */
208 extern int openIsisI2a ( char *p, int i );
209 extern int openIsisU2a ( char *p, unsigned u );
210
211 /**
212         get field value as int as of A2i.
213         boolean values are recognized as 0 and 1.
214         if not found, return def.
215 */
216 extern int openIsisRInt ( OpenIsisRec *r, int tag, int def, int *pos );
217
218 /**
219  * get field value as string from rec or default rec.
220  * note: def should be a non-legal value, since a def result in the
221  * first record causes a lookup in dflt.
222  */
223 extern int openIsisRInt2 (OpenIsisRec *rec,
224         OpenIsisRec *dflt, int tag, int def);
225
226 /**
227         get field value as enum.
228         if not found, return def.
229 */
230 extern int openIsisREnum ( OpenIsisFdt *fdt,
231         OpenIsisRec *r, int tag, int def, int *pos );
232
233 /**
234         get field value as string of length len (including 0-byte).
235         if not found, return 0.
236 */
237 extern char* openIsisRString (OpenIsisRec *r,
238         int tag, int *pos, char *buf, int len);
239
240 /**
241  * get field value as string from rec or default rec.
242  */
243 extern char* openIsisRString2 (OpenIsisRec *rec,
244         OpenIsisRec *dflt, int tag, char *buf, int len);
245
246 /** flatten (serialize) text record
247         to tag\tval lines ended by a blank line.
248         Text means the record is assumed to not contain
249         vertical tabs of any importance,
250         so newlines in field values are replaced with vertical tabs (^K).
251         buf must be of size rec->used,
252         wich has enough room for all values + 24bytes header
253         + 12 bytes per field (ok for sign+10digits+tab).
254         @return # of bytes written
255 */
256 extern int openIsisRSerialize ( char *buf, OpenIsisRec *rec );
257 /**
258         like Serialize, but newlines are turned into newline-tab.
259         buf must be of size 2*rec->used (unless you know you don't have newlines)
260 */
261 extern int openIsisRSerializeBin ( char *buf, OpenIsisRec *rec );
262
263 /**     alloc buffer with appropriate length, if necessary.
264         @param *len input: length of buf
265         @param *len output: length of serialized record written
266                 to returned buffer
267         @return buffer, must be freed after usage if reallocated (i.e. != buf),
268                 null on error
269 */
270 extern char* openIsisRSerializeAlloc (OpenIsisRec *rec, char *buf, int *len);
271
272 /** flatten fully transparently,
273         replacing newlines with newline-tab.
274 extern int openIsisRBinSerialize ( char *buf, int len, OpenIsisRec *rec );
275 */
276
277 /* ************************************************************
278         fdt
279 */
280
281 /** get field description by id (tag).
282 */
283 extern OpenIsisFd* openIsisFById ( const OpenIsisFdt *fdt, int id, int subf );
284
285 /** get field description by name.
286 */
287 extern OpenIsisFd* openIsisFByName (const OpenIsisFdt *fdt, const char *name);
288
289 enum {
290         OPENISIS_NOENUM = 0x10000 /* enum NOENUM :) -- not a short */
291 };
292
293 /** lookup enum value for field id.
294         name must be exact match or unique prefix.
295         @return the enum value or NOENUM
296 */
297 extern int openIsisFEnum ( OpenIsisFdt *fdt, int id, const char *name );
298
299 /**     free fdt and fd structures.
300         @return 0
301 */
302 extern OpenIsisFdt* openIsisFFree (OpenIsisFdt *fdt);
303
304 /**     convert fdt to record.
305         @param fdt source
306         @param rec target where to append fd, may be null
307         @param embchld boolean indicating whether subfield childs should
308                 be embedded in fd part of target rather than in fdt part
309         @return target or null if no memory available
310 */
311 extern OpenIsisRec* openIsisFFdt2Rec (
312         const OpenIsisFdt *fdt, OpenIsisRec *rec, int embchld);
313
314 /**     build fdt from rec.
315         @param rec source
316         @return fdt or null on error
317 */
318 extern OpenIsisFdt* openIsisFRec2Fdt (OpenIsisRec *rec);
319
320
321 /* ************************************************************
322         session type and utilities
323 */
324
325 typedef struct OpenIsisSes *OpenIsisSession;
326
327 extern void *openIsisMAlloc ( int size );
328 extern void  openIsisMFree ( void *mem );
329 extern void *openIsisMDup ( const void *str, int size );
330
331 /**
332         convert string to html by replacing the four characters
333         &lt;,&gt;,&amp; and &quot;.
334         free the returned pointer after usage.
335         XML has a fifth standard entity apos,
336         but many HTML clients don't grok it.
337 */
338 extern char *openIsisToHtml ( const char *str, int len );
339 extern int openIsisUtf8Chk ( void *mem, int len, int *tof );
340
341
342 /* ************************************************************
343         stream IO
344 */
345
346 typedef struct OpenIsisIos *OpenIsisStream;
347 typedef int OpenIsisSFunc ( OpenIsisStream s, int op );
348
349 extern int openIsisSOpen ( const char *name, int flags, OpenIsisSFunc *type );
350
351 /**
352         error and loglevel codes one nibble each.
353 */
354 enum { /* our very own errno */
355         OPENISIS_ERR_OK    = 0, /* 0 is no error, also read(2)'s EINTR, EAGAIN */
356         /* errors logged at level VERBOSE */
357         OPENISIS_ERR_EOF   = 0x10000, /* end of file */
358         /* errors logged at level ERROR */
359         OPENISIS_ERR_FAULT = 0x20000, /* NULL pointer or bad sized buffer given */
360         OPENISIS_ERR_INVAL = 0x30000, /* general invalid parameters, any EINVAL errno */
361         OPENISIS_ERR_BADF  = 0x40000, /* bad file, also read(2)'s EINVAL, some of open(2) */
362         /* errors logged at level SYSERR */
363         OPENISIS_ERR_IO    = 0x50000, /* real IO error, also write(2)'s ENOSPC, EPIPE */
364         OPENISIS_ERR_NOMEM = 0x60000, /* out of memory, also open(2)'s EMFILE, ENFILE */
365         OPENISIS_ERR_BUSY  = 0x70000, /* object is busy */
366         /* errors logged at level FATAL */
367         OPENISIS_ERR_TRASH = 0x80000, /* database internal consistency */
368         OPENISIS_ERR_IDIOT = 0x90000 /* caught programming error */
369 };
370
371 typedef enum {
372         OPENISIS_LOG_OFF = 0, /* don't log anything */
373         OPENISIS_LOG_FATAL   = 0x100000, /* fatal internal errors: we can't go on */
374         OPENISIS_LOG_SYSERR  = 0x200000, /* problem with system ressources: bad file, no mem */
375         OPENISIS_LOG_IOERR   = 0x300000, /* problem on IO */
376         OPENISIS_LOG_ERROR   = 0x400000, /* unusable input, database or query */
377         OPENISIS_LOG_WARN    = 0x500000, /* bad input */
378         OPENISIS_LOG_INFO    = 0x600000, /* some major event like opening a db */
379         OPENISIS_LOG_VERBOSE = 0x700000, /* any event like reading a record */
380         OPENISIS_LOG_TRACE   = 0x800000, /* database content (log_str) */
381         /* highest levels only with debug built */
382         OPENISIS_LOG_DEBUG   = 0x900000, /* lots of processing details */
383         OPENISIS_LOG_ALL     = 0xa00000  /* just everything, even built-in content */
384 } OpenIsisLogLevel;
385
386 enum {
387         OPENISIS_ERR_ERRORS = 10,
388         OPENISIS_ERR_MASK  = 0xf0000, /* mask for filtering error code */
389         OPENISIS_ERR_SHIFT = 16, /* shift to make codes 0,1...ERR_ERRORS */
390         OPENISIS_LOG_NOCHANGE = -1, /* leave as is when initialising log */
391         OPENISIS_LOG_LEVELS  = 11,
392         OPENISIS_LOG_MASK    = 0xf00000, /* mask for filtering log levels */
393         OPENISIS_LOG_SHIFT   = 20, /* shift to make codes 0,1...LOG_LEVELS */
394         /*
395                 the following ids are provided just in case
396                 you don't feel comfortable assuming that in,out,err are always 0,1,2 ;)
397                 typically, you don't need any of these, 0 will work ...
398         */
399         OPENISIS_SIN  = 0, /* stream id of stdin */
400         OPENISIS_SOUT = 1, /* stdout */
401         OPENISIS_SERR = 2, /* stderr */
402         OPENISIS_SMASK = 0xffff, /* mask of stream id part of to */
403         OPENISIS_MSG_VA = 0x1000000 /* 1st parameter after fmt IS a va_list */
404 };
405
406 /**
407         printf to session's stream given by to.
408         The streams 0,1 and 2 of the default session are usually bound
409         to the system file descriptors 0,1 and 2 under unixes.
410         On windows, 2 is redirected to file oisiserr.txt.
411         0 and 1 are bound to CONIN$ and CONOUT$ for console apps,
412         to NULL and oisisout.txt for GUI apps.
413         For server sessions, 0 and 1 are connected to the client
414         and 2 is redirected to some per-session logging.
415         @param to
416                 the lower bytes as given by SMASK specify the stream to use.
417                 the higher bytes may specify loglevel and or error code.
418                 if either loglevel or error code is given,
419                 the other will be derived accordingly
420                 and stream defaults to 2 (if stream id is 0).
421                 otherwise, stream defaults to 1,
422                 so you never can print to 0.
423         @return the negative error code
424 */
425 extern int openIsisSMsg ( int to, const char *fmt, ... );
426
427 /**
428         get a string delimited by char delim (typically '\n') on stream number fd.
429         on success, ptr is set to the string
430         and it's length is returned, not including the delimiting char.
431         Note that there need not be a delimiting char near end of file.
432         If there is no string available, ptr is set to 0 (NULL).
433         If input might be available later, 0 is returned,
434         else some negative error code.
435 */
436 extern int openIsisSGets ( int fd, char **ptr, char delim );
437 #define openIsisSReadln( p ) openIsisSGets( 0, p, '\n' )
438
439 typedef struct OpenIsisRecStream {
440         OpenIsisStream  in; /* input stream to read from */
441         int             flg; /* flags */
442         OpenIsisRec    *buf; /* original buffer */
443         OpenIsisRec    *rec; /* record read */
444         OpenIsisRec    *dict; /* dictionary of field names */
445 } OpenIsisRecStream;
446
447 /*
448         stream in records in some free-style format suitable for
449         mails, properties, syspar ...
450         fields are delimited by CR or NL or CR-NL
451         within a field, tag stops at blank,TAB,= or :
452         after a TAB, val starts immediately
453         after a = or :, val starts at 1st character not a blank
454         after a blank, val starts at 1st char not one of the above separators
455
456         processing
457 -       a field or record separator is recognized anywhere
458 - within each field, the tag is read up to the first separator
459         (any "special" char, all controls, whitespace and most punctuation).
460         upon reaching a separator, the tag is identified.
461         if it is empty, and the record has a field, now new field is created.
462         else, if the tag cannot be identified,
463         a tag of -1 is used and the tag string appended as value.
464 - the separator consists of any number of leading blanks,
465   some separator char, and, unless the sepchar is TAB, trailing blanks.
466         if the current field is not empty, the separator is appended as value.
467 - the rest of the field is appended as value
468
469 - a field with empty tag and value (blank line)
470         terminates the record in most modes
471 - a field with empty tag (continuation line)
472         has it's separator AND value appended to the previous field
473 - if either a tag or a separator extend over more than 4k,
474         the stream is considered over limit.
475
476 */
477 enum {
478         OPENISIS_STOPONEMPTY =   0x10, /* stop at empty line */
479         OPENISIS_AUTOCLONE   =   0x20, /* clone the record even if not needed */
480         OPENISIS_TRANSPARENT =   0x40, /* do not convert vtabs to newlines */
481         OPENISIS_MAIL        =  0x100, /* process mail body */
482         OPENISIS_MBOX        =  0x200, /* input stream is mbox format */
483         OPENISIS_DETACH      =  0x400, /* detach body */
484         OPENISIS_CONVERT     =  0x800  /* fix body parts */
485 };
486
487 extern int openIsisSGetr ( OpenIsisRecStream *stream );
488
489
490
491 /* ************************************************************
492         record utilities requiring a session
493 */
494
495 /**
496         clone record or create empty record.
497         with room >= 0 and rec != NULL,
498         make sure that there is at least one field and room bytes available.
499         else, it works in shrink-to-fit mode: exactly the required bytes are used.
500         @param rec to extend, may be NULL
501         @param room number of required free bytes (<0 for shrink-to-fit)
502         @param discard wether the original record should be freed after extension
503         @return a rec with suitable room
504 */
505 extern OpenIsisRec* openIsisRDup (
506         OpenIsisRec *r, int room, int discard );
507
508
509 /**
510         printf a new field of up to 1024 bytes at the end of record.
511 */
512 extern OpenIsisRec* openIsisRMsg (
513         OpenIsisRec *r, int discard, int tag, const char *fmt, ... );
514
515 /**
516         check for free headspace in a record.
517         make sure that there is at least one field and room bytes available.
518         NOTE: this may change recp
519         @see openIsisRDup
520 */
521 #define OPENISIS_RSPACE( recp, room, disc ) \
522         do { if ( ! (recp) \
523                 || (recp)->len >= (recp)->fields \
524                 || (recp)->bytes < (recp)->used + (room) \
525         ) (recp) = openIsisRDup( (recp), (room), (disc) ); } while (0)
526
527 /**
528         add a field to a record.
529         a new field entry and n bytes space are provided.
530         if the pointer s is not NULL, n bytes are copied from it to the field.
531         NOTE: this may change recp
532         @see openIsisRDup
533 */
534 #define OPENISIS_RADD( recp, ntag, s, n, disc ) \
535         do { \
536                 int _ll = (n); \
537                 OPENISIS_RSPACE( recp, _ll, disc ); \
538                 if ( (recp) ) { \
539                         OpenIsisField *_ff = (recp)->field + (recp)->len++; \
540                         _ff->tag = (ntag); \
541                         _ff->val = ((char*)recp)+(recp)->used; \
542                         if ( ! s ) \
543                                 _ff->len = 0; \
544                         else \
545                                 memcpy( (char*)_ff->val, s, _ff->len = _ll ); \
546                         (recp)->used += _ff->len; \
547                 } \
548         } while(0)
549
550 /**
551         append n bytes to the last field of a record.
552         NOTE: this may change recp
553         NOTE: this requires the last field to reside at the end of the buffer
554         @see openIsisRDup
555 */
556 #define OPENISIS_RCAT( recp, s, n, disc ) \
557         do { \
558                 OpenIsisField *_ff; \
559                 int _ll = (n); \
560                 assert ( (recp) ); \
561                 assert ( (recp)->len ); \
562                 if ( (recp)->bytes < (recp)->used + _ll ) \
563                         (recp) = openIsisRDup( (recp), _ll, (disc) ); \
564                 _ff = (recp)->field + (recp)->len - 1; \
565                 memcpy( (char*)(_ff->val+_ff->len), s, _ll ); \
566                 _ff->len += _ll; \
567                 (recp)->used += _ll; \
568         } while(0)
569
570 /* like OPENISIS_RADD, but based on strlen */
571 #define OPENISIS_RADDS( recp, ntag, s, disc ) \
572         OPENISIS_RADD( recp, ntag, s, strlen(s), disc )
573 /* like OPENISIS_RADD, but based on field */
574 #define OPENISIS_RADDF( recp, f, disc ) \
575         OPENISIS_RADD( recp, (f)->tag, (f)->val, (f)->len, disc )
576 /* like OPENISIS_RCAT, but based on strlen */
577 #define OPENISIS_RCATS( recp, s, disc ) \
578         OPENISIS_RCAT( recp, s, strlen(s), disc )
579
580 /**
581         create a record from a field, i.e. split subfields.
582         if a rec buffer is given, it is filled up to it's rec->len and returned.
583         else an appropriately allocated rec is returned,
584         which must be freed after usage.
585         NOTE: USE WITH CARE, IT SOMEWHAT BREAKS THE GENERAL CONTRACT OF REC!
586         DO NOT TRY TO EXTEND THE RETURNED RECORD !!!
587         The rec does NOT have it's own data buffer,
588         but instead field values are pointers into the input field's value.
589         The returned rec will therefore become invalid,
590         if the inpur field is freed.
591         @param rec a rec buffer to fill or NULL
592         @param field some string to be split up at '^' characters
593         @return an OpenIsisRec or NULL, if splitting failed.
594 */
595 extern OpenIsisRec *openIsisRSplitf (
596         OpenIsisRec *rec, const OpenIsisField* field );
597
598
599 enum { /* RSet flags */
600         OPENISIS_RARGC = 0xffff, /* argc mask */
601         OPENISIS_RFDT = 0x0010000, /* first vararg is the Fdt to use */
602         OPENISIS_RARGV= 0x0020000, /* next vararg is a char **argv */
603         OPENISIS_RDIS = 0x0040000, /* discard original record on change */
604         OPENISIS_RNOC = 0x0080000, /* do not recompact after CHG/DEL op */
605         OPENISIS_RIGN = 0x0100000, /* ignore unknown fields */
606         /* default op is to append fields at the end */
607         OPENISIS_RCHG = 0x1000000, /* change mode: overwrite previous field values */
608         OPENISIS_RDEL = 0x2000000, /* args is a list of tags to delete */
609         OPENISIS_RDFLT= 0x4000000, /* default mode: set field value only if not already present */
610         OPENISIS_ROP  = 0xf000000  /* op mask */
611 };
612
613 /**
614         set fields in a record.
615         this is going to be the real field setting one-stop-shop.
616         This is called
617         EITHER with real varargs tag, val, tag, val ... 0, stopped by a 0 tag,
618         OR with an char **argv as vararg.
619         In most modes, the varargs are like tag, val, tag, val ...
620         Tags may be either numeric (int) or by field name.
621         Field names are translated to numerical ids by the Fdt,
622         which may be given explicitly or derived from the rec's dbid.
623         @param rec      record to modify or 0 to create new one
624         @param mode bitwise OR of flags and the number of fields (2 byte)
625                 if the number of fields is 0,
626                 args must be zero terminated
627         @return the same record or a copy, depending on space needs
628 */
629 extern OpenIsisRec *openIsisRSet ( OpenIsisRec *rec, int mode, ... );
630
631 /**
632         add serialized "text" to rec
633         supports the RDIS, STOPONEMPTY and TRANSPARENT flags
634         @return # of bytes read
635 */
636 extern int openIsisRDeserialize (
637         OpenIsisRec **rec, const char *buf, int len, int flg );
638
639
640 /**
641         append tag with integer value to rec
642 */
643 extern OpenIsisRec *openIsisRAddI (
644         OpenIsisRec *rec, int tag, int value, int discard);
645
646 enum {
647         OPENISIS_FMT_SHARP = 32,        /* # */
648         OPENISIS_FMT_SLASH,     /* / */
649         OPENISIS_FMT_PERCENT,   /* % */
650         OPENISIS_FMT_OPEN,      /* { */
651         OPENISIS_FMT_CLOSE,     /* } */
652         OPENISIS_FMT_ESC,       /* ! */
653         OPENISIS_FMT_B, /* bold */
654         OPENISIS_FMT_BOX,       /* draw a box (0i) */
655         OPENISIS_FMT_BPICT,     /* draw background pict (1sn) */
656         OPENISIS_FMT_C, /* column (1i) */
657         OPENISIS_FMT_CL,        /* colour (1i) */
658         OPENISIS_FMT_COLS,      /* colour table (s_) - emits a string of hex vals */
659         OPENISIS_FMT_FONTS,     /* font table (s_) */
660         OPENISIS_FMT_FS,        /* font size (1i) */
661         OPENISIS_FMT_F, /* font (1i) */
662         OPENISIS_FMT_I, /* italic */
663         OPENISIS_FMT_LINK,      /* link (2s_) */
664         OPENISIS_FMT_LW,        /* line width (1i) */
665         OPENISIS_FMT_M, /* indentation in twips(1in) */
666         OPENISIS_FMT_NC,        /* new column (0i) */
667         OPENISIS_FMT_NEWLINE,   /* set newline (1s) */
668         OPENISIS_FMT_NP,        /* newpage (0i) */
669         OPENISIS_FMT_PICT,      /* draw pict (1s) */
670         OPENISIS_FMT_QC,        /* center */
671         OPENISIS_FMT_QJ,        /* justify */
672         OPENISIS_FMT_TAB,       /* tab (0i) */
673         OPENISIS_FMT_UL,        /* underline */
674         OPENISIS_FMT_X  /* blanks (1i) */
675 };
676
677 extern OpenIsisRec* openIsisRFmt (
678         OpenIsisRec *buf, const char *fmt, OpenIsisRec *r );
679
680
681
682 /* ************************************************************
683         db access
684 */
685
686 /**
687         get highest rowid in db
688         @param dbid id returned by openIsisOpen
689         @return positive rowid on success, 0 if unknown, negative on error
690 */
691 extern int openIsisDMaxId ( int dbid );
692
693 /**
694         read a cooked row.
695         free the returned pointer after usage.
696         @param db id returned by openIsisOpen
697         @param rowid the mfn
698         @return an OpenIsisRec or NULL, if row not available.
699 */
700 extern OpenIsisRec *openIsisDRead ( int db, int rowid );
701
702 /**
703         for convenience: read and format in one.
704 */
705 extern OpenIsisRec *openIsisDFmt (
706         OpenIsisRec *buf, const char *fmt, int db, int rowid );
707
708
709 /**
710         write a record and/or index entries.
711         If the rowid is 0, the record will be modified by assigning a new rowid.
712         @param db id returned by openIsisOpen
713         @param rec the OpenIsisRec to write
714         @param idx record containing index entries
715         @return 0 or an error code
716 */
717 extern int openIsisDWritex ( int dbid, OpenIsisRec *rec,
718         OpenIsisRec *idx );
719
720 /**
721         write a record as with DWritex.
722         index entries should be derived automatically.
723 */
724 extern int openIsisDWrite ( int dbid, OpenIsisRec *rec );
725 #define OPENISIS_DWRITE( rec ) openIsisDWrite( (rec)->dbid, rec )
726
727
728 /**
729         simple full scan search.
730         read the first row with rowid >= given rowid
731         and containing txt in subfield tag (any, if < 0).
732         free the returned pointer after usage.
733         @param db id returned by openIsisOpen
734         @param rowid the mfn
735         @param tag field in which to look for key, 0 for any
736         @return an OpenIsisRec or NULL, if row not available.
737 */
738 extern OpenIsisRec *openIsisDScan (
739         int db, int rowid, int tag, const char *key );
740
741 /**
742         get a term for key w/ or w/o the postings.
743         prefix mode is determined by a trailing '$' in key.
744         for prefix mode, the last preset field in the record
745         gives a starting point, i.e. terms up to and including
746         it are ignored.
747         thus, if there are more matching terms than fit in the record,
748         the search can be continued by passing the same record.
749
750         @return an OpenIsisRec or NULL
751 */
752 extern OpenIsisRec* openIsisDTerm (
753         OpenIsisRec *rec, int db, const char *key );
754
755
756 #ifndef OPENISIS_SETLEN
757 #define OPENISIS_SETLEN 1000
758 #endif
759
760 /**
761         record set type as returned from openIsisSearch.
762         first entry is the set length n, followed by rowids 1..n.
763         actual array length is thus n+1.
764 */
765 typedef struct {
766         int len;
767         int id[OPENISIS_SETLEN];
768 } OpenIsisSet;
769
770
771 /* query mode */
772 enum {
773         /* search given string using index */
774         OPENISIS_QRY_KEYEQ, /* index scan key equal */
775         OPENISIS_QRY_KEYPF, /* index scan key prefix */
776         OPENISIS_QRY_KEYAT, /* index scan key auto (checks for '$') */
777         /* fulltext scan for given string */
778         OPENISIS_QRY_SCANE=64, /* fulltext scan for equal */
779         OPENISIS_QRY_SCANC, /* fulltext scan for contains */
780         /* parse string as query expression */
781         OPENISIS_QRY_SIMPLE=128, /* simple left-to-right binding */
782         OPENISIS_QRY_PROPER /* proper binding using precedence, () */
783 };
784
785
786 /**
787         query the db.
788         @param set set buffer to fill.
789                 set->len must contain the actual buffer length (# of ids).
790                 0 means default length OPENISIS_SETLEN.
791         @param db id returned by openIsisOpen
792         @param key keyword or query expression to search for
793         @param mode query mode, optionally |ed with a field tag<<16.
794                 a field tag affects key and scan modes.
795         @param skip mfns < skip are ignored, useful to continue a query
796         @return the number of rowids in set (= set->len) on success, <0 on error.
797 */
798 extern int openIsisDQuery ( OpenIsisSet *set, int db,
799         const char *key, int mode, int skip );
800
801
802 /**
803         callback for index loop
804 */
805 typedef int OpenIsisDXCb ( void *me, OpenIsisKey *key, OpenIsisHit *hit );
806
807 typedef struct {
808         int            flg;
809         void          *me; /* commonly the session */
810         OpenIsisDXCb  *cb;
811         OpenIsisKey    key;
812         OpenIsisKey    to;
813 }       OpenIsisDXLoop;
814
815 enum { /* flags */
816         OPENISIS_IDXPF   = 0, /* loop where from is prefix of key */
817         OPENISIS_IDXEQ   = 1, /* loop from == key */
818         OPENISIS_IDXUPTO = 2, /* loop from <= key < to */
819         OPENISIS_IDXINCL = 3, /* loop from <= key <= to */
820         OPENISIS_IDXMODE = 0x03, /* mask for match mode */
821         OPENISIS_IDXTRAD = 0x10000  /* use traditional index */
822 };
823
824 /**
825 */
826 extern int openIsisDXLoop ( int dbid, OpenIsisDXLoop *l );
827
828
829
830 /* ************************************************************
831         system control -- session 0 only
832 */
833
834 enum {
835         /* system (schema 0) parameters */
836         OPENISIS_SPATH   = 5, /* db dir */
837         OPENISIS_SLOGF   = 700, /* logfile */
838         OPENISIS_SLOGV   = 701, /* verbosity */
839         /* schema parameters */
840         OPENISIS_SC_NAME   = 710, /* schema n name */
841         OPENISIS_SC_HOST   = 711, /* schema n host */
842         OPENISIS_SC_PORT   = 712, /* schema n port */
843         OPENISIS_SC_DFLTDB = 721, /* schema default db */
844         /* database parameters */
845         OPENISIS_DNAME = 800,
846         OPENISIS_DTYPE = 801,
847         OPENISIS_DRO   = 802,
848         OPENISIS_DPATH = 803,
849         OPENISIS_DDUMP = 804,
850         OPENISIS_DENC  = 810, /* encoding */
851         OPENISIS_DFDT  = 811, /* path to serialized fdt */
852         OPENISIS_DFMT  = 850, /* worksheets */
853         OPENISIS_DPFT  = 851, /* printformats */
854         OPENISIS_DFST  = 852, /* field selections */
855         /* fdt entries */
856         OPENISIS_FDID    = 860, /* tag */
857         OPENISIS_FDSUB   = 861, /* subfield char */
858         OPENISIS_FDTYPE  = 862, /* field type */
859         OPENISIS_FDREP   = 863, /* repeatable flag */
860         OPENISIS_FDNUMC  = 864,
861         OPENISIS_FDLEN   = 865, /* length: 0 variable, >0 maxlen, <0 fixed len */
862         OPENISIS_FDNAME  = 866, /* field name */
863         OPENISIS_FDDESC  = 867, /* field description */
864         OPENISIS_FDPAT   = 868, /* pattern */
865         OPENISIS_FDDFLT  = 869, /* default value */
866         OPENISIS_FDINFO  = 870, /* application specific addons */
867         OPENISIS_FDCHLD  = 871,
868         OPENISIS_FDT_LEN = 880, /* fdt: number of fd's */
869         OPENISIS_FDT_FD  = 881, /* fdt: embedded fd */
870         OPENISIS_FDT_REC = 882, /* fdt: application specific addons */
871         /* communication parameters */
872         OPENISIS_COM_SID    = 900,  /* session id */
873         OPENISIS_COM_SER    = 901,  /* serial no of request */
874         OPENISIS_COM_DBN    = 902,  /* db name */
875         OPENISIS_COM_TMS    = 903,  /* server timestamp */
876         OPENISIS_COM_ROW    = 904,  /* rowid */
877         OPENISIS_COM_CFG    = 907,  /* embedded cfg */
878         OPENISIS_COM_REC    = 908,  /* embedded data record */
879         /* communication parameters: request */
880         OPENISIS_RQS_TYPE   = 920,  /* request type */
881         OPENISIS_RQS_FLG    = 921,  /* flags */
882         OPENISIS_RQS_QMOD   = 922,  /* mode (query) */
883         OPENISIS_RQS_SKIP   = 923,  /* skip (query) */
884         OPENISIS_RQS_SIZE   = 924,  /* output size (query) */
885         OPENISIS_RQS_KEY    = 925,  /* key value (query) */
886         OPENISIS_RQS_IDX    = 926,  /* index record (insert, update) */
887         /**     communication parameters: response */
888         OPENISIS_RSP_DBID   = 940,  /* local db id */
889         OPENISIS_RSP_ERR    = 941,  /* error code */
890         OPENISIS_RSP_MSG    = 942,  /* error message */
891         OPENISIS_RSP_NUMT   = 943,  /* total number of records (query, read) */
892         OPENISIS_RSP_NUMR   = 944,  /* number in this response (query, read) */
893         OPENISIS_RSP_CERR   = 945   /* client side error */
894 };
895
896 extern const OpenIsisFdt *openIsisFdtSyspar; /* schema 0 */
897 extern const OpenIsisFdt *openIsisFdtScheme; /* schema n */
898 extern const OpenIsisFdt *openIsisFdtDbpar;  /* db cfg */
899 extern const OpenIsisFdt *openIsisFdtFd;     /* fd rec */
900 extern const OpenIsisFdt *openIsisFdtFdt;    /* fdt rec */
901 extern const OpenIsisFdt *openIsisFdtRqs;    /* request rec */
902 extern const OpenIsisFdt *openIsisFdtRsp;    /* response rec */
903
904 /** request types. */
905 enum {
906         OPENISIS_RQST_OPEN     =  1, /* open db */
907         OPENISIS_RQST_CLOS     =  3, /* close db */
908         OPENISIS_RQST_MNT      =  4, /* mount db */
909         OPENISIS_RQST_LSDB     =  6, /* list available dbs */
910         OPENISIS_RQST_MROW     = 10, /* get maxrowid of db */
911         OPENISIS_RQST_QRY      = 11, /* exec query on db */
912         OPENISIS_RQST_READ     = 12, /* get rec for rowid */
913         OPENISIS_RQST_INS      = 20, /* insert rec */
914         OPENISIS_RQST_UPD      = 21, /* update rec */
915         OPENISIS_RQST_DEL      = 22, /* delete row */
916         OPENISIS_RQST_EVAL     = 30  /* command evaluation */
917 };
918
919 /** request flags. */
920 enum {
921         OPENISIS_RQSF_MNT   = 0x0001, /* mount db */
922         OPENISIS_RQSF_QRR   = 0x0002  /* fetch records on query */
923 };
924
925 /** max length of key in query request. */
926 #define OPENISIS_QRY_KEYLEN 1024
927 /** max length of error messages. */
928 #define OPENISIS_ERRMSGLEN  1024
929
930 enum {
931         OPENISIS_RELE = 0x0000000, /* release, unlock */
932         OPENISIS_LOCK = 0x1000000,
933         OPENISIS_WAKE = 0x2000000, /* broadcast signal, notifyall */
934         OPENISIS_WAIT = 0x3000000,
935         OPENISIS_COND = 0x0ffffff  /* condition mask */
936 };
937 /** a function to provide a global lock in a multi threaded process.
938         @param lock coded action.
939                 the high byte is one of release, lock, wake and wait.
940                 the lower bytes indicate a condition for wake and wait.
941                 the value may be hashed to a small set of conditions,
942                 typically eight or one (ignore).
943         @return 0 on success
944 sample with a single condition:
945 int myOpenIsisLockFunc ( int lock )
946 {
947         static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
948         static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
949         switch ( OPENISIS_WAIT & lock ) {
950         case OPENISIS_RELE: return pthread_mutex_unlock( &mut );
951         case OPENISIS_LOCK: return pthread_mutex_lock( &mut );
952         case OPENISIS_WAKE: return pthread_cond_broadcast( &cond );
953         case OPENISIS_WAIT: return pthread_cond_wait( &cond, &mut );
954         }
955         return -1;
956 }
957 */
958 typedef int OpenIsisCLockFunc ( int lock );
959
960 /** initialize system with some common parameters and a lock func.
961         @param lock a function to provide a global lock in a multi threaded process.
962 */
963 extern int openIsisCInit ( int argc, const char **argv,
964         OpenIsisCLockFunc lock );
965
966 /**
967         set logging level and device.
968         @param level the logging level
969                 may be given numerical or as ascii char in -ofsewivtda for
970                 nochange(-1), off (0), fatal (1), syserr, error, warn, info, verbose,
971                 trace, debug, all(9)
972                 default is set to error
973         @param filename specifies, if not NULL, a file to append log to
974 */
975 extern void openIsisCLog ( int level, const char *filename );
976
977
978 /** get the default session, possibly adding args.
979         only one (session master) thread in a process may call this.
980         @param args initialisation properties (cloned to prop)
981 */
982 extern OpenIsisSession openIsisCOpen ( OpenIsisRec *args );
983
984 /** get a new session.
985         only one (session master) thread in a process may call this.
986         @param args initialisation properties (cloned to prop)
987 */
988 extern OpenIsisSession openIsisCSession ( OpenIsisRec *args );
989
990
991 /* ************************************************************
992         schema
993 */
994
995 #define OPENISIS_SC_NAMELEN  32 /* max length of schema identification */
996 #define OPENISIS_DB_NAMELEN  32 /* max length of db id relative to schema */
997
998 #define OPENISIS_SCIDMSK  0x0ff00  /* schema part of id */
999 #define OPENISIS_DBIDMSK  0x000ff  /* db part of id */
1000
1001 typedef struct {
1002         char           name[OPENISIS_DB_NAMELEN];
1003         int            dbid;
1004         int            mntcnt; /* number of sessions currently using this */
1005         int            tms;    /* last (re)opening timestamp */
1006         OpenIsisRec   *cfg;
1007         OpenIsisFdt   *fdt;
1008 } OpenIsisDb;
1009
1010 typedef struct {
1011         char           name[OPENISIS_SC_NAMELEN];
1012         int            scid;
1013         int            mntcnt;
1014         OpenIsisRec   *cfg;
1015         int            ndbs;
1016         OpenIsisDb   **dbs;
1017 } OpenIsisSchema;
1018
1019 /* ************************************************************
1020         client side
1021 */
1022
1023 typedef struct OpenIsisStb *OpenIsisStub;
1024
1025 /**     function that sends request record rqs to remote address of stb
1026 */
1027 typedef int OpenIsisStbRqsProc (OpenIsisStub stb, OpenIsisRec *rqs);
1028
1029 /**     callback for freeing external resources when a stub is deleted.
1030         @param client_data client_data registered in openIsisNOpen
1031 */
1032 typedef void OpenIsisStbDelProc (OpenIsisStub stb, void *client_data);
1033
1034 /**     deprecated
1035 */
1036 typedef int OpenIsisRspCb (void *client_data,
1037         OpenIsisStub stub, OpenIsisRec *response, OpenIsisDb *db);
1038
1039 typedef struct {
1040         /*      function for request sending.
1041                 if 0, defaults to internal blocking sender
1042         */
1043         int (*sendproc) (OpenIsisStub stub, OpenIsisRec *rqs);
1044         /*      default response callback */
1045         OpenIsisRspCb  *dfltcb;
1046         /*      delete callback: cleanup client data cbd that is no longer
1047                 used. if 0==cbd, session is going to be deleted.
1048         */
1049         void (*delcb) (void *cld, OpenIsisStub session, void *cbd);
1050         /*      client data for dfltcb */
1051         void *dfltcld; 
1052         /*      client data for delcb */
1053         void *delcld; 
1054 } OpenIsisStubCbData;
1055
1056 extern OpenIsisStub openisis_stub0;
1057
1058 /**     create stub for local schema.
1059 */
1060 extern OpenIsisStub openIsisNInit (
1061         int argc, const char **argv, OpenIsisStubCbData *dta
1062 );
1063
1064 /**     destroy local schema.
1065 */
1066 extern void openIsisNDeinit ();
1067
1068 /**     create a new stub.
1069 */
1070 extern OpenIsisStub openIsisNOpen (
1071         const char *name, int argc, const char **argv, OpenIsisStubCbData *dta
1072 );
1073
1074 /**     destroy a stub.
1075 */
1076 extern void openIsisNClose (OpenIsisStub stub);
1077
1078 /**     get schema from stub.
1079 */
1080 extern OpenIsisSchema* openIsisNSchema (OpenIsisStub stub);
1081
1082 /**     send request.
1083         SID,SER,TMS are set in this call.
1084         Note: rqs (or the internal copy) will be freed at the next call
1085                 to openIsisNClean or openIsisNSend.
1086         @param stub communication partner
1087         @param rqs request parameter
1088         @param actcb optional async callback for this request
1089         @param actcld optional client data for actcb
1090         @param rdup make a internal copy of rqs
1091         @return 0 on success
1092 */
1093 extern int openIsisNSend (
1094         OpenIsisStub stub, OpenIsisRec *rqs,
1095         OpenIsisRspCb *actcb, void *actcld, int rdup
1096 );
1097
1098 /**     get stub's response record.
1099         @param dbid optional db id of embedded result records
1100 */
1101 extern OpenIsisRec *openIsisNRecv (OpenIsisStub stub, OpenIsisDb **db);
1102
1103 /**     clean request, response, session used in last openIsisNSend call.
1104 */
1105 extern void openIsisNClean (OpenIsisStub stub);
1106
1107 /** util: unwrap embbeded response records.
1108 */
1109 extern int openIsisNGetResult (OpenIsisStub stub,
1110         int **rowids, OpenIsisRec ***recs, OpenIsisDb **db, int *total);
1111
1112 /**     Notification of a successfully received response record.
1113         Interface for applications that handle asynchronous communications
1114         with a remote server.
1115         @param rsp address of received response record
1116 */
1117 extern void openIsisNNotifyResponse (OpenIsisStub stub, OpenIsisRec **rsp);
1118
1119 /**     Error notification when server communication breaks down.
1120         Interface for applications that handle asynchronous communications
1121         with a remote server.
1122         @param errcode reason of failure
1123 */
1124 extern void openIsisNNotifyError (OpenIsisStub stub, int errcode);
1125
1126 /**     get communication channel from stub.
1127 */
1128 extern struct CliChnl* openIsisNGetChannel (OpenIsisStub stub);
1129
1130 /**     get db by name.
1131 */
1132 extern OpenIsisDb *openIsisNDbByName (OpenIsisStub stub, const char *dbname);
1133
1134 /**     get db by id.
1135 */
1136 extern OpenIsisDb *openIsisNDbById (int dbid);
1137
1138
1139 /* ************************************************************
1140         db control
1141 */
1142
1143 /**
1144         open an isis database.
1145         The following options are supported as text-style parameters:
1146         <ul>
1147         <li>db &lt;name&gt;<br>
1148                 basename of database. same as param dbname.
1149         </li>
1150         <li>dbpath &lt;path&gt;<br>
1151                 path to database. usefull when opening secondary indexes
1152                 or other files whose names are not based on the db basename.
1153         </li>
1154         <li>v &lt;level&gt;<br>
1155                 set verbosity level
1156         </li>
1157         </ul>
1158         @param dbname identification name of database.
1159                 the dbpath arg, if given, will be prepended, and the ISIS file
1160                 extensions appended to build the actual filename.
1161                 dbname may be NULL, if argv includes a db arg.
1162         @param argv array of names and values.
1163                 May be NULL.
1164                 argv contains parameter names, which may be prefixed
1165                 by a dash '-'. See the syspar and dbpar fdt above for
1166                 supported parameter names.
1167                 Unrecognized parameter names are ignored.
1168         @param argc length of argv.
1169                 You may supply -1 to indicate that argv is NULL terminated.
1170         @param syspar optional syspar record
1171         @param dbpar optional dbpar record, a clone will be saved in the
1172                 db header cfg rec
1173         @param fdt optional fdt of this db, the reference will be saved
1174                 in the db header fdt, so fdt must *NOT* be freed after call
1175         @return db structure or 0 on error
1176 */
1177 extern OpenIsisDb* openIsisCDOpen ( const char *dbname,
1178         OpenIsisRec *dbpar, OpenIsisRec *syspar, OpenIsisFdt *fdt );
1179 /**     
1180         open by vector
1181         @return some non-negative dbid on success,
1182                 some negative errorcode on error.
1183                 Errorcodes include -ENOENT, -ENOMEM, -EACCESS and others
1184                 returned by file access functions.
1185 */
1186 extern int openIsisCDOpenv ( const char *dbname, const char **argv, int argc );
1187
1188 enum {
1189         OPENISIS_CHK_ONLY = 0x01,       /* check only, do not fix */
1190         OPENISIS_CHK_XRF  = 0x02,       /* check the xrf */
1191         OPENISIS_CHK_FIX  = 0xfe,       /* check all and fix */
1192         OPENISIS_CHK_ALL  = 0xff        /* check all, no fix */
1193 };
1194 /** check and optionally fix the database.
1195 */
1196 extern int openIsisCDCheck ( int dbid, int flags );
1197
1198
1199
1200 /**
1201         close a database.
1202         @param dbid id returned by openIsisOpen
1203         @return 0 on success, some negative errorcode else.
1204 */
1205 extern int openIsisCDClose ( int dbid );
1206
1207
1208 /* ************************************************************
1209         low level index access
1210
1211         DO NOT USE unless you know what you're doing !!!!!!!!!
1212
1213 */
1214
1215 typedef struct OpenIsisIdx *OpenIsisIndex;
1216
1217 /**
1218         get the db's index for loading.
1219         the index may not be access until the loading session is finished.
1220         @param mode lowest byte give percent free for index
1221 */
1222 extern OpenIsisIndex openIsisCXOpen ( int dbid, int mode );
1223
1224 /**
1225         load a sorted series of keys and hits into index.
1226         @param key may be NULL to append to previous key.
1227         @param hit a value of NULL terminates the loading session
1228 */
1229 extern int openIsisCXAdd ( OpenIsisIndex idx,
1230         OpenIsisKey *key, OpenIsisHit *hit );
1231
1232 #define openIsisCXClose( idx ) openIsisCXAdd( idx, 0, 0 )
1233
1234 #ifdef _REENTRANT
1235 extern int openisis_threaded;
1236 #endif
1237
1238 /* ************************************************************
1239         single session and legacy mode pre 0.9
1240 */
1241
1242 /** raw version of an ISIS field.
1243         * off gives an offset from the start of the record taken as char*.
1244         * values are *NOT* terminated by a 0 byte.
1245 */
1246 typedef struct {
1247         /*
1248         although isis-1 dbs have only 2 bytes for field tags (numbers),
1249         we use ints with the lower 3 bytes for the tag.
1250         The highest byte may have special usage in some context.
1251         */
1252         int tag;
1253         int off;
1254         int len;
1255 } OpenIsisFld;
1256
1257 /** raw version of an ISIS Record. rarely used.
1258 */
1259 typedef struct {
1260         int         dbid;
1261         int         rowid;
1262         int         bytes; /* total avail bytes */
1263         int         used; /* total used bytes (originally BWB) */
1264         int         fields;  /* avail number of fields (originally BWP) */
1265         int         base; /* byte offset of contents area (after fields) */
1266         int         len;        /* used number of fields */
1267         int         state;
1268         OpenIsisFld field[1];
1269 } OpenIsisRaw;
1270
1271 /** read raw. */
1272 extern OpenIsisRaw *openIsisDRaw ( int db, int rowid );
1273
1274 #ifndef OPENISIS_NOPRE09
1275
1276
1277 /* utilities */
1278 #define openIsis2Html( str, len ) \
1279         openIsisToHtml ( str, len )
1280 #define openIsisValidUTF8( mem, len, tof ) \
1281         openIsisUtf8Chk ( mem, len, tof )
1282
1283 /* record tools */
1284 #define openIsisClone( r, ro, d ) \
1285         openIsisRDup( r, ro, d )
1286 /* GNUC only, and waaarns ...
1287 #define openIsisPrintf( r, d, t, f, a... ) \
1288         openIsisRMsg( r, d, t, f, ## a )
1289 */
1290 #define OPENISIS_CHKFREE( recp, room, disc ) \
1291         OPENISIS_RSPACE( recp, room, disc )
1292 #define OPENISIS_ADD( recp, ntag, s, n, disc ) \
1293         OPENISIS_RADD( recp, ntag, s, n, disc )
1294 #define OPENISIS_CAT( recp, s, n, disc ) \
1295         OPENISIS_RCAT( recp, s, n, disc )
1296 #define OPENISIS_SADD( recp, ntag, s, disc ) \
1297         OPENISIS_RADDS( recp, ntag, s, disc )
1298 #define OPENISIS_SCAT( recp, s, disc ) \
1299         OPENISIS_RCATS( recp, s, disc )
1300 #define openIsisReadField( rec, f ) \
1301         openIsisRSplitf( rec, f )
1302 #define openIsisFmt( buf, fmt, r ) \
1303         openIsisRFmt( buf, fmt, r )
1304 #define openIsisReadStream( stream ) \
1305         openIsisSGetr( stream )
1306
1307 /* database */
1308 #define openIsisMaxRowid( db ) \
1309         openIsisDMaxId( db )
1310 #define openIsisReadRow( db, rowid ) \
1311         openIsisDRead( db, rowid )
1312 #define openIsisReadRaw( db, rowid ) \
1313         openIsisDRaw( db, rowid )
1314 #define openIsisRead( buf, fmt, db, rowid ) \
1315         openIsisDFmt( buf, fmt, db, rowid )
1316 #define openIsisWrite( db, r ) \
1317         openIsisDWrite( db, r )
1318 #define openIsisWritex( db, r, i ) \
1319         openIsisDWritex( db, r, i )
1320 #define openIsisScan( db, rowid, tag, key ) \
1321         openIsisDScan( db, rowid, tag, key )
1322 #define openIsisTerm( rec, db, key ) \
1323         openIsisDTerm( rec, db, key )
1324 #define openIsisQuery( set, db, key, mode, skip ) \
1325         openIsisDQuery( set, db, key, mode, skip )
1326 /* database index */
1327 #define OpenIsisIdxCb OpenIsisDXCb
1328 #define OpenIsisIdxLoop OpenIsisDXLoop
1329 #define openIsisIdxLoop( dbis, cb ) \
1330         openIsisDXLoop( dbis, cb )
1331
1332 /* system control (main session only) */
1333 #define openIsisLog openIsisCLog
1334 #define OpenIsisLockFunc OpenIsisCLockFunc
1335 #define openIsisInit( argc, argv, lock ) \
1336         openIsisCInit( argc, argv, lock )
1337 #define openIsisSesGet( id, args ) \
1338         (id) ? openIsisCSession( args ) : openIsisCOpen( args )
1339 /* database control (main session only) */
1340 #define openIsisOpen openIsisCDOpenv
1341 #define openIsisCheck openIsisCDCheck
1342 #define openIsisClose openIsisCDClose
1343 /* database index control (main session only) */
1344 #define openIsisIdxOpen openIsisCXOpen
1345 #define openIsisIdxAdd openIsisCXAdd
1346 #define openIsisIdxDone( idx ) openIsisCXClose( idx )
1347
1348 #endif  /* OPENISIS_NOPRE09 */
1349
1350 #ifdef __cplusplus
1351 }
1352 #endif /* extern "C" */
1353 #define OPENISIS_H
1354 #endif /* OPENISIS_H */