/[webpac]/trunk/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

Contents of /trunk/openisis/luti.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (show annotations)
Mon Mar 8 17:49:13 2004 UTC (20 years ago) by dpavlin
File MIME type: text/plain
File size: 12421 byte(s)
including openisis 0.9.0 into webpac tree

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
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