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
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.
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.
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
20 see README for more information
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
30 #define OPENISIS_VERSION "0.9.0"
42 /* ************************************************************
46 /** cooked version of an ISIS field.
47 * values are *NOT* terminated by a 0 byte.
49 typedef struct OpenIsisField {
56 /** cooked version of an ISIS Record.
58 typedef struct OpenIsisRec {
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 */
67 OpenIsisField field[1];
70 /* compute base from fields (for both raw and cooked record) */
71 #define OPENISIS_BASESZ( nfields ) ((int)sizeof(int)*(8 + 3*(nfields)))
73 /* initialise record of f fields, n bytes */
74 #define OPENISIS_INITREC( r, n, f ) \
79 (r)->used = (r)->base = OPENISIS_BASESZ( (r)->fields ); \
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 ) \
88 (r)->len = (r)->state = 0; \
89 (r)->used = (r)->base = OPENISIS_BASESZ( (r)->fields ); \
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 ) )
100 /** field description.
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) */
118 #define OPENISIS_FD_NAMELEN 32
119 typedef struct OpenIsisFd {
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 */
135 /** field description table.
140 OpenIsisRec *rec; /* additional fields like formats, worksheets ... */
141 /* additional internal data like a hash might follow */
145 typedef struct { /* where a key has a hit */
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 */
156 unsigned char byt[23];
162 unsigned char byt[255];
166 /** Writex tags, see doc/Inverted.
167 Non-negative tags add (or delete) themselves.
168 Negative control indexing.
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 */
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
186 extern OpenIsisField *openIsisRGet ( OpenIsisRec *r, int tag, int *pos );
188 extern OpenIsisField *openIsisROccurence ( OpenIsisRec *r, int tag, int occ );
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.
194 extern int openIsisA2i ( const char *p, int l );
195 /** similar to openIsisA2i but
196 - return number of parsed characters
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
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)
208 extern int openIsisI2a ( char *p, int i );
209 extern int openIsisU2a ( char *p, unsigned u );
212 get field value as int as of A2i.
213 boolean values are recognized as 0 and 1.
214 if not found, return def.
216 extern int openIsisRInt ( OpenIsisRec *r, int tag, int def, int *pos );
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.
223 extern int openIsisRInt2 (OpenIsisRec *rec,
224 OpenIsisRec *dflt, int tag, int def);
227 get field value as enum.
228 if not found, return def.
230 extern int openIsisREnum ( OpenIsisFdt *fdt,
231 OpenIsisRec *r, int tag, int def, int *pos );
234 get field value as string of length len (including 0-byte).
235 if not found, return 0.
237 extern char* openIsisRString (OpenIsisRec *r,
238 int tag, int *pos, char *buf, int len);
241 * get field value as string from rec or default rec.
243 extern char* openIsisRString2 (OpenIsisRec *rec,
244 OpenIsisRec *dflt, int tag, char *buf, int len);
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
256 extern int openIsisRSerialize ( char *buf, OpenIsisRec *rec );
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)
261 extern int openIsisRSerializeBin ( char *buf, OpenIsisRec *rec );
263 /** alloc buffer with appropriate length, if necessary.
264 @param *len input: length of buf
265 @param *len output: length of serialized record written
267 @return buffer, must be freed after usage if reallocated (i.e. != buf),
270 extern char* openIsisRSerializeAlloc (OpenIsisRec *rec, char *buf, int *len);
272 /** flatten fully transparently,
273 replacing newlines with newline-tab.
274 extern int openIsisRBinSerialize ( char *buf, int len, OpenIsisRec *rec );
277 /* ************************************************************
281 /** get field description by id (tag).
283 extern OpenIsisFd* openIsisFById ( const OpenIsisFdt *fdt, int id, int subf );
285 /** get field description by name.
287 extern OpenIsisFd* openIsisFByName (const OpenIsisFdt *fdt, const char *name);
290 OPENISIS_NOENUM = 0x10000 /* enum NOENUM :) -- not a short */
293 /** lookup enum value for field id.
294 name must be exact match or unique prefix.
295 @return the enum value or NOENUM
297 extern int openIsisFEnum ( OpenIsisFdt *fdt, int id, const char *name );
299 /** free fdt and fd structures.
302 extern OpenIsisFdt* openIsisFFree (OpenIsisFdt *fdt);
304 /** convert fdt to record.
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
311 extern OpenIsisRec* openIsisFFdt2Rec (
312 const OpenIsisFdt *fdt, OpenIsisRec *rec, int embchld);
314 /** build fdt from rec.
316 @return fdt or null on error
318 extern OpenIsisFdt* openIsisFRec2Fdt (OpenIsisRec *rec);
321 /* ************************************************************
322 session type and utilities
325 typedef struct OpenIsisSes *OpenIsisSession;
327 extern void *openIsisMAlloc ( int size );
328 extern void openIsisMFree ( void *mem );
329 extern void *openIsisMDup ( const void *str, int size );
332 convert string to html by replacing the four characters
333 <,>,& and ".
334 free the returned pointer after usage.
335 XML has a fifth standard entity apos,
336 but many HTML clients don't grok it.
338 extern char *openIsisToHtml ( const char *str, int len );
339 extern int openIsisUtf8Chk ( void *mem, int len, int *tof );
342 /* ************************************************************
346 typedef struct OpenIsisIos *OpenIsisStream;
347 typedef int OpenIsisSFunc ( OpenIsisStream s, int op );
349 extern int openIsisSOpen ( const char *name, int flags, OpenIsisSFunc *type );
352 error and loglevel codes one nibble each.
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 */
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 */
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 */
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 ...
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 */
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.
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
425 extern int openIsisSMsg ( int to, const char *fmt, ... );
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.
436 extern int openIsisSGets ( int fd, char **ptr, char delim );
437 #define openIsisSReadln( p ) openIsisSGets( 0, p, '\n' )
439 typedef struct OpenIsisRecStream {
440 OpenIsisStream in; /* input stream to read from */
442 OpenIsisRec *buf; /* original buffer */
443 OpenIsisRec *rec; /* record read */
444 OpenIsisRec *dict; /* dictionary of field names */
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
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
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.
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 */
487 extern int openIsisSGetr ( OpenIsisRecStream *stream );
491 /* ************************************************************
492 record utilities requiring a session
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
505 extern OpenIsisRec* openIsisRDup (
506 OpenIsisRec *r, int room, int discard );
510 printf a new field of up to 1024 bytes at the end of record.
512 extern OpenIsisRec* openIsisRMsg (
513 OpenIsisRec *r, int discard, int tag, const char *fmt, ... );
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
521 #define OPENISIS_RSPACE( recp, room, disc ) \
523 || (recp)->len >= (recp)->fields \
524 || (recp)->bytes < (recp)->used + (room) \
525 ) (recp) = openIsisRDup( (recp), (room), (disc) ); } while (0)
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
534 #define OPENISIS_RADD( recp, ntag, s, n, disc ) \
537 OPENISIS_RSPACE( recp, _ll, disc ); \
539 OpenIsisField *_ff = (recp)->field + (recp)->len++; \
541 _ff->val = ((char*)recp)+(recp)->used; \
545 memcpy( (char*)_ff->val, s, _ff->len = _ll ); \
546 (recp)->used += _ff->len; \
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
556 #define OPENISIS_RCAT( recp, s, n, disc ) \
558 OpenIsisField *_ff; \
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 ); \
567 (recp)->used += _ll; \
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 )
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.
595 extern OpenIsisRec *openIsisRSplitf (
596 OpenIsisRec *rec, const OpenIsisField* field );
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 */
614 set fields in a record.
615 this is going to be the real field setting one-stop-shop.
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
629 extern OpenIsisRec *openIsisRSet ( OpenIsisRec *rec, int mode, ... );
632 add serialized "text" to rec
633 supports the RDIS, STOPONEMPTY and TRANSPARENT flags
634 @return # of bytes read
636 extern int openIsisRDeserialize (
637 OpenIsisRec **rec, const char *buf, int len, int flg );
641 append tag with integer value to rec
643 extern OpenIsisRec *openIsisRAddI (
644 OpenIsisRec *rec, int tag, int value, int discard);
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) */
677 extern OpenIsisRec* openIsisRFmt (
678 OpenIsisRec *buf, const char *fmt, OpenIsisRec *r );
682 /* ************************************************************
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
691 extern int openIsisDMaxId ( int dbid );
695 free the returned pointer after usage.
696 @param db id returned by openIsisOpen
698 @return an OpenIsisRec or NULL, if row not available.
700 extern OpenIsisRec *openIsisDRead ( int db, int rowid );
703 for convenience: read and format in one.
705 extern OpenIsisRec *openIsisDFmt (
706 OpenIsisRec *buf, const char *fmt, int db, int rowid );
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
717 extern int openIsisDWritex ( int dbid, OpenIsisRec *rec,
721 write a record as with DWritex.
722 index entries should be derived automatically.
724 extern int openIsisDWrite ( int dbid, OpenIsisRec *rec );
725 #define OPENISIS_DWRITE( rec ) openIsisDWrite( (rec)->dbid, rec )
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
735 @param tag field in which to look for key, 0 for any
736 @return an OpenIsisRec or NULL, if row not available.
738 extern OpenIsisRec *openIsisDScan (
739 int db, int rowid, int tag, const char *key );
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
747 thus, if there are more matching terms than fit in the record,
748 the search can be continued by passing the same record.
750 @return an OpenIsisRec or NULL
752 extern OpenIsisRec* openIsisDTerm (
753 OpenIsisRec *rec, int db, const char *key );
756 #ifndef OPENISIS_SETLEN
757 #define OPENISIS_SETLEN 1000
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.
767 int id[OPENISIS_SETLEN];
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, () */
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.
798 extern int openIsisDQuery ( OpenIsisSet *set, int db,
799 const char *key, int mode, int skip );
803 callback for index loop
805 typedef int OpenIsisDXCb ( void *me, OpenIsisKey *key, OpenIsisHit *hit );
809 void *me; /* commonly the session */
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 */
826 extern int openIsisDXLoop ( int dbid, OpenIsisDXLoop *l );
830 /* ************************************************************
831 system control -- session 0 only
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,
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 */
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 */
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 */
904 /** request types. */
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 */
919 /** request flags. */
921 OPENISIS_RQSF_MNT = 0x0001, /* mount db */
922 OPENISIS_RQSF_QRR = 0x0002 /* fetch records on query */
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
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 */
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).
944 sample with a single condition:
945 int myOpenIsisLockFunc ( int lock )
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 );
958 typedef int OpenIsisCLockFunc ( int lock );
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.
963 extern int openIsisCInit ( int argc, const char **argv,
964 OpenIsisCLockFunc lock );
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,
972 default is set to error
973 @param filename specifies, if not NULL, a file to append log to
975 extern void openIsisCLog ( int level, const char *filename );
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)
982 extern OpenIsisSession openIsisCOpen ( OpenIsisRec *args );
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)
988 extern OpenIsisSession openIsisCSession ( OpenIsisRec *args );
991 /* ************************************************************
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 */
998 #define OPENISIS_SCIDMSK 0x0ff00 /* schema part of id */
999 #define OPENISIS_DBIDMSK 0x000ff /* db part of id */
1002 char name[OPENISIS_DB_NAMELEN];
1004 int mntcnt; /* number of sessions currently using this */
1005 int tms; /* last (re)opening timestamp */
1011 char name[OPENISIS_SC_NAMELEN];
1019 /* ************************************************************
1023 typedef struct OpenIsisStb *OpenIsisStub;
1025 /** function that sends request record rqs to remote address of stb
1027 typedef int OpenIsisStbRqsProc (OpenIsisStub stb, OpenIsisRec *rqs);
1029 /** callback for freeing external resources when a stub is deleted.
1030 @param client_data client_data registered in openIsisNOpen
1032 typedef void OpenIsisStbDelProc (OpenIsisStub stb, void *client_data);
1036 typedef int OpenIsisRspCb (void *client_data,
1037 OpenIsisStub stub, OpenIsisRec *response, OpenIsisDb *db);
1040 /* function for request sending.
1041 if 0, defaults to internal blocking sender
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.
1049 void (*delcb) (void *cld, OpenIsisStub session, void *cbd);
1050 /* client data for dfltcb */
1052 /* client data for delcb */
1054 } OpenIsisStubCbData;
1056 extern OpenIsisStub openisis_stub0;
1058 /** create stub for local schema.
1060 extern OpenIsisStub openIsisNInit (
1061 int argc, const char **argv, OpenIsisStubCbData *dta
1064 /** destroy local schema.
1066 extern void openIsisNDeinit ();
1068 /** create a new stub.
1070 extern OpenIsisStub openIsisNOpen (
1071 const char *name, int argc, const char **argv, OpenIsisStubCbData *dta
1076 extern void openIsisNClose (OpenIsisStub stub);
1078 /** get schema from stub.
1080 extern OpenIsisSchema* openIsisNSchema (OpenIsisStub stub);
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
1093 extern int openIsisNSend (
1094 OpenIsisStub stub, OpenIsisRec *rqs,
1095 OpenIsisRspCb *actcb, void *actcld, int rdup
1098 /** get stub's response record.
1099 @param dbid optional db id of embedded result records
1101 extern OpenIsisRec *openIsisNRecv (OpenIsisStub stub, OpenIsisDb **db);
1103 /** clean request, response, session used in last openIsisNSend call.
1105 extern void openIsisNClean (OpenIsisStub stub);
1107 /** util: unwrap embbeded response records.
1109 extern int openIsisNGetResult (OpenIsisStub stub,
1110 int **rowids, OpenIsisRec ***recs, OpenIsisDb **db, int *total);
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
1117 extern void openIsisNNotifyResponse (OpenIsisStub stub, OpenIsisRec **rsp);
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
1124 extern void openIsisNNotifyError (OpenIsisStub stub, int errcode);
1126 /** get communication channel from stub.
1128 extern struct CliChnl* openIsisNGetChannel (OpenIsisStub stub);
1132 extern OpenIsisDb *openIsisNDbByName (OpenIsisStub stub, const char *dbname);
1136 extern OpenIsisDb *openIsisNDbById (int dbid);
1139 /* ************************************************************
1144 open an isis database.
1145 The following options are supported as text-style parameters:
1147 <li>db <name><br>
1148 basename of database. same as param dbname.
1150 <li>dbpath <path><br>
1151 path to database. usefull when opening secondary indexes
1152 or other files whose names are not based on the db basename.
1154 <li>v <level><br>
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.
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
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
1177 extern OpenIsisDb* openIsisCDOpen ( const char *dbname,
1178 OpenIsisRec *dbpar, OpenIsisRec *syspar, OpenIsisFdt *fdt );
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.
1186 extern int openIsisCDOpenv ( const char *dbname, const char **argv, int argc );
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 */
1194 /** check and optionally fix the database.
1196 extern int openIsisCDCheck ( int dbid, int flags );
1202 @param dbid id returned by openIsisOpen
1203 @return 0 on success, some negative errorcode else.
1205 extern int openIsisCDClose ( int dbid );
1208 /* ************************************************************
1209 low level index access
1211 DO NOT USE unless you know what you're doing !!!!!!!!!
1215 typedef struct OpenIsisIdx *OpenIsisIndex;
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
1222 extern OpenIsisIndex openIsisCXOpen ( int dbid, int mode );
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
1229 extern int openIsisCXAdd ( OpenIsisIndex idx,
1230 OpenIsisKey *key, OpenIsisHit *hit );
1232 #define openIsisCXClose( idx ) openIsisCXAdd( idx, 0, 0 )
1235 extern int openisis_threaded;
1238 /* ************************************************************
1239 single session and legacy mode pre 0.9
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.
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.
1257 /** raw version of an ISIS Record. rarely used.
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 */
1268 OpenIsisFld field[1];
1272 extern OpenIsisRaw *openIsisDRaw ( int db, int rowid );
1274 #ifndef OPENISIS_NOPRE09
1278 #define openIsis2Html( str, len ) \
1279 openIsisToHtml ( str, len )
1280 #define openIsisValidUTF8( mem, len, tof ) \
1281 openIsisUtf8Chk ( mem, len, tof )
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 )
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 )
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 )
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 )
1348 #endif /* OPENISIS_NOPRE09 */
1352 #endif /* extern "C" */
1354 #endif /* OPENISIS_H */