1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <vdb/extern.h>
28
29 #include "schema-priv.h"
30 #include "schema-parse.h"
31 #include "schema-expr.h"
32
33 #include <klib/symbol.h>
34 #include <klib/symtab.h>
35 #include <klib/rc.h>
36 #include <sysalloc.h>
37 #include <bitstr.h>
38 #include <atomic32.h>
39
40 #include <stdlib.h>
41 #include <string.h>
42 #include <assert.h>
43
44
45 /*--------------------------------------------------------------------------
46 * VSchema
47 */
48
49
50 /* CacheIntrinsicTypeId
51 * for id-caching
52 *
53 * reads id atomically from "cache" and returns if non-zero
54 *
55 * otherwise retrieves type id by name lookup, and sets
56 * value atomically in "cache" before returning.
57 */
VSchemaCacheIntrinsicTypeId(const VSchema * self,atomic32_t * cache,const char * type_name)58 uint32_t VSchemaCacheIntrinsicTypeId ( const VSchema *self,
59 atomic32_t *cache, const char *type_name )
60 {
61 uint32_t id;
62
63 assert ( self != NULL );
64 assert ( cache != NULL );
65 assert ( type_name != NULL && type_name [ 0 ] != 0 );
66
67 /* retrieve cached value */
68 id = atomic32_read ( cache );
69 if ( id == 0 )
70 {
71 String name;
72 uint32_t prev;
73 const KSymbol *sym;
74 const SDatatype *dt;
75
76 /* find intrinsic schema */
77 const VSchema *intrinsic = self;
78 while ( intrinsic -> dad != NULL )
79 intrinsic = intrinsic -> dad;
80
81 /* find datatype U32 */
82 StringInitCString ( & name, type_name );
83 sym = ( const KSymbol* )
84 BSTreeFind ( & intrinsic -> scope, & name, KSymbolCmp );
85 assert ( sym != NULL );
86 dt = sym -> u . obj;
87
88 /* this SHOULD be idempotent */
89 prev = atomic32_test_and_set ( cache, ( int ) dt -> id, id );
90 assert ( prev == id || prev == dt -> id );
91
92 id = dt -> id;
93 }
94
95 return id;
96 }
97
98
99 /*--------------------------------------------------------------------------
100 * constant numeric expressions
101 *
102 * built-in typecasting allows for the chain
103 * bool => uint => int => float
104 *
105 * built-in size promotion is automatic from 8 => 16 => 32 => 64 bits
106 *
107 * constant size-demotion is allowed due to knowledge of constant value
108 *
109 * explicit casts may reverse type promotion rules
110 */
111
112
113 /* 64 bit interchange union
114 */
115 typedef union nx nx;
116 union nx
117 {
118 uint64_t u64;
119 int64_t i64;
120 double f64;
121 };
122
123
124 /* readers
125 * access data in 8, 16, 32 or 64 bit form
126 * return data in 64 bit form
127 * advance data pointer
128 */
129 static
read_bool(nx * data,const void * p)130 const void *read_bool ( nx *data, const void *p )
131 {
132 const bool *src = p;
133 data -> u64 = src [ 0 ];
134 return src + 1;
135 }
136
137 static
read_U8(nx * data,const void * p)138 const void *read_U8 ( nx *data, const void *p )
139 {
140 const uint8_t *src = p;
141 data -> u64 = src [ 0 ];
142 return src + 1;
143 }
144
145 static
read_U16(nx * data,const void * p)146 const void *read_U16 ( nx *data, const void *p )
147 {
148 const uint16_t *src = p;
149 data -> u64 = src [ 0 ];
150 return src + 1;
151 }
152
153 static
read_U32(nx * data,const void * p)154 const void *read_U32 ( nx *data, const void *p )
155 {
156 const uint32_t *src = p;
157 data -> u64 = src [ 0 ];
158 return src + 1;
159 }
160
161 static
read_U64(nx * data,const void * p)162 const void *read_U64 ( nx *data, const void *p )
163 {
164 const uint64_t *src = p;
165 data -> u64 = src [ 0 ];
166 return src + 1;
167 }
168
169 static
read_I8(nx * data,const void * p)170 const void *read_I8 ( nx *data, const void *p )
171 {
172 const int8_t *src = p;
173 data -> i64 = src [ 0 ];
174 return src + 1;
175 }
176
177 static
read_I16(nx * data,const void * p)178 const void *read_I16 ( nx *data, const void *p )
179 {
180 const int16_t *src = p;
181 data -> i64 = src [ 0 ];
182 return src + 1;
183 }
184
185 static
read_I32(nx * data,const void * p)186 const void *read_I32 ( nx *data, const void *p )
187 {
188 const int32_t *src = p;
189 data -> i64 = src [ 0 ];
190 return src + 1;
191 }
192
193 static
read_I64(nx * data,const void * p)194 const void *read_I64 ( nx *data, const void *p )
195 {
196 const int64_t *src = p;
197 data -> i64 = src [ 0 ];
198 return src + 1;
199 }
200
201 static
read_F32(nx * data,const void * p)202 const void *read_F32 ( nx *data, const void *p )
203 {
204 const float *src = p;
205 data -> f64 = src [ 0 ];
206 return src + 1;
207 }
208
209 static
read_F64(nx * data,const void * p)210 const void *read_F64 ( nx *data, const void *p )
211 {
212 const double *src = p;
213 data -> f64 = src [ 0 ];
214 return src + 1;
215 }
216
217 /* writers
218 * write data in 8, 16, 32, or 64 bit form
219 * receive data in 64 bit form
220 * advance pointers
221 */
222 static
write_bool(void * p,const nx * data)223 void *write_bool ( void *p, const nx *data )
224 {
225 bool *dst = p;
226 dst [ 0 ] = data -> u64 ? true : false;
227 return dst + 1;
228 }
229
230 static
write_U8(void * p,const nx * data)231 void *write_U8 ( void *p, const nx *data )
232 {
233 uint8_t *dst = p;
234 dst [ 0 ] = ( uint8_t ) data -> u64;
235 if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
236 return NULL;
237 return dst + 1;
238 }
239
240 static
write_U16(void * p,const nx * data)241 void *write_U16 ( void *p, const nx *data )
242 {
243 uint16_t *dst = p;
244 dst [ 0 ] = ( uint16_t ) data -> u64;
245 if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
246 return NULL;
247 return dst + 1;
248 }
249
250 static
write_U32(void * p,const nx * data)251 void *write_U32 ( void *p, const nx *data )
252 {
253 uint32_t *dst = p;
254 dst [ 0 ] = ( uint32_t ) data -> u64;
255 if ( ( uint64_t ) dst [ 0 ] != data -> u64 )
256 return NULL;
257 return dst + 1;
258 }
259
260 static
write_U64(void * p,const nx * data)261 void *write_U64 ( void *p, const nx *data )
262 {
263 uint64_t *dst = p;
264 dst [ 0 ] = data -> u64;
265 return dst + 1;
266 }
267
268 static
write_I8(void * p,const nx * data)269 void *write_I8 ( void *p, const nx *data )
270 {
271 int8_t *dst = p;
272 dst [ 0 ] = ( int8_t ) data -> i64;
273 if ( ( int64_t ) dst [ 0 ] != data -> i64 )
274 return NULL;
275 return dst + 1;
276 }
277
278 static
write_I16(void * p,const nx * data)279 void *write_I16 ( void *p, const nx *data )
280 {
281 int16_t *dst = p;
282 dst [ 0 ] = ( int16_t ) data -> i64;
283 if ( ( int64_t ) dst [ 0 ] != data -> i64 )
284 return NULL;
285 return dst + 1;
286 }
287
288 static
write_I32(void * p,const nx * data)289 void *write_I32 ( void *p, const nx *data )
290 {
291 int32_t *dst = p;
292 dst [ 0 ] = ( int32_t ) data -> i64;
293 if ( ( int64_t ) dst [ 0 ] != data -> i64 )
294 return NULL;
295 return dst + 1;
296 }
297
298 static
write_I64(void * p,const nx * data)299 void *write_I64 ( void *p, const nx *data )
300 {
301 int64_t *dst = p;
302 dst [ 0 ] = data -> i64;
303 return dst + 1;
304 }
305
306 static
write_F32(void * p,const nx * data)307 void *write_F32 ( void *p, const nx *data )
308 {
309 double e;
310 float *dst = p;
311 dst [ 0 ] = ( float ) data -> f64;
312 e = ( double ) dst [ 0 ] - data -> f64;
313 if ( -1.0 < e || e > 1.0 )
314 return NULL;
315 return dst + 1;
316 }
317
318 static
write_F64(void * p,const nx * data)319 void *write_F64 ( void *p, const nx *data )
320 {
321 double *dst = p;
322 dst [ 0 ] = data -> f64;
323 return dst + 1;
324 }
325
326
327 /* converters
328 * convert from one data type to another
329 */
330 static
null_cvt(nx * data)331 nx *null_cvt ( nx *data )
332 {
333 return data;
334 }
335
336 static
uint_int(nx * data)337 nx *uint_int ( nx *data )
338 {
339 if ( data -> i64 < 0 )
340 return NULL;
341 return data;
342 }
343
344 static
uint_float(nx * data)345 nx *uint_float ( nx *data )
346 {
347 if ( data -> i64 < 0 )
348 return NULL;
349 data -> f64 = (double)data -> i64;
350 return data;
351 }
352
353 static
int_float(nx * data)354 nx *int_float ( nx *data )
355 {
356 data -> f64 = (double)data -> i64;
357 return data;
358 }
359
360 static
float_int(nx * data)361 nx *float_int ( nx *data )
362 {
363 data -> i64 = ( int64_t ) data -> f64;
364 return data;
365 }
366
367 static
float_uint(nx * data)368 nx *float_uint ( nx *data )
369 {
370 data -> i64 = ( int64_t ) data -> f64;
371 if ( data -> i64 < 0 )
372 return NULL;
373 return data;
374 }
375
376 static
int_uint(nx * data)377 nx *int_uint ( nx *data )
378 {
379 if ( data -> i64 < 0 )
380 return NULL;
381 return data;
382 }
383
384 /* eval-numeric-expr
385 * tries to evaluate a constant numeric expression against type
386 * returns non-zero error code if failed
387 */
388 #if SLVL >= 1
eval_numeric_expr(const VSchema * self,const VTypedecl * td,const SConstExpr * expr,SConstExpr ** xp,bool force)389 LIB_EXPORT rc_t CC eval_numeric_expr ( const VSchema *self, const VTypedecl *td,
390 const SConstExpr *expr, SConstExpr **xp, bool force )
391 {
392 SConstExpr *x;
393 uint32_t sbits, sdim;
394 uint32_t i, dbits, ddim;
395
396 void *dst;
397 const void *src;
398
399 const void* ( * reader ) ( nx*, const void* );
400 void* ( * writer ) ( void*, const nx* );
401 nx* ( * cvt ) ( nx* );
402
403 /* source and destination types of constant vector */
404 const SDatatype *sdt = VSchemaFindTypeid ( self, expr -> td . type_id );
405 const SDatatype *ddt = VSchemaFindTypeid ( self, td -> type_id );
406 if ( sdt == NULL || ddt == NULL )
407 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcNotFound );
408
409 /* size of source and destination types */
410 sbits = sdt -> size;
411 dbits = ddt -> size;
412
413 /* regardless of how derived the specified types may be,
414 get their dimensions in terms of intrinsic types */
415 sdim = SDatatypeIntrinsicDim ( sdt );
416 ddim = SDatatypeIntrinsicDim ( ddt );
417
418 /* convert stated sizes to intrinsic element size */
419 assert ( sdim != 0 && ( sbits % sdim ) == 0 );
420 sbits /= sdim;
421 assert ( ddim != 0 && ( dbits % ddim ) == 0 );
422 dbits /= ddim;
423
424 /* test for cast compatibility */
425 if ( ! force ) switch ( ddt -> domain )
426 {
427 case ddBool:
428 /* only bool casts to bool */
429 if ( sdt -> domain != ddBool )
430 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
431 break;
432 case ddUint: case ddInt: case ddFloat:
433 if ( sdt -> domain > ddt -> domain )
434 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
435 break;
436 default:
437 return SILENT_RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
438 }
439
440 /* reset dimensions to account for explicit values */
441 sdim *= expr -> td . dim;
442 i = ddim * td -> dim;
443
444 /* destination dim must divide source dim evenly */
445 if ( i == 0 || sdim < i || ( sdim % i ) != 0 )
446 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
447
448 /* determine reader */
449 switch ( sdt -> domain )
450 {
451 case ddBool:
452 reader = read_bool; break;
453 case ddUint:
454 switch ( sbits )
455 {
456 case 8: reader = read_U8; break;
457 case 16: reader = read_U16; break;
458 case 32: reader = read_U32; break;
459 case 64: reader = read_U64; break;
460 default:
461 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
462 }
463 break;
464 case ddInt:
465 switch ( sbits )
466 {
467 case 8: reader = read_I8; break;
468 case 16: reader = read_I16; break;
469 case 32: reader = read_I32; break;
470 case 64: reader = read_I64; break;
471 default:
472 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
473 }
474 break;
475 case ddFloat:
476 switch ( sbits )
477 {
478 case 32: reader = read_F32; break;
479 case 64: reader = read_F64; break;
480 default:
481 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
482 }
483 break;
484 default:
485 /* here to quiet compiler complaints */
486 reader = NULL;
487 }
488
489 /* determine writer */
490 switch ( ddt -> domain )
491 {
492 case ddBool:
493 writer = write_bool; break;
494 case ddUint:
495 switch ( dbits )
496 {
497 case 8: writer = write_U8; break;
498 case 16: writer = write_U16; break;
499 case 32: writer = write_U32; break;
500 case 64: writer = write_U64; break;
501 default:
502 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
503 }
504 break;
505 case ddInt:
506 switch ( dbits )
507 {
508 case 8: writer = write_I8; break;
509 case 16: writer = write_I16; break;
510 case 32: writer = write_I32; break;
511 case 64: writer = write_I64; break;
512 default:
513 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
514 }
515 break;
516 case ddFloat:
517 switch ( dbits )
518 {
519 case 32: writer = write_F32; break;
520 case 64: writer = write_F64; break;
521 default:
522 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
523 }
524 break;
525 default:
526 writer = NULL;
527 }
528
529 /* determine converter */
530 if ( sdt -> domain == ddt -> domain )
531 cvt = null_cvt;
532 else switch ( ddt -> domain )
533 {
534 case ddBool:
535 case ddUint:
536 switch ( sdt -> domain )
537 {
538 case ddInt:
539 cvt = int_uint; break;
540 case ddFloat:
541 cvt = float_uint; break;
542 default:
543 cvt = null_cvt;
544 }
545 break;
546 case ddInt:
547 switch ( sdt -> domain )
548 {
549 case ddFloat:
550 cvt = float_int; break;
551 default:
552 cvt = uint_int; break;
553 }
554 break;
555 case ddFloat:
556 switch ( sdt -> domain )
557 {
558 case ddInt:
559 cvt = int_float; break;
560 default:
561 cvt = uint_float; break;
562 }
563 break;
564 default:
565 cvt = null_cvt;
566 }
567
568 /* create output object */
569 {
570 unsigned int alloc_size;
571
572 alloc_size=(((size_t)dbits * sdim + 7) >> 3);
573 if(alloc_size < sizeof(x->u)){ /** don't go below size of union ***/
574 alloc_size=sizeof(*x);
575 } else { /** overallocate here ***/
576 alloc_size+=sizeof(*x)-sizeof(x->u);
577 }
578 alloc_size = (alloc_size+3)&~3; /** align to 4 bytes **/
579 x = malloc ( alloc_size );
580 if ( x == NULL )
581 return RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
582 memset(x,0,alloc_size);
583 }
584
585 /* copy, and perform type conversion */
586 src = & expr -> u;
587 dst = & x -> u;
588 for ( i = 0; i < sdim; ++ i )
589 {
590 nx data;
591 const nx *dp;
592
593 /* read element */
594 src = ( * reader ) ( & data, src );
595
596 /* type-promote */
597 dp = ( * cvt ) ( & data );
598 if ( dp == NULL )
599 {
600 free ( x );
601 return RC ( rcVDB, rcExpression, rcEvaluating, rcConstraint, rcViolated );
602 }
603
604 /* write element */
605 dst = ( * writer ) ( dst, dp );
606 if ( dst == NULL )
607 {
608 free ( x );
609 return RC ( rcVDB, rcExpression, rcEvaluating, rcConstraint, rcViolated );
610 }
611 }
612
613 /* it is done */
614 x -> dad . var = eConstExpr;
615 atomic32_set ( & x -> dad . refcount, 1 );
616 x -> td . type_id = td -> type_id;
617 x -> td . dim = sdim / ddim;
618 * xp = x;
619 return 0;
620 }
621 #endif
622
623
624 /*--------------------------------------------------------------------------
625 * constant textual expressions
626 *
627 * built-in typecasting allows for the chain
628 * ascii => unicode
629 *
630 * built-in size promotion is automatic from 8 => 16 => 32 bits
631 *
632 * constant size-demotion is allowed due to knowledge of constant value
633 *
634 * explicit casts may reverse type promotion rules
635 */
636
637
638 static
read_ascii(uint32_t * ch,const void * p,const void * end)639 const void *read_ascii ( uint32_t *ch, const void *p, const void *end )
640 {
641 const char *src = p;
642 if ( src [ 0 ] < 0 )
643 return NULL;
644 * ch = src [ 0 ];
645 return src + 1;
646 }
647
648 static
read_utf8(uint32_t * ch,const void * p,const void * end)649 const void *read_utf8 ( uint32_t *ch, const void *p, const void *end )
650 {
651 const char *src = p;
652 int len = utf8_utf32 ( ch, src, end );
653 if ( len <= 0 )
654 return NULL;
655 return src + len;
656 }
657
658 static
read_utf16(uint32_t * ch,const void * p,const void * end)659 const void *read_utf16 ( uint32_t *ch, const void *p, const void *end )
660 {
661 const uint16_t *src = p;
662 * ch = src [ 0 ];
663 return src + 1;
664 }
665
666 static
read_utf32(uint32_t * ch,const void * p,const void * end)667 const void *read_utf32 ( uint32_t *ch, const void *p, const void *end )
668 {
669 const uint32_t *src = p;
670 * ch = src [ 0 ];
671 return src + 1;
672 }
673
674 static
write_ascii(void * p,void * end,uint32_t ch)675 void *write_ascii ( void *p, void *end, uint32_t ch )
676 {
677 char *dst = p;
678 if ( ch >= 128 )
679 ch = '?';
680 dst [ 0 ] = ( char ) ch;
681 return dst + 1;
682 }
683
684 static
write_utf8(void * p,void * end,uint32_t ch)685 void *write_utf8 ( void *p, void *end, uint32_t ch )
686 {
687 char *dst = p;
688 int len = utf32_utf8 ( dst, end, ch );
689 if ( len <= 0 )
690 return NULL;
691 return dst + len;
692 }
693
694 static
write_utf16(void * p,void * end,uint32_t ch)695 void *write_utf16 ( void *p, void *end, uint32_t ch )
696 {
697 uint16_t *dst = p;
698 if ( ch > 0x10000 )
699 ch = '?';
700 dst [ 0 ] = ( uint16_t ) ch;
701 return dst + 1;
702 }
703
704 static
write_utf32(void * p,void * end,uint32_t ch)705 void *write_utf32 ( void *p, void *end, uint32_t ch )
706 {
707 uint32_t *dst = p;
708 dst [ 0 ] = ch;
709 return dst + 1;
710 }
711
712 #if SLVL >= 1
eval_text_expr(const VSchema * self,const VTypedecl * td,const SConstExpr * expr,SConstExpr ** xp,bool force)713 LIB_EXPORT rc_t CC eval_text_expr ( const VSchema *self, const VTypedecl *td,
714 const SConstExpr *expr, SConstExpr **xp, bool force )
715 {
716 size_t size;
717 uint32_t len;
718 SConstExpr *x;
719 uint32_t sbits, sdim;
720 uint32_t i, dbits, ddim;
721
722 void *dst, *dend;
723 const void *src, *send;
724 void* ( * writer ) ( void*, void*, uint32_t );
725 const void* ( * reader ) ( uint32_t*, const void*, const void* );
726
727 /* source and destination types of constant vector */
728 const SDatatype *sdt = VSchemaFindTypeid ( self, expr -> td . type_id );
729 const SDatatype *ddt = VSchemaFindTypeid ( self, td -> type_id );
730 if ( sdt == NULL || ddt == NULL )
731 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcNotFound );
732
733 /* size of source and destination types */
734 sbits = sdt -> size;
735 dbits = ddt -> size;
736
737 /* regardless of how derived the specified types may be,
738 get their dimensions in terms of intrinsic types */
739 sdim = SDatatypeIntrinsicDim ( sdt );
740 ddim = SDatatypeIntrinsicDim ( ddt );
741
742 /* convert stated sizes to intrinsic element size */
743 assert ( sdim != 0 && ( sbits % sdim ) == 0 );
744 sbits /= sdim;
745 assert ( ddim != 0 && ( dbits % ddim ) == 0 );
746 dbits /= ddim;
747
748 /* test for cast compatibility */
749 if ( ! force ) switch ( ddt -> domain )
750 {
751 case ddAscii:
752 /* only ascii casts to ascii */
753 if ( sdt -> domain != ddAscii )
754 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
755 break;
756 case ddUnicode:
757 if ( sdt -> domain < ddAscii || sdt -> domain > ddt -> domain )
758 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
759 break;
760 default:
761 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
762 }
763
764 /* restore source dimension */
765 sdim *= expr -> td . dim;
766
767 /* determine reader and length */
768 len = sdim;
769 switch ( sdt -> domain )
770 {
771 case ddAscii:
772 reader = read_ascii; break;
773 default:
774 switch ( sbits )
775 {
776 case 8:
777 reader = read_utf8;
778 len = string_len ( expr -> u . utf8, sdim );
779 break;
780 case 16:
781 reader = read_utf16;
782 break;
783 case 32:
784 reader = read_utf32;
785 break;
786 default:
787 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
788 }
789 }
790
791 /* determine writer and size */
792 ddim = len;
793 switch ( ddt -> domain )
794 {
795 case ddAscii:
796 writer = write_ascii;
797 size = len;
798 break;
799 default:
800 switch ( sbits )
801 {
802 case 8:
803 writer = write_utf8;
804 switch ( dbits )
805 {
806 case 16:
807 utf16_cvt_string_len ( expr -> u . utf16, len << 1, & size );
808 break;
809 case 32:
810 utf32_cvt_string_len ( expr -> u . utf32, len << 2, & size );
811 break;
812 default:
813 size = sdim;
814 }
815 ddim = ( uint32_t ) size;
816 break;
817 case 16:
818 writer = write_utf16;
819 size = len << 1;
820 break;
821 case 32:
822 writer = write_utf32;
823 size = len << 2;
824 break;
825 default:
826 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnexpected );
827 }
828 }
829
830 /* create output object */
831 {
832 unsigned int alloc_size;
833
834 alloc_size=size;
835 if(alloc_size < sizeof(x->u)){ /** don't go below size of union ***/
836 alloc_size=sizeof(*x);
837 } else { /** overallocate here ***/
838 alloc_size+=sizeof(*x)-sizeof(x->u);
839 }
840 alloc_size = (alloc_size+3)&~3; /** align to 4 bytes **/
841 x = malloc ( alloc_size );
842 if ( x == NULL )
843 return RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
844 memset(x,0,alloc_size);
845 }
846
847
848 /* copy, and perform type conversion */
849 src = expr -> u . utf8;
850 send = & expr -> u . utf8 [ sdim ];
851 dst = x -> u . utf8;
852 dend = & x -> u . utf8 [ size ];
853 for ( i = 0; i < len; ++ i )
854 {
855 uint32_t ch;
856
857 /* read character */
858 src = ( * reader ) ( & ch, src, send );
859 if ( src == NULL )
860 {
861 free ( x );
862 return RC ( rcVDB, rcExpression, rcEvaluating, rcData, rcCorrupt );
863 }
864
865 /* write character */
866 dst = ( * writer ) ( dst, dend, ch );
867 if ( dst == NULL )
868 {
869 free ( x );
870 return RC ( rcVDB, rcExpression, rcEvaluating, rcData, rcCorrupt );
871 }
872 }
873
874 /* it is done */
875 x -> dad . var = eConstExpr;
876 atomic32_set ( & x -> dad . refcount, 1 );
877 x -> td . type_id = td -> type_id;
878 x -> td . dim = ddim;
879 * xp = x;
880 return 0;
881 }
882 #endif
883
884
885 /*--------------------------------------------------------------------------
886 * SConstExpr
887 */
888
889
890 /* Resolve
891 * return constant expression as a vector of indicated type
892 */
893 rc_t SConstExprResolveAsBool ( const SConstExpr *self,
894 const VSchema *schema, bool *b, uint32_t capacity );
895 rc_t SConstExprResolveAsI8 ( const SConstExpr *self,
896 const VSchema *schema, int8_t *i8, uint32_t capacity );
897 rc_t SConstExprResolveAsI16 ( const SConstExpr *self,
898 const VSchema *schema, int16_t *i16, uint32_t capacity );
899 rc_t SConstExprResolveAsI32 ( const SConstExpr *self,
900 const VSchema *schema, int32_t *i32, uint32_t capacity );
901 rc_t SConstExprResolveAsI64 ( const SConstExpr *self,
902 const VSchema *schema, int64_t *i64, uint32_t capacity );
903 rc_t SConstExprResolveAsU8 ( const SConstExpr *self,
904 const VSchema *schema, uint8_t *u8, uint32_t capacity );
905 rc_t SConstExprResolveAsU16 ( const SConstExpr *self,
906 const VSchema *schema, uint16_t *u16, uint32_t capacity );
907
SConstExprResolveAsU32(const SConstExpr * self,const VSchema * schema,uint32_t * u32,uint32_t capacity,Vector * cx_bind)908 rc_t SConstExprResolveAsU32 ( const SConstExpr *self,
909 const VSchema *schema, uint32_t *u32, uint32_t capacity, Vector *cx_bind )
910 {
911 if ( capacity != 1 )
912 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUnsupported );
913 return eval_uint_expr ( schema, ( const SExpression* ) self, u32, cx_bind );
914 }
915
916 rc_t SConstExprResolveAsU64 ( const SConstExpr *self,
917 const VSchema *schema, uint32_t *u64, uint32_t capacity );
918 rc_t SConstExprResolveAsF32 ( const SConstExpr *self,
919 const VSchema *schema, float *f32, uint32_t capacity );
920 rc_t SConstExprResolveAsF64 ( const SConstExpr *self,
921 const VSchema *schema, double *f64, uint32_t capacity );
922 rc_t SConstExprResolveAsAscii ( const SConstExpr *self,
923 const VSchema *schema, char *ascii, size_t capacity );
924 rc_t SConstExprResolveAsUTF8 ( const SConstExpr *self,
925 const VSchema *schema, char *utf8, size_t bytes );
926 rc_t SConstExprResolveAsUTF16 ( const SConstExpr *self,
927 const VSchema *schema, uint16_t *utf16, uint32_t capacity );
928 rc_t SConstExprResolveAsUTF32 ( const SConstExpr *self,
929 const VSchema *schema, uint32_t *utf32, uint32_t capacity );
930
931
932 /*--------------------------------------------------------------------------
933 * STypeExpr
934 */
935
936 /* Resolve
937 * resolve type expression to either a VTypedecl or VFormatdecl
938 */
STypeExprResolveAsFormatdecl(const STypeExpr * self,const VSchema * schema,VFormatdecl * fd,Vector * cx_bind)939 rc_t STypeExprResolveAsFormatdecl ( const STypeExpr *self,
940 const VSchema *schema, VFormatdecl *fd, Vector *cx_bind )
941 {
942 rc_t rc;
943 uint32_t dim;
944
945 /* if self is resolved, then the format, type
946 and dimension are completely resolved */
947 if ( self -> resolved )
948 {
949 * fd = self -> fd;
950 return 0;
951 }
952
953 #if SLVL < 3
954 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
955 #else
956 /* the format is always completely resolved,
957 this leaves type and/or dimension */
958
959 if ( self -> id != NULL )
960 {
961 /* the type needs to be resolved */
962 const STypeExpr *type = ( const STypeExpr* ) VectorGet ( cx_bind, self -> id -> type_id );
963 if ( type == NULL )
964 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUndefined );
965 if ( type -> dad . var != eTypeExpr )
966 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
967 rc = STypeExprResolveAsFormatdecl ( type, schema, fd, cx_bind );
968 if ( rc != 0 )
969 return rc;
970
971 /* at this point, "fd" has some format - which we'll clobber,
972 a type and dim from the indirect type just resolved */
973 }
974 else
975 {
976 /* take known type and default dimension */
977 fd -> td . type_id = self -> fd . td . type_id;
978 fd -> td . dim = 1;
979 }
980
981 /* always take our format */
982 fd -> fmt = self -> fd . fmt;
983
984 /* test for unresolved dimension */
985 dim = self -> fd . td . dim;
986 if ( dim == 0 && self -> dim != NULL )
987 {
988 const SExpression *dx = self -> dim;
989 while ( dx != NULL )
990 {
991 const SIndirectConst *ic;
992
993 if ( dx -> var == eConstExpr )
994 {
995 rc = SConstExprResolveAsU32 ( ( const SConstExpr* ) dx, schema, & dim, 1, cx_bind );
996 if ( rc != 0 )
997 return rc;
998 break;
999 }
1000
1001 if ( dx -> var != eIndirectExpr )
1002 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1003
1004 ic = ( ( const SSymExpr* ) dx ) -> _sym -> u . obj;
1005 assert ( ic != NULL );
1006
1007 dx = ( const SExpression* ) VectorGet ( cx_bind, ic -> expr_id );
1008 }
1009
1010 /* must have non-zero dim */
1011 if ( dim == 0 )
1012 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcUndefined );
1013 }
1014
1015 /* factor in our dimension */
1016 fd -> td . dim *= dim;
1017 return 0;
1018 #endif
1019 }
1020
STypeExprResolveAsTypedecl(const STypeExpr * self,const VSchema * schema,VTypedecl * td,Vector * cx_bind)1021 rc_t STypeExprResolveAsTypedecl ( const STypeExpr *self,
1022 const VSchema *schema, VTypedecl *td, Vector *cx_bind )
1023 {
1024 VFormatdecl fd;
1025 rc_t rc = STypeExprResolveAsFormatdecl ( self, schema, & fd, cx_bind );
1026 if ( rc == 0 )
1027 {
1028 if ( fd . fmt != 0 )
1029 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1030 * td = fd . td;
1031 }
1032 return rc;
1033 }
1034
1035
1036 /*--------------------------------------------------------------------------
1037 * general constant expression evaluation
1038 */
1039 #if SLVL >= 1
1040
1041 /* eval-type-expr
1042 * should be able to boil things down to defined type vector
1043 */
1044 static
eval_type_expr(const VSchema * self,const VTypedecl * td,const STypeExpr * expr,SExpression ** xp)1045 rc_t eval_type_expr ( const VSchema *self, const VTypedecl *td,
1046 const STypeExpr *expr, SExpression **xp )
1047 {
1048 PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle type expression" ));
1049 return -1;
1050 }
1051
1052 /* eval-indirect-expr
1053 */
1054 static
eval_indirect_expr(const VSchema * self,const VTypedecl * td,const SSymExpr * expr,SExpression ** xp,Vector * cx_bind)1055 rc_t eval_indirect_expr ( const VSchema *self, const VTypedecl *td,
1056 const SSymExpr *expr, SExpression **xp, Vector *cx_bind )
1057 {
1058 const SIndirectConst *ic = expr -> _sym -> u . obj;
1059
1060 /* if the expression is there */
1061 if ( ic -> expr_id != 0 )
1062 {
1063 const SExpression *ic_expr = ( const SExpression* ) VectorGet ( cx_bind, ic -> expr_id );
1064 if ( ic_expr != NULL )
1065 return eval_const_expr ( self, td, ic_expr, xp, cx_bind );
1066 }
1067
1068 /* just return self */
1069 * xp = & ( ( SSymExpr* ) expr ) -> dad;
1070 atomic32_inc ( & ( ( SSymExpr* ) expr ) -> dad . refcount );
1071 return 0;
1072 }
1073
1074
1075 /* eval-const-cast-expr
1076 */
1077 static
eval_const_cast_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp)1078 rc_t eval_const_cast_expr ( const VSchema *self, const VTypedecl *td,
1079 const SExpression *expr, SExpression **xp )
1080 {
1081 PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle const cast expression" ));
1082 return -1;
1083 }
1084
1085
1086 /* eval-func-param-expr
1087 */
1088 static
eval_func_param_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp)1089 rc_t eval_func_param_expr ( const VSchema *self, const VTypedecl *td,
1090 const SExpression *expr, SExpression **xp )
1091 {
1092 PLOGMSG( klogWarn, ( klogWarn, "TDB: $(msg)", "msg=handle function expression" ));
1093 return -1;
1094 }
1095
1096 struct eval_vector_param_expr_pb
1097 {
1098 rc_t rc;
1099 const VSchema *self;
1100 const VTypedecl *td;
1101 Vector *cx_bind;
1102 Vector v;
1103 };
1104
1105 static
vector_free(void * item,void * data)1106 void CC vector_free ( void *item, void *data )
1107 {
1108 free ( item );
1109 }
1110
1111 static
do_eval_vector_param_expr(void * item,void * data)1112 bool CC do_eval_vector_param_expr ( void *item, void *data )
1113 {
1114 struct eval_vector_param_expr_pb *pb = data;
1115 SExpression *rslt = NULL;
1116
1117 pb -> rc = eval_const_expr ( pb -> self, pb -> td, item, & rslt, pb -> cx_bind );
1118 if ( pb -> rc != 0 )
1119 return true;
1120
1121 switch ( rslt -> var )
1122 {
1123 case eConstExpr:
1124 VectorAppend ( & pb -> v, NULL, rslt );
1125 break;
1126 case eVectorExpr:
1127 free ( rslt );
1128 break;
1129 default:
1130 free ( rslt );
1131 pb -> rc = RC ( rcVDB, rcExpression, rcEvaluating, rcExpression, rcUnexpected );
1132 return true;
1133 }
1134
1135 return false;
1136 }
1137
1138 /* eval-vector-param-expr
1139 */
1140 static
eval_vector_param_expr(const VSchema * self,const VTypedecl * td,const SVectExpr * expr,SExpression ** xp,Vector * cx_bind)1141 rc_t eval_vector_param_expr ( const VSchema *self, const VTypedecl *td,
1142 const SVectExpr *expr, SExpression **xp, Vector *cx_bind )
1143 {
1144 struct eval_vector_param_expr_pb pb;
1145
1146 *xp = NULL;
1147
1148 pb . rc = 0;
1149 pb . self = self;
1150 pb . td = td;
1151 pb . cx_bind = cx_bind;
1152 VectorInit ( & pb . v, 0, 32 );
1153
1154 VectorDoUntil ( & expr -> expr, 0, do_eval_vector_param_expr, & pb );
1155 if ( pb . rc == 0 )
1156 {
1157 SConstExpr *rslt;
1158 uint32_t elem_count = VectorLength ( & pb . v );
1159 uint32_t elem_bits;
1160 size_t alloc_size;
1161
1162 {
1163 const SDatatype *dt = VSchemaFindTypeid ( self, td -> type_id );
1164 elem_bits = dt -> size;
1165 }
1166
1167 alloc_size = ( ( ( size_t ) elem_bits * elem_count + 7 ) >> 3 );
1168
1169 /** don't go below size of union ***/
1170 if ( alloc_size < sizeof rslt -> u )
1171 alloc_size = sizeof * rslt;
1172 /** overallocate here ***/
1173 else
1174 alloc_size += sizeof * rslt - sizeof rslt -> u ;
1175
1176 /** align to 4 bytes **/
1177 alloc_size = ( alloc_size + 3 ) & ~ 3;
1178 rslt = calloc ( alloc_size, 1 );
1179 if ( rslt == NULL )
1180 pb . rc = RC ( rcVDB, rcExpression, rcEvaluating, rcMemory, rcExhausted );
1181 else
1182 {
1183 uint32_t i;
1184
1185 rslt -> dad . var = eConstExpr;
1186 atomic32_set ( & rslt -> dad . refcount, 1 );
1187 rslt -> td = *td;
1188 rslt -> td . dim = elem_count;
1189
1190 for ( i = 0; i != elem_count; ++i )
1191 {
1192 const SConstExpr *y = VectorGet ( & pb . v, i );
1193 bitcpy ( & rslt -> u, i * elem_bits, & y -> u, 0, elem_bits );
1194 }
1195
1196 *xp = & rslt -> dad;
1197 }
1198 }
1199
1200 VectorWhack( & pb . v, vector_free, 0 );
1201
1202 return pb . rc;
1203 }
1204
1205
1206 /* eval-const-expr
1207 * tries to evaluate a constant expression against type
1208 * returns non-zero error code if failed
1209 */
eval_const_expr(const VSchema * self,const VTypedecl * td,const SExpression * expr,SExpression ** xp,Vector * cx_bind)1210 rc_t eval_const_expr ( const VSchema *self, const VTypedecl *td,
1211 const SExpression *expr, SExpression **xp, Vector *cx_bind )
1212 {
1213 rc_t rc;
1214 const SConstExpr *s;
1215
1216 switch ( expr -> var )
1217 {
1218 case eTypeExpr:
1219 return eval_type_expr ( self, td, ( const STypeExpr* ) expr, xp );
1220 case eConstExpr:
1221 s = ( const SConstExpr* ) expr;
1222 break;
1223 #if SLVL >= 3
1224 case eIndirectExpr:
1225 return eval_indirect_expr ( self, td, ( const SSymExpr* ) expr, xp, cx_bind );
1226 #endif
1227 #if SLVL >= 4
1228 case eFuncParamExpr:
1229 return eval_func_param_expr ( self, td, expr, xp );
1230 #endif
1231 case eCastExpr:
1232 return eval_const_cast_expr ( self, td, expr, xp );
1233 case eVectorExpr:
1234 return eval_vector_param_expr(self, td, ( const SVectExpr* ) expr, xp, cx_bind );
1235 default:
1236 *xp = NULL;
1237 return RC ( rcVDB, rcExpression, rcEvaluating, rcExpression, rcUnexpected );
1238 }
1239
1240 /* try to evaluate as numeric */
1241 rc = eval_numeric_expr ( self, td, s, ( SConstExpr** ) xp, false );
1242
1243 /* fall over to text */
1244 if ( rc != 0 && GetRCState ( rc ) == rcUnexpected && GetRCObject ( rc ) == (enum RCObject)rcType )
1245 rc = eval_text_expr ( self, td, s, ( SConstExpr** ) xp, false );
1246
1247 return rc;
1248 }
1249
1250 /* eval-uint-expr
1251 * special const expression evaluator for uint32_t
1252 */
eval_uint_expr(const VSchema * self,const SExpression * expr,uint32_t * value,Vector * cx_bind)1253 rc_t eval_uint_expr ( const VSchema *self,
1254 const SExpression *expr, uint32_t *value, Vector *cx_bind )
1255 {
1256 rc_t rc;
1257 VTypedecl td;
1258 SConstExpr *x;
1259
1260 /* capture runtime value for U32 */
1261 static atomic32_t s_U32_id;
1262 uint32_t U32_id = VSchemaCacheIntrinsicTypeId ( self, & s_U32_id, "U32" );
1263
1264 /* evaluate expression against type */
1265 td . type_id = U32_id;
1266 td . dim = 1;
1267 rc = eval_const_expr ( self, & td, expr, ( SExpression** ) & x, cx_bind );
1268 if ( rc != 0 )
1269 return rc;
1270
1271 /* verify dimensionality */
1272 assert ( x -> dad . var == eConstExpr );
1273 if ( x -> td . dim != 1 )
1274 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1275
1276 /* got it */
1277 * value = x -> u . u32 [ 0 ];
1278 free ( x );
1279 return 0;
1280 }
1281
1282
1283 /* eval-uint64-expr
1284 * special const expression evaluator for uint32_t
1285 */
eval_uint64_expr(const VSchema * self,const SExpression * expr,uint64_t * value,Vector * cx_bind)1286 rc_t eval_uint64_expr ( const VSchema *self,
1287 const SExpression *expr, uint64_t *value, Vector *cx_bind )
1288 {
1289 rc_t rc;
1290 VTypedecl td;
1291 SConstExpr *x;
1292
1293 /* capture runtime value for U64 */
1294 static atomic32_t s_U64_id;
1295 uint64_t U64_id = VSchemaCacheIntrinsicTypeId ( self, & s_U64_id, "U64" );
1296
1297 /* evaluate expression against type */
1298 td . type_id = U64_id;
1299 td . dim = 1;
1300 rc = eval_const_expr ( self, & td, expr, ( SExpression** ) & x, cx_bind );
1301 if ( rc != 0 )
1302 return rc;
1303
1304 /* verify dimensionality */
1305 assert ( x -> dad . var == eConstExpr );
1306 if ( x -> td . dim != 1 )
1307 return RC ( rcVDB, rcExpression, rcEvaluating, rcType, rcIncorrect );
1308
1309 /* got it */
1310 * value = x -> u . u64 [ 0 ];
1311 free ( x );
1312 return 0;
1313 }
1314
1315
1316 /* eval-expr-syntax
1317 * examine expression syntax
1318 * fixes forward references
1319 */
1320 static
eval_vect_expr_syntax(void * item,void * data)1321 bool CC eval_vect_expr_syntax ( void *item, void *data )
1322 {
1323 rc_t *rc = data;
1324 SExpression *x = item;
1325 * rc = eval_expr_syntax ( x );
1326 return ( * rc != 0 ) ? true : false;
1327 }
1328
1329 static
eval_type_expr_syntax(const STypeExpr * expr)1330 rc_t eval_type_expr_syntax ( const STypeExpr *expr )
1331 {
1332 if ( expr -> dad . var != eTypeExpr )
1333 return RC ( rcVDB, rcExpression, rcValidating, rcExpression, rcIncorrect );
1334 return 0;
1335 }
1336
1337 static
eval_fwd_expr_syntax(SSymExpr * expr)1338 rc_t eval_fwd_expr_syntax ( SSymExpr *expr )
1339 {
1340 const KSymbol *sym = expr -> _sym;
1341 assert ( sym != NULL );
1342 switch ( sym -> type )
1343 {
1344 case eFuncParam:
1345 expr -> dad . var = eParamExpr;
1346 break;
1347 case eProduction:
1348 expr -> dad . var = eProdExpr;
1349 break;
1350 case eColumn:
1351 expr -> dad . var = eColExpr;
1352 break;
1353 case ePhysMember:
1354 expr -> dad . var = ePhysExpr;
1355 break;
1356 case eForward:
1357 return RC ( rcVDB, rcSchema, rcValidating, rcName, rcUndefined );
1358 case eVirtual:
1359 break;
1360
1361 default:
1362 return RC ( rcVDB, rcSchema, rcValidating, rcExpression, rcInvalid );
1363 }
1364
1365 return 0;
1366 }
1367
eval_expr_syntax(const SExpression * expr)1368 rc_t eval_expr_syntax ( const SExpression *expr )
1369 {
1370 rc_t rc;
1371
1372 if ( expr == NULL )
1373 rc = RC ( rcVDB, rcExpression, rcValidating, rcSelf, rcNull );
1374 else switch ( expr -> var )
1375 {
1376 case eFwdExpr:
1377 rc = eval_fwd_expr_syntax ( ( SSymExpr* ) expr );
1378 break;
1379 case eCastExpr:
1380 rc = eval_type_expr_syntax ( ( const STypeExpr* ) ( ( const SBinExpr* ) expr ) -> left );
1381 if ( rc == 0 )
1382 rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> right );
1383 break;
1384 case eVectorExpr:
1385 rc = 0;
1386 VectorDoUntil ( & ( ( const SVectExpr* ) expr ) -> expr, false, eval_vect_expr_syntax, & rc );
1387 break;
1388 case eCondExpr:
1389 rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> left );
1390 if ( rc == 0 )
1391 rc = eval_expr_syntax ( ( ( const SBinExpr* ) expr ) -> right );
1392 break;
1393 default:
1394 rc = 0;
1395 }
1396
1397 return rc;
1398 }
1399
1400 #endif
1401