/[webpac]/trunk2/openisis/luti.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk2/openisis/luti.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (hide annotations)
Mon Mar 8 17:49:13 2004 UTC (16 years ago) by dpavlin
Original Path: trunk/openisis/luti.c
File MIME type: text/plain
File size: 12421 byte(s)
including openisis 0.9.0 into webpac tree

1 dpavlin 237 /*
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    
23     /*
24     $Id: luti.c,v 1.48 2003/06/23 14:47:35 kripke Exp $
25     utilities
26     */
27    
28     #include <string.h> /* strlen */
29    
30     #include "openisis.h"
31     #include "luti.h"
32    
33    
34     /* ************************************************************
35     private types
36     */
37    
38     typedef struct {
39     char *name;
40     int id;
41     } LutiLTEnt;
42    
43     typedef struct OpenIsisLT {
44     LutiLTEnt *arr;
45     int siz; /* malloc'ed */
46     int num; /* used */
47     } LutiLTNod;
48    
49     #define LT_NUM 27
50     #define LT_SIZE (LT_NUM * sizeof (LutiLTNod))
51    
52     #define LTIDX(name) ( \
53     ('a' <= *(name) && 'z' >= *(name)) ? *(name) - 'a' : ( \
54     ('A' <= *(name) && 'Z' >= *(name)) ? *(name) - 'A' : 26 \
55     ))
56    
57     #define LT_INCR 2
58    
59     /* ************************************************************
60     private data
61     */
62    
63    
64    
65     /* ************************************************************
66     private functions
67     */
68    
69    
70     /* ************************************************************
71     package data
72     */
73     const char luti_hex[16] = {
74     '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
75     };
76    
77     /* ************************************************************
78     package functions
79     */
80    
81     void log_rec (
82     int level, Rec *rec, const char *msg, const char *delim
83     ) {
84     Field *F;
85     int ch = 2;
86     if (0 > level) {
87     level = -level;
88     ch = 1;
89     }
90     if ((unsigned)level > log_lev) {
91     return;
92     }
93     if (msg && *msg) {
94     sMsg (ch, msg);
95     }
96     sMsg (ch, "%p", rec);
97     if (rec) {
98     if (! delim) {
99     delim = "; ";
100     }
101     sMsg (ch, " #f=%d", (int)rec->len);
102     for (F = rec->field; rec->len > F - rec->field; ++F) {
103     sMsg (ch, delim);
104     sMsg (ch, "%d", (int)F->tag);
105     sMsg (ch, " %.*s", (int)F->len, F->val);
106     }
107     }
108     sMsg (ch, "\n");
109     }
110    
111    
112     int lprint ( void *buf, int i )
113     {
114     char *c = buf;
115     if ( 0 > i ) {
116     *c++ = '-';
117     i = -i;
118     }
119     if ( ! i )
120     *c++ = '0';
121     else {
122     int dig = 0, j=i;
123     char *p;
124     for ( ; j; j /= 10 )
125     dig++;
126     p = c += dig;
127     for ( ; i; i /= 10 )
128     *--p = '0' + i % 10;
129     }
130     *c = 0;
131     return c - (char*)buf;
132     } /* lprint */
133    
134    
135     int a2il ( const char *p, int l, int *res )
136     {
137     const char *s = p;
138     const char *e = p + (0<=l ? l : (int)strlen(p));
139     char op = 0;
140     int ret = 0;
141     while ( p < e && ' ' >= (unsigned char)*p ) /* skip white */
142     p++;
143     if ( p < e )
144     switch ( *p ) {
145     case '-':
146     if ( p+1 == e ) ret = 1; /* so sole '-' is -1 */
147     case '~': /* sole ~ is ~0 */
148     case '+':
149     op = *p++;
150     }
151     if ( p < e && '0' == *p && ++p < e && 'x' == *p ) {
152     while ( ++p < e ) {
153     int v = *p;
154     if ( '0' <= v && v <= '9' )
155     v -= '0';
156     else if ( 'a' <= v && v <= 'f' )
157     v -= 'a'-10;
158     else if ( 'A' <= v && v <= 'F' )
159     v -= 'A'-10;
160     else
161     break;
162     ret = (ret<<4) + v;
163     }
164     } else {
165     while ( p < e && '0' <= *p && *p <= '9' )
166     ret = 10*ret + *p++ - '0';
167     }
168     if (0 != res)
169     switch (op) {
170     case '-': *res = -ret; break;
171     case '~': *res = ~ret; break;
172     default: *res = ret;
173     }
174     return p - s;
175     } /* a2il */
176    
177     int a2i ( const char *p, int l ) {
178     int res;
179     a2il (p, l, &res);
180     return res;
181     }
182    
183     int a2id ( const char *p, int l, int dflt ) {
184     int res;
185     if (0 > l) {
186     l = (int) strlen (p);
187     }
188     if (l != a2il (p, l, &res)) {
189     return dflt;
190     }
191     return res;
192     }
193    
194    
195     int i2a ( char *p, int i )
196     {
197     if ( i ) {
198     int min, dig = 0, j;
199     if ( 0 < i )
200     min = 0;
201     else {
202     min = 1;
203     *p++ = '-';
204     i = -i;
205     }
206     for ( j=i; j; j/=10 )
207     dig++;
208     for ( *(p+=dig)=0; i; i/=10 )
209     *--p = '0' + (i % 10);
210     return min+dig;
211     }
212     *p++ = '0';
213     *p = 0;
214     return 1;
215     } /* i2a */
216    
217    
218     int u2a ( char *p, unsigned u )
219     {
220     if ( u ) {
221     int dig = 0, j;
222     for ( j=u; j; j/=10 )
223     dig++;
224     for ( *(p+=dig)=0; u; u/=10 )
225     *--p = '0' + (u % 10);
226     return dig;
227     }
228     *p++ = '0';
229     *p = 0;
230     return 1;
231     } /* u2a */
232    
233    
234     LutiLT luti_ltnew () {
235     LutiLT res = (LutiLT) mAlloc (LT_SIZE);
236     return res;
237     }
238    
239     void luti_ltdel (LutiLT lt) {
240     LutiLTNod *N;
241     LutiLTEnt *E;
242     if (lt) {
243     for (N = lt + LT_NUM; --N >= lt; ) {
244     if (N->arr) {
245     for (E = N->arr + N->num; --E >= N->arr; ) {
246     if (E->name) {
247     mFree (E->name);
248     }
249     }
250     mFree (N->arr);
251     }
252     }
253     mFree (lt);
254     }
255     }
256    
257     void luti_ltadd (LutiLT lt, const char *name, int id) {
258     if (0 != lt) {
259     LutiLTNod *N;
260     LutiLTEnt *E;
261     int idx;
262     if (!name) {
263     name = "";
264     }
265     idx = LTIDX (name);
266     N = lt + idx;
267     if (N->siz == N->num) {
268     E = mAlloc ( (LT_INCR + N->siz) * sizeof (LutiLTEnt));
269     if (N->siz) {
270     memcpy (E, N->arr, N->siz * sizeof (LutiLTEnt));
271     mFree (N->arr);
272     }
273     N->arr = E;
274     N->siz += LT_INCR;
275     }
276     N->arr[N->num].name = mDup (name, -1);
277     N->arr[N->num].id = id;
278     ++N->num;
279     }
280     }
281    
282     int luti_ltget (LutiLT lt, const char *name) {
283     if (0 != lt) {
284     LutiLTNod *N;
285     LutiLTEnt *E;
286     int idx;
287     if (!name) {
288     name = "";
289     }
290     idx = LTIDX (name);
291     N = lt + idx;
292     if (N->num) {
293     for (E = N->arr + N->num; --E >= N->arr; ) {
294     if (! strcmp (E->name, name)) {
295     return E->id;
296     }
297     }
298     }
299     }
300     return -1;
301     }
302    
303     void luti_ltrmv (LutiLT lt, const char *name) {
304     if (0 != lt) {
305     LutiLTNod *N;
306     LutiLTEnt *E;
307     int idx;
308     if (!name) {
309     name = "";
310     }
311     idx = LTIDX (name);
312     N = lt + idx;
313     if (N->num) {
314     for (E = N->arr + N->num; --E >= N->arr; ) {
315     if (! strcmp (E->name, name)) {
316     int len = N->num - (E - N->arr) - 1;
317     mFree (E->name);
318     if (len) {
319     memmove (E, E + 1, len * sizeof (LutiLTEnt));
320     }
321     --N->num;
322     return;
323     }
324     }
325     }
326     log_msg (LOG_WARN, "luti_ltrmv: no such entry <%s>", name);
327     }
328     }
329    
330     static Rec *_unwrap ( Rec *env, int *pos, int tag, int dbid, int rdonly )
331     {
332     Field *F;
333     Rec *rec = 0;
334     int rlen, np;
335     if (! env ) {
336     return 0;
337     }
338     if (! pos) {
339     np = 0;
340     pos = &np;
341     }
342     F = rGet (env, tag, pos);
343     if (!F) {
344     return 0;
345     }
346     rlen = a2id (F->val, (int)F->len, -1);
347     if (0 > rlen) {
348     sMsg (LOG_ERROR,
349     "luti_unwrap: illegal reclen %d, pos %d, tag %d",
350     rlen, *pos, F->tag);
351     return 0;
352     }
353     ++F;
354     if (env->len < *pos + rlen) {
355     sMsg (LOG_ERROR,
356     "luti_unwrap: illegal reclen %d, pos %d, tag %d, env %d",
357     rlen, *pos, F->tag, env->len);
358     return 0;
359     }
360     if (! rlen && ! rdonly) {
361     OPENISIS_RSPACE (rec, 0, 0);
362     if (0 == rec) {
363     return 0;
364     }
365     }
366     while (0 <= --rlen) {
367     if (! rdonly) {
368     RADD (rec, F->tag, F->val, F->len, !0);
369     if (0 == rec) {
370     return 0;
371     }
372     }
373     ++F;
374     ++(*pos);
375     }
376     if (rdonly) {
377     return (Rec*)1;
378     }
379     rec->dbid = dbid;
380     return rec;
381     }
382    
383     Rec *luti_unwrap ( Rec *env, int *pos, int tag, int dbid)
384     {
385     return _unwrap (env, pos, tag, dbid, 0);
386     }
387    
388     Rec* luti_append (Rec *tgt, Rec *src) {
389     Field *F, *E;
390     if (!src) {
391     return tgt;
392     }
393     E = src->field + src->len;
394     for (F = src->field; tgt && E > F; ++F) {
395     RADD (tgt, F->tag, F->val, F->len, !0);
396     }
397     return tgt;
398     }
399    
400     Rec *luti_wrap (Rec *env, Rec *rec, int tag) {
401     if (!rec) {
402     return env;
403     }
404     env = rAddI (env, tag, rec->len, !0);
405     return luti_append (env, rec);
406     }
407    
408     int luti_ptrincr (
409     void *start, int *num, int incr, int siz, int maxn
410     ) {
411     char **base = (char**)start;
412     char *arr;
413     int oldn = *num;
414     if (0 < maxn && oldn >= maxn) {
415     return -1;
416     }
417     arr = mAlloc ((oldn + incr) * siz);
418     if (!arr) {
419     return -1;
420     }
421     if (oldn) {
422     memcpy (arr, *base, oldn * siz);
423     mFree (*base);
424     }
425     memset (arr + oldn * siz, 0, incr * siz);
426     *num += incr;
427     *base = arr;
428     return oldn;
429     }
430    
431     void luti_free (void **arr, int num) {
432     if (arr) {
433     while (0 <= --num) {
434     if (arr[num]) {
435     mFree (arr[num]);
436     }
437     }
438     mFree (arr);
439     }
440     }
441    
442     int luti_true (const char *str, int len) {
443     if (! str || ! *str) {
444     return -1;
445     }
446     if (0 > len) {
447     len = strlen (str);
448     }
449     if (1 == len) {
450     if ('0' == *str ||
451     'f' == *str ||
452     'F' == *str ||
453     'n' == *str ||
454     'N' == *str
455     ) {
456     return 0;
457     }
458     if ('1' == *str ||
459     'y' == *str ||
460     'Y' == *str ||
461     't' == *str ||
462     'T' == *str
463     ) {
464     return 1;
465     }
466     return -1;
467     }
468     if (! strncmp ("false", str, len) ||
469     ! strncmp ("no", str, len)) {
470     return 0;
471     }
472     if (! strncmp ("true", str, len) ||
473     ! strncmp ("yes", str, len)) {
474     return 1;
475     }
476     return -1;
477     }
478    
479     /* ------------------------------------------------------------------------
480     * unwrap by path
481     */
482    
483     Fdt* luti_fdt_from_rec (Rec *rec) {
484     Db *dbh;
485     if (rec &&
486     0 <= rec->dbid &&
487     (dbh = nDbById (rec->dbid))
488     ) {
489     return dbh->fdt;
490     }
491     return 0;
492     }
493    
494     const char* luti_parse_path (
495     const char *path, const Fdt *fdt, Fd **fd, int *tag, int *occ
496     ) {
497     Fd *_f = 0;
498     int _t = -1;
499     int _o = -1;
500     int num, qsub;
501    
502     if (fd) {
503     *fd = 0;
504     }
505     if (tag) {
506     *tag = -1;
507     }
508     if (occ) {
509     *occ = -1;
510     }
511     if (! path) {
512     return 0;
513     }
514    
515     if ('.' == *path
516     || ('-' == *path && (path[1]<'0' || '9'<path[1]))
517     ) { /* path or option style */
518     ++path;
519     }
520    
521     num = a2il (path, -1, &_t);
522     if (num) {
523     if (fdt) {
524     _f = fById (fdt, _t, 0);
525     }
526     }
527     else {
528     char name[OPENISIS_FD_NAMELEN];
529     if (! fdt) {
530     return 0;
531     }
532     for (num = 0;
533     path[num] && '[' != path[num] && '(' != path[num];
534     ++num)
535     ;
536     if (num > OPENISIS_FD_NAMELEN - 1) {
537     return 0;
538     }
539     strncpy (name, path, num) [num] = 0;
540     _f = fByName ( fdt, name );
541     if (! _f) {
542     return 0;
543     }
544     _t = _f->id;
545     }
546     path += num;
547    
548     if (tag) {
549     *tag = _t;
550     }
551     if (fd) {
552     *fd = _f;
553     }
554    
555     if ('[' != *path && '(' != *path) {
556     return path;
557     }
558     qsub = *path;
559    
560     ++path;
561     num = a2il (path, -1, &_o);
562     if (! num || 0 > _o) {
563     return 0;
564     }
565     path += num;
566     if ((']' != *path && '[' == qsub) || (')' != *path && '(' == qsub)) {
567     return 0;
568     }
569    
570     if (occ) {
571     *occ = _o;
572     }
573     return path + 1;
574     }
575    
576     Rec* luti_getembed ( Rec *env, const char *path, const Fdt *fdt)
577     {
578     Rec *res;
579     int tag, occ, idx, pos;
580     if ( ! env || ! path || ! *path) {
581     return 0;
582     }
583     if (! fdt) {
584     fdt = luti_fdt_from_rec (env);
585     }
586     path = luti_parse_path (path, fdt, 0, &tag, &occ);
587     if (! path) {
588     return 0;
589     }
590     res = 0;
591     idx = pos = 0;
592     while (1) {
593     res = _unwrap (env, &pos, tag, -1, idx < occ);
594     if (! res) {
595     return 0;
596     }
597     if (idx >= occ) {
598     break;
599     }
600     ++idx;
601     }
602     if (*path) {
603     Rec *r2 = luti_getembed (res, path, 0);
604     mFree (res);
605     return r2;
606     }
607     return res;
608     }
609    
610    
611     int lhash ( const char *str, int len )
612     {
613     int h = 0;
614     while ( len-- )
615     h = 31*h + *str++;
616     return 0<=h ? h : -h;
617     }
618    
619    
620     /* ************************************************************
621     public functions
622     */
623    
624     char *toHtml ( const char *str, int len )
625     {
626     int l;
627     char *p, *e, *ret;
628     if ( ! str )
629     return 0;
630     if ( 0 > len )
631     len = strlen(str);
632     l = len + 1;
633     for ( e = (p=(char*)str) + len; p<e; p++ )
634     switch ( *p ) {
635     case '<': case '>': l += 3; break;
636     case '&': l += 4; break;
637     case '"': l += 5; break;
638     /* do not replace ' w/ &apos; -- many clients don't grok it */
639     }
640     ret = mAlloc( l );
641     if ( ! ret )
642     return 0;
643     for ( p=ret; str<e; str++ )
644     switch ( *str ) {
645     case '<': *p='&'; p[1]='l'; p[2]='t'; p[3]=';'; p+=4; break;
646     case '>': *p='&'; p[1]='g'; p[2]='t'; p[3]=';'; p+=4; break;
647     case '&': *p='&'; p[1]='a'; p[2]='m'; p[3]='p'; p[4]=';'; p+=5; break;
648     case '"': *p='&';p[1]='q';p[2]='u';p[3]='o';p[4]='t';p[5]=';';p+=6;break;
649     default: *p++ = *str;
650     }
651     *p = 0;
652     return ret;
653     } /* toHtml */
654    
655    
656     int utf8Chk ( void *mem, int len, int *tof )
657     {
658     unsigned char *c = (unsigned char *)mem;
659     int f = 0; /* expected followers */
660     int l = len;
661     if ( tof )
662     f = *tof;
663     for ( ; l--; c++ ) {
664     unsigned char u = *c;
665     int tofollow = u < 128 ? 0 : u < 192 ? -1 : u < 224 ? 1 : 2;
666     if ( f ) {
667     if ( 0 > tofollow ) { f--; continue; }
668     break;
669     }
670     if ( 0 <= tofollow ) { f = tofollow; continue; }
671     goto croak;
672     }
673     if ( tof )
674     *tof = f;
675     if ( ! f )
676     return 0;
677     if ( 0 > l && tof ) /* exhausted buf, want follower */
678     return 0;
679     sMsg( LOG_ERROR, "expected follower at %d got %x", len-l-1, (int)*c );
680     return len-l;
681     croak:
682     sMsg( LOG_ERROR, "expected no follower at %d got %x", len-l-1, (int)*c );
683     return len-l;
684     } /* utf8Chk */

  ViewVC Help
Powered by ViewVC 1.1.26