00001
00002 #include "define.h"
00003
00004 #ifdef POLARIS_GNU_PRAGMAS
00005 #pragma implementation
00006 #endif
00007
00008 #include <stdio.h>
00009 #include <memory.h>
00010
00011 #include "BinRep.h"
00012 #include "BinPtr.h"
00013 #include "MemBuf.h"
00014 #include "debug.h"
00015 #include "String.h"
00016 #include "IntElem.h"
00017 #include "Collection/Iterator.h"
00018 #include "Collection/Mutator.h"
00019 #include "Collection/KeyIterator.h"
00020 #include "macros.h"
00021
00022
00023
00024 static int
00025 bytes_per_value( int x )
00026 {
00027 if (x >= -128 && x <= 127)
00028 return 1;
00029 else if (x >= -32768 && x <= 32767)
00030 return 2;
00031 return 4;
00032 }
00033
00034 inline BINSTR_TYPE
00035 select_type( int size, BINSTR_TYPE t1, BINSTR_TYPE t2, BINSTR_TYPE t3 )
00036 {
00037 if (size == 1)
00038 return t1;
00039 else if (size == 2)
00040 return t2;
00041 return t3;
00042 }
00043
00044
00045
00046 BinRep::BinRep()
00047 {
00048 #ifdef CLASS_INSTANCE_REGISTRY
00049 register_instance(BIN_REP, sizeof(BinRep), this);
00050 #endif
00051
00052 _fc = _ILLEGAL_TYPES;
00053 _len = 0;
00054 }
00055
00056
00057 BinRep::BinRep(const BinRep &br)
00058 {
00059 #ifdef CLASS_INSTANCE_REGISTRY
00060 register_instance(BIN_REP, sizeof(BinRep), this);
00061 #endif
00062
00063 _fc = br._fc;
00064 _len = br._len;
00065
00066 if (br.is_tuple())
00067 _u.L = new List<BinRep>( *br._u.L );
00068 else if (br.is_set())
00069 _u.S = new Set<BinRep>( *br._u.S );
00070 else if (br.is_map())
00071 _u.D = new Database<String,BinRep>( *br._u.D );
00072 else {
00073 _u.C = malloc(_len*sizeof(char));
00074 memcpy( _u.C, br._u.C, _len );
00075 }
00076 }
00077
00078
00079 BinRep &
00080 BinRep::operator = (const BinRep &br)
00081 {
00082 _fc = br._fc;
00083 _len = br._len;
00084
00085 if (br.is_tuple())
00086 _u.L = new List<BinRep>( *br._u.L );
00087 else if (br.is_set())
00088 _u.S = new Set<BinRep>( *br._u.S );
00089 else if (br.is_map())
00090 _u.D = new Database<String,BinRep>( *br._u.D );
00091 else {
00092 _u.C = malloc(_len*sizeof(char));
00093 memcpy( _u.C, br._u.C, _len );
00094 }
00095
00096 return (*this);
00097 }
00098
00099 BinRep::BinRep(const void *binstr)
00100 {
00101 #ifdef CLASS_INSTANCE_REGISTRY
00102 register_instance(BIN_REP, sizeof(BinRep), this);
00103 #endif
00104
00105 _fc = _ILLEGAL_TYPES;
00106 _len = 0;
00107
00108 _parse( binstr );
00109 }
00110
00111 BinRep::~BinRep()
00112 {
00113 #ifdef CLASS_INSTANCE_REGISTRY
00114 unregister_instance(BIN_REP, this);
00115 #endif
00116
00117 _destroy();
00118 }
00119
00120 BinRep &
00121 BinRep::_omega() const
00122 {
00123 static BinRep *om = 0;
00124
00125 if (om == 0) {
00126 om = new BinRep;
00127 om->_fc = IEF_OMEGA;
00128 om->_len = 0;
00129 om->_u.C = 0;
00130 }
00131
00132 return *om;
00133 }
00134
00135 void
00136 BinRep::_parse( const void *binstr )
00137 {
00138 _destroy();
00139
00140 char *s = (char *) binstr;
00141
00142 if (*s == IEF_HEADER)
00143 _ief_parse( binstr, 0 );
00144 else
00145 _setl_parse( binstr );
00146 }
00147
00148 void
00149 BinRep::_parse( istream & ifs )
00150 {
00151 char ch;
00152
00153 _destroy();
00154
00155 ifs.get( ch );
00156
00157 if (ifs.eof())
00158 return;
00159
00160 ifs.putback( ch );
00161
00162 if (ch == IEF_HEADER)
00163 _ief_parse( ifs );
00164 else
00165 _setl_parse( ifs );
00166 }
00167
00168 static void
00169 aux_ief_parse( Database<int,BinRep> &dict, BinRep &br, BinPtr &p )
00170 {
00171 binptr_1 form_code;
00172
00173 p.fetch( form_code );
00174
00175 switch ( form_code ) {
00176 case IEF_OMEGA:
00177 br.put_omega();
00178 break;
00179
00180 case IEF_TRUE:
00181 br.put_boolean( True );
00182 break;
00183
00184 case IEF_FALSE:
00185 br.put_boolean( False );
00186 break;
00187
00188 case IEF_REAL:
00189 {
00190 double x;
00191 p.fetch( x );
00192 br.put_double( x );
00193 }
00194 break;
00195
00196 case IEF_INTEGER_1:
00197 {
00198 binptr_1 x;
00199 p.fetch( x );
00200 br.put_integer( x );
00201 }
00202 break;
00203
00204 case IEF_INTEGER_2:
00205 {
00206 binptr_2 x;
00207 p.fetch( x );
00208 br.put_integer( x );
00209 }
00210 break;
00211
00212 case IEF_INTEGER_4:
00213 {
00214 binptr_4 x;
00215 p.fetch( x );
00216 br.put_integer( x );
00217 }
00218 break;
00219
00220 case IEF_STRING_1:
00221 {
00222 binptr_1 size;
00223 p.fetch( size );
00224
00225 char *buffer = new char[ size+1 ];
00226
00227 p.fetch( buffer, size );
00228
00229 br.put_string( buffer, size );
00230
00231 delete [] buffer;
00232 }
00233 break;
00234
00235 case IEF_STRING_2:
00236 {
00237 binptr_2 size;
00238 p.fetch( size );
00239
00240 char *buffer = new char[ size+1 ];
00241
00242 p.fetch( buffer, size );
00243 br.put_string( buffer, size );
00244
00245 delete [] buffer;
00246 }
00247 break;
00248
00249 case IEF_STRING_4:
00250 {
00251 binptr_4 size;
00252 p.fetch( size );
00253
00254 char *buffer = new char[ size+1 ];
00255
00256 p.fetch( buffer, size );
00257 br.put_string( buffer, size );
00258
00259 delete [] buffer;
00260 }
00261 break;
00262
00263 case IEF_TUPLE_1:
00264 {
00265 binptr_1 size;
00266 p.fetch( size );
00267 List<BinRep> *L = new List<BinRep>;
00268 for (int i = 0; i < size; ++i) {
00269 BinRep *b = new BinRep;
00270 aux_ief_parse( dict, *b, p );
00271 L->ins_last( b );
00272 }
00273 br.put_tuple( L );
00274 }
00275 break;
00276
00277 case IEF_TUPLE_2:
00278 {
00279 binptr_2 size;
00280 p.fetch( size );
00281 List<BinRep> *L = new List<BinRep>;
00282 for (int i = 0; i < size; ++i) {
00283 BinRep *b = new BinRep;
00284 aux_ief_parse( dict, *b, p );
00285 L->ins_last( b );
00286 }
00287 br.put_tuple( L );
00288 }
00289 break;
00290
00291 case IEF_TUPLE_4:
00292 {
00293 binptr_4 size;
00294 p.fetch( size );
00295 List<BinRep> *L = new List<BinRep>;
00296 for (int i = 0; i < size; ++i) {
00297 BinRep *b = new BinRep;
00298 aux_ief_parse( dict, *b, p );
00299 L->ins_last( b );
00300 }
00301 br.put_tuple( L );
00302 }
00303 break;
00304
00305 case IEF_SET_1:
00306 case IEF_MAP_1:
00307 {
00308 binptr_1 size;
00309 p.fetch( size );
00310 Set<BinRep> *S = new Set<BinRep>;
00311 for (int i = 0; i < size; ++i) {
00312 BinRep *b = new BinRep;
00313 aux_ief_parse( dict, *b, p );
00314 S->ins( b );
00315 }
00316 br.put_set( S );
00317 }
00318 break;
00319
00320 case IEF_SET_2:
00321 case IEF_MAP_2:
00322 {
00323 binptr_2 size;
00324 p.fetch( size );
00325 Set<BinRep> *S = new Set<BinRep>;
00326 for (int i = 0; i < size; ++i) {
00327 BinRep *b = new BinRep;
00328 aux_ief_parse( dict, *b, p );
00329 S->ins( b );
00330 }
00331 br.put_set( S );
00332 }
00333 break;
00334
00335 case IEF_SET_4:
00336 case IEF_MAP_4:
00337 {
00338 binptr_4 size;
00339 p.fetch( size );
00340 Set<BinRep> *S = new Set<BinRep>;
00341 for (int i = 0; i < size; ++i) {
00342 BinRep *b = new BinRep;
00343 aux_ief_parse( dict, *b, p );
00344 S->ins( b );
00345 }
00346 br.put_set( S );
00347 }
00348 break;
00349
00350 case IEF_DICT_1:
00351 {
00352 binptr_1 x;
00353 p.fetch( x );
00354 BinRep *b = dict.find_ref( (int) x );
00355 p_assert( b, "Error: unknown dictionary entry" );
00356 br = *b;
00357 }
00358 break;
00359
00360 case IEF_DICT_2:
00361 {
00362 binptr_2 x;
00363 p.fetch( x );
00364 BinRep *b = dict.find_ref( (int) x );
00365 p_assert( b, "Error: unknown dictionary entry" );
00366 br = *b;
00367 }
00368 break;
00369
00370 case IEF_DICT_4:
00371 {
00372 binptr_4 x;
00373 p.fetch( x );
00374 BinRep *b = dict.find_ref( (int) x );
00375 p_assert( b, "Error: unknown dictionary entry" );
00376 br = *b;
00377 }
00378 break;
00379 }
00380 }
00381
00382
00383 void
00384 BinRep::_ief_parse( const void *bin_header, const void *bin_body )
00385 {
00386 Database<int,BinRep> dict;
00387
00388
00389 BinPtr p( bin_header );
00390 binptr_4 header_version, header_length;
00391
00392 binptr_1 form_code;
00393 p.fetch( form_code );
00394
00395 p_assert( form_code == IEF_HEADER, "not the IEF_HEADER code" );
00396
00397 p.fetch( header_version );
00398 p.fetch( header_length );
00399
00400 int count = 0;
00401
00402 p.fetch( form_code );
00403
00404 switch ( form_code ) {
00405 case IEF_TUPLE_1:
00406 {
00407 binptr_1 x;
00408 p.fetch( x );
00409 count = x;
00410 break;
00411 }
00412 case IEF_TUPLE_2:
00413 {
00414 binptr_2 x;
00415 p.fetch( x );
00416 count = x;
00417 break;
00418 }
00419 case IEF_TUPLE_4:
00420 {
00421 binptr_4 x;
00422 p.fetch( x );
00423 count = x;
00424 break;
00425 }
00426 }
00427
00428 for (int i = 1; i <= count; ++i) {
00429 BinRep *br = new BinRep;
00430 aux_ief_parse( dict, *br, p );
00431 dict.ins( i, br );
00432 }
00433
00434 if (bin_body != 0)
00435 p.reset( bin_body );
00436
00437 binptr_4 body_version, body_length;
00438
00439 p.fetch( form_code );
00440 p_assert( form_code == IEF_BODY, "not the IEF_BODY code" );
00441
00442 p.fetch( body_version );
00443 p.fetch( body_length );
00444
00445 aux_ief_parse( dict, (*this), p );
00446 }
00447
00448 void
00449 BinRep::_ief_parse( istream &ifs )
00450 {
00451 Database<int,BinRep> dict;
00452
00453 BinPtr p( ifs );
00454
00455 binptr_4 header_version, header_length;
00456 binptr_1 form_code;
00457
00458 p.fetch( form_code );
00459
00460 p_assert( form_code == IEF_HEADER, "not the IEF_HEADER code" );
00461
00462 p.fetch( header_version );
00463 p.fetch( header_length );
00464
00465 int count = 0;
00466
00467 p.fetch( form_code );
00468
00469 switch ( form_code ) {
00470 case IEF_TUPLE_1:
00471 {
00472 binptr_1 x;
00473 p.fetch( x );
00474 count = x;
00475 break;
00476 }
00477 case IEF_TUPLE_2:
00478 {
00479 binptr_2 x;
00480 p.fetch( x );
00481 count = x;
00482 break;
00483 }
00484 case IEF_TUPLE_4:
00485 {
00486 binptr_4 x;
00487 p.fetch( x );
00488 count = x;
00489 break;
00490 }
00491 }
00492
00493 for (int i = 1; i <= count; ++i) {
00494 BinRep *br = new BinRep;
00495 aux_ief_parse( dict, *br, p );
00496 dict.ins( i, br );
00497 }
00498
00499 binptr_4 body_version, body_length;
00500
00501 p.fetch( form_code );
00502 p_assert( form_code == IEF_BODY, "not the IEF_BODY code" );
00503
00504 p.fetch( body_version );
00505 p.fetch( body_length );
00506
00507 aux_ief_parse( dict, (*this), p );
00508 }
00509
00510
00511 static void
00512 aux_setl_parse( BinRep &br, BinPtr &p )
00513 {
00514 binptr_4 form_code;
00515
00516 p.fetch( form_code );
00517
00518 switch ( form_code ) {
00519 case FT_ALT_OMEGA:
00520 {
00521 binptr_4 extra;
00522
00523 p.fetch( extra );
00524 br.put_omega();
00525 }
00526 break;
00527
00528 case FT_OMEGA:
00529 br.put_omega();
00530 break;
00531
00532 case FT_ATOM:
00533 {
00534 binptr_4 atom_value, pointer;
00535
00536 p.fetch( atom_value );
00537 p.fetch( pointer );
00538 br.put_boolean( (atom_value != 0) );
00539 }
00540 break;
00541
00542 case FT_SHORT:
00543 {
00544 binptr_4 int_value;
00545
00546 p.fetch( int_value );
00547 br.put_integer( int_value );
00548 }
00549 break;
00550
00551 case FT_DOUBLE:
00552 {
00553 double real_value;
00554
00555 p.fetch( real_value );
00556 br.put_double( real_value );
00557 }
00558 break;
00559
00560 case FT_LONGINT:
00561 {
00562 binptr_4 long_length, digit;
00563 int long_value, sign, pos;
00564
00565 p.fetch( long_length );
00566
00567 if (long_length >= 0)
00568 sign = 1;
00569 else {
00570 sign = -1;
00571 long_length = -long_length;
00572 }
00573
00574 for (long_value = pos = 0; long_length > 0; --long_length) {
00575 p.fetch( digit );
00576 long_value |= (digit << (pos++ * 15));
00577 }
00578 long_value = sign * long_value;
00579
00580 br.put_integer( long_value );
00581 }
00582 break;
00583
00584 case FT_STRING:
00585 {
00586 binptr_4 len;
00587
00588 p.fetch( len );
00589
00590 char *buffer = new char[ len+1 ];
00591
00592 p.fetch( buffer, len );
00593 br.put_string( buffer, len );
00594
00595 delete [] buffer;
00596 }
00597 break;
00598
00599 case FT_TUPLE:
00600 {
00601 binptr_4 tuple_length;
00602
00603 p.fetch( tuple_length );
00604
00605 List<BinRep> *L = new List<BinRep>;
00606
00607 for (int i = 0; i < tuple_length; ++i) {
00608 BinRep *b = new BinRep;
00609 aux_setl_parse( *b, p );
00610 L->ins_last( b );
00611 }
00612
00613 br.put_tuple( L );
00614 }
00615 break;
00616 case FT_SET:
00617 {
00618 binptr_4 set_length;
00619
00620 p.fetch( set_length );
00621
00622 Set<BinRep> *S = new Set<BinRep>;
00623
00624 for (int i = 0; i < set_length; ++i) {
00625 BinRep *b = new BinRep;
00626 aux_setl_parse( *b, p );
00627 S->ins( b );
00628 }
00629
00630 br.put_set( S );
00631 }
00632 break;
00633
00634 default:
00635 p_abort( "unknown form_code" );
00636 break;
00637 }
00638 }
00639
00640 void
00641 BinRep::_setl_parse( const void *binstr )
00642 {
00643 BinPtr p( binstr );
00644 aux_setl_parse( *this, p );
00645 }
00646
00647 void
00648 BinRep::_setl_parse( istream &ifs )
00649 {
00650 BinPtr p( ifs );
00651 aux_setl_parse( *this, p );
00652 }
00653
00654 void
00655 BinRep::_init()
00656 {
00657 _fc = _ILLEGAL_TYPES;
00658 _len = 0;
00659 }
00660
00661
00662 void
00663 BinRep::_destroy()
00664 {
00665 switch ( _fc ) {
00666 case _ILLEGAL_TYPES:
00667
00668 break;
00669
00670 case FT_TUPLE:
00671 case IEF_TUPLE_1:
00672 case IEF_TUPLE_2:
00673 case IEF_TUPLE_4:
00674 delete _u.L;
00675 _u.L = 0;
00676 break;
00677
00678 case FT_SET:
00679 case IEF_SET_1:
00680 case IEF_SET_2:
00681 case IEF_SET_4:
00682 delete _u.S;
00683 _u.S = 0;
00684 break;
00685
00686 case IEF_MAP_1:
00687 case IEF_MAP_2:
00688 case IEF_MAP_4:
00689 p_abort( "not supported" );
00690
00691 delete _u.D;
00692 _u.D = 0;
00693 break;
00694
00695 default:
00696 free(_u.C);
00697 _u.C = 0;
00698 break;
00699 }
00700
00701 _fc = _ILLEGAL_TYPES;
00702 _len = 0;
00703 }
00704
00705 BinRep &
00706 BinRep::operator = (const void *binstr)
00707 {
00708 _destroy();
00709 _parse( binstr );
00710
00711 return (*this);
00712 }
00713
00714 void
00715 BinRep::ascii_format(String & str) const
00716 {
00717 str = "";
00718 _ascii_format( str );
00719 }
00720
00721 void
00722 BinRep::_ascii_format(String & str) const
00723 {
00724 if ( is_omega() )
00725 str += "OM";
00726 else if (is_boolean())
00727 str += ( to_boolean() ? "TRUE" : "FALSE" );
00728 else if (is_integer()){
00729 char buffer[32];
00730 sprintf( buffer, "%d", to_integer() );
00731 str += buffer;
00732 }
00733 else if (is_double()) {
00734 char buffer[32];
00735 sprintf( buffer, "%f", to_double() );
00736 str += "(double)";
00737 str += buffer;
00738 }
00739 else if (is_string()) {
00740 String s;
00741 to_string( s );
00742
00743 str += "\"";
00744 str += s;
00745 str += "\"";
00746 }
00747 else if (is_tuple()) {
00748 str += "[";
00749 Iterator<BinRep> iter = to_tuple();
00750 if (iter.valid()) {
00751 iter.current()._ascii_format( str );
00752 for (++iter; iter.valid(); ++iter) {
00753 str += ",";
00754 iter.current()._ascii_format( str );
00755 }
00756 }
00757 str += "]";
00758 }
00759 else if (is_set()) {
00760 str += "{";
00761 Iterator<BinRep> iter = to_set();
00762 if (iter.valid()) {
00763 iter.current()._ascii_format( str );
00764 for (++iter; iter.valid(); ++iter) {
00765 str += ",";
00766 iter.current()._ascii_format( str );
00767 }
00768 }
00769 str += "}";
00770 }
00771 else if (is_map()) {
00772 str += "{";
00773 KeyIterator<String,BinRep> iter = to_map();
00774 if (iter.valid()) {
00775 str += "[";
00776 str += iter.current_key();
00777 str += ",";
00778 iter.current_data()._ascii_format( str );
00779 str += "]";
00780
00781 for (++iter; iter.valid(); ++iter) {
00782 str += ", [";
00783 str += iter.current_key();
00784 str += ",";
00785 iter.current_data()._ascii_format( str );
00786 str += "]";
00787 }
00788 }
00789 str += "}";
00790 }
00791 }
00792
00793 int
00794 BinRep::_setl_length() const
00795 {
00796 int size = sizeof( binptr_4 );
00797
00798 switch( _fc ) {
00799 case FT_OMEGA:
00800 case IEF_OMEGA:
00801 break;
00802
00803 case FT_ATOM:
00804 case IEF_TRUE:
00805 case IEF_FALSE:
00806 size += 2 * sizeof( binptr_4 );
00807 break;
00808
00809 case FT_DOUBLE:
00810 case IEF_REAL:
00811 size += sizeof( binptr_8 );
00812 break;
00813
00814 case FT_LONGINT:
00815 case FT_SHORT:
00816 case IEF_INTEGER_1:
00817 case IEF_INTEGER_2:
00818 case IEF_INTEGER_4:
00819 {
00820 int x = to_integer();
00821
00822 if (bytes_per_value(x) <= 2)
00823 size += sizeof( binptr_4 );
00824 else
00825 size += sizeof( binptr_4 ) + 3*sizeof( binptr_4 );
00826 }
00827 break;
00828
00829 case FT_STRING:
00830 case IEF_STRING_1:
00831 case IEF_STRING_2:
00832 case IEF_STRING_4:
00833 size += sizeof( binptr_4 ) + _len;
00834 break;
00835
00836 case FT_TUPLE:
00837 case IEF_TUPLE_1:
00838 case IEF_TUPLE_2:
00839 case IEF_TUPLE_4:
00840 {
00841 size += sizeof( binptr_4 );
00842 for (Iterator<BinRep> iter = to_tuple(); iter.valid(); ++iter)
00843 size += iter.current()._setl_length();
00844 }
00845 break;
00846
00847 case FT_SET:
00848 case IEF_SET_1:
00849 case IEF_SET_2:
00850 case IEF_SET_4:
00851 {
00852 size += sizeof( binptr_4 );
00853 for (Iterator<BinRep> iter = to_set(); iter.valid(); ++iter)
00854 size += iter.current()._setl_length();
00855 }
00856 break;
00857
00858 case IEF_MAP_1:
00859 case IEF_MAP_2:
00860 case IEF_MAP_4:
00861 {
00862 p_abort( "not suppoted" );
00863
00864 size += sizeof( binptr_4 );
00865 for (KeyIterator<String,BinRep> iter = to_map();
00866 iter.valid(); ++iter) {
00867 size += iter.current_data()._setl_length();
00868 }
00869 }
00870 break;
00871
00872 default:
00873 p_abort( "unknown form code" );
00874 break;
00875 }
00876
00877 return size;
00878 }
00879
00880 int
00881 BinRep::_ief_length( Database<String,IntElem> *map ) const
00882 {
00883 int size = sizeof( binptr_1 );
00884
00885 switch( _fc ) {
00886 case FT_OMEGA:
00887 case IEF_OMEGA:
00888 case FT_ATOM:
00889 case IEF_TRUE:
00890 case IEF_FALSE:
00891 break;
00892
00893 case FT_DOUBLE:
00894 case IEF_REAL:
00895 size += sizeof( binptr_8 );
00896 break;
00897
00898 case FT_LONGINT:
00899 case FT_SHORT:
00900 case IEF_INTEGER_1:
00901 case IEF_INTEGER_2:
00902 case IEF_INTEGER_4:
00903 size += bytes_per_value( to_integer() );
00904 break;
00905
00906 case FT_STRING:
00907 case IEF_STRING_1:
00908 case IEF_STRING_2:
00909 case IEF_STRING_4:
00910 if (map == 0)
00911 size += bytes_per_value( _len ) + _len;
00912 else {
00913 String str;
00914
00915 to_string( str );
00916
00917 IntElem *e;
00918
00919 if ((e = map->find_ref(str)) == 0) {
00920 e = new IntElem( map->entries() + 1 );
00921 map->ins( str, e );
00922 }
00923
00924 size += bytes_per_value( e->value() );
00925 }
00926 break;
00927
00928 case FT_TUPLE:
00929 case IEF_TUPLE_1:
00930 case IEF_TUPLE_2:
00931 case IEF_TUPLE_4:
00932 {
00933 size += bytes_per_value( to_tuple().entries() );
00934 for (Iterator<BinRep> iter = to_tuple(); iter.valid(); ++iter)
00935 size += iter.current()._ief_length( map );
00936 }
00937 break;
00938
00939 case FT_SET:
00940 case IEF_SET_1:
00941 case IEF_SET_2:
00942 case IEF_SET_4:
00943 {
00944 size += bytes_per_value( to_set().entries() );
00945 for (Iterator<BinRep> iter = to_set(); iter.valid(); ++iter)
00946 size += iter.current()._ief_length( map );
00947 }
00948 break;
00949
00950 case IEF_MAP_1:
00951 case IEF_MAP_2:
00952 case IEF_MAP_4:
00953 {
00954 p_abort( "not suppoted" );
00955
00956 size += bytes_per_value( to_map().entries() );
00957 for (KeyIterator<String,BinRep> iter = to_map();
00958 iter.valid(); ++iter) {
00959 size += iter.current_data()._ief_length( map );
00960 }
00961 }
00962 break;
00963
00964 default:
00965 p_abort( "unknown form code" );
00966 break;
00967 }
00968
00969 return size;
00970 }
00971
00972 void
00973 BinRep::_ief_format( BinPtr &p, Database<String,IntElem> *map ) const
00974 {
00975 switch( _fc ) {
00976 case FT_OMEGA:
00977 case IEF_OMEGA:
00978 p.store( IEF_OMEGA, 1 );
00979 break;
00980
00981 case FT_ATOM:
00982 case IEF_TRUE:
00983 case IEF_FALSE:
00984 p.store( ( to_boolean() ? IEF_TRUE : IEF_FALSE ), 1 );
00985 break;
00986
00987 case FT_DOUBLE:
00988 case IEF_REAL:
00989 {
00990 double x = to_double();
00991
00992 p.store( IEF_REAL, 1 );
00993 p.store( x );
00994 }
00995 break;
00996
00997 case FT_LONGINT:
00998 case FT_SHORT:
00999 case IEF_INTEGER_1:
01000 case IEF_INTEGER_2:
01001 case IEF_INTEGER_4:
01002 {
01003 int value = to_integer();
01004 int size = bytes_per_value( value );
01005
01006 p.store( select_type(size,
01007 IEF_INTEGER_1, IEF_INTEGER_2, IEF_INTEGER_4 ), 1 );
01008 p.store( value, size );
01009 }
01010 break;
01011
01012 case FT_STRING:
01013 case IEF_STRING_1:
01014 case IEF_STRING_2:
01015 case IEF_STRING_4:
01016 if (map == 0) {
01017 int size = bytes_per_value( _len );
01018
01019 p.store( select_type(size,
01020 IEF_STRING_1, IEF_STRING_2, IEF_STRING_4 ), 1 );
01021 p.store( _len, size );
01022 p.store( _u.C, _len );
01023 }
01024 else {
01025 String str;
01026 to_string( str );
01027
01028 IntElem *e = map->find_ref(str);
01029 p_assert( e, "must call _ief_length() first" );
01030
01031 int size = bytes_per_value( e->value() );
01032
01033 p.store( select_type(size,
01034 IEF_DICT_1, IEF_DICT_2, IEF_DICT_4 ), 1 );
01035 p.store( e->value(), size );
01036 }
01037 break;
01038
01039 case FT_TUPLE:
01040 case IEF_TUPLE_1:
01041 case IEF_TUPLE_2:
01042 case IEF_TUPLE_4:
01043 {
01044 List<BinRep> &L = to_tuple();
01045
01046 int size = bytes_per_value( L.entries() );
01047
01048 p.store( select_type(size,
01049 IEF_TUPLE_1, IEF_TUPLE_2, IEF_TUPLE_4 ), 1 );
01050 p.store( L.entries(), size );
01051
01052 for (Iterator<BinRep> iter = L; iter.valid(); ++iter)
01053 iter.current()._ief_format( p, map );
01054 }
01055 break;
01056
01057 case FT_SET:
01058 case IEF_SET_1:
01059 case IEF_SET_2:
01060 case IEF_SET_4:
01061 {
01062 Set<BinRep> &S = to_set();
01063
01064 int size = bytes_per_value( S.entries() );
01065
01066 p.store( select_type(size,
01067 IEF_SET_1, IEF_SET_2, IEF_SET_4 ), 1 );
01068 p.store( S.entries(), size );
01069
01070 for (Iterator<BinRep> iter = S; iter.valid(); ++iter)
01071 iter.current()._ief_format( p, map );
01072 }
01073 break;
01074
01075 case IEF_MAP_1:
01076 case IEF_MAP_2:
01077 case IEF_MAP_4:
01078 {
01079 p_abort( "not supported" );
01080
01081 Database<String, BinRep> &D = to_map();
01082
01083 int size = bytes_per_value( D.entries() );
01084
01085 p.store( select_type(size,
01086 IEF_MAP_1, IEF_MAP_2, IEF_MAP_4 ), 1 );
01087 p.store( D.entries(), size );
01088
01089 for (KeyIterator<String,BinRep> iter = to_map();
01090 iter.valid(); ++iter) {
01091
01092 iter.current_data()._ief_format( p, map );
01093 }
01094 }
01095 break;
01096
01097 default:
01098 p_abort( "unknown form code" );
01099 break;
01100 }
01101 }
01102
01103 void
01104 BinRep::ief_format(MemBuf &buf) const
01105 {
01106 Database<String,IntElem> map;
01107
01108 int body_version = 1;
01109 int body_length = _ief_length( &map );
01110
01111 List<BinRep> *dict = new List<BinRep>;
01112
01113 dict->make_static_list( map.entries() );
01114
01115 for (KeyIterator<String,IntElem> iter = map; iter.valid(); ++iter) {
01116 BinRep *b = new BinRep;
01117 b->put_string( iter.current_key() );
01118 dict->modify( iter.current_data().value() - 1, b );
01119 }
01120
01121 dict->unfix_size();
01122
01123 BinRep head;
01124
01125 head.put_tuple( dict );
01126
01127 int header_version = 1;
01128 int header_length = head._ief_length( 0 );
01129
01130 buf.reset();
01131 buf.append_empty( 2*sizeof(binptr_1) + 4*sizeof(binptr_4)
01132 + header_length
01133 + body_length );
01134 BinPtr p( buf.data_ref() );
01135
01136 p.store( IEF_HEADER, 1 );
01137 p.store( header_version );
01138 p.store( header_length );
01139 head._ief_format( p, 0 );
01140
01141 p.store( IEF_BODY, 1 );
01142 p.store( body_version );
01143 p.store( body_length );
01144 _ief_format( p, &map );
01145 }
01146
01147 void
01148 BinRep::_setl_format( BinPtr &p ) const
01149 {
01150 switch( _fc ) {
01151 case FT_OMEGA:
01152 case IEF_OMEGA:
01153 p.store( (long) FT_OMEGA, 4 );
01154 break;
01155
01156 case FT_ATOM:
01157 case IEF_TRUE:
01158 case IEF_FALSE:
01159 {
01160 binptr_4 atom_value= (int) to_boolean();
01161 binptr_4 pointer = 0x01234567;
01162
01163 p.store( FT_ATOM, 4 );
01164 p.store( atom_value );
01165 p.store( pointer );
01166 }
01167 break;
01168
01169 case FT_DOUBLE:
01170 case IEF_REAL:
01171 {
01172 double x = to_double();
01173
01174 p.store( FT_DOUBLE, 4 );
01175 p.store( x );
01176 }
01177 break;
01178
01179 case FT_LONGINT:
01180 case FT_SHORT:
01181 case IEF_INTEGER_1:
01182 case IEF_INTEGER_2:
01183 case IEF_INTEGER_4:
01184 {
01185 int value = to_integer();
01186 int size = bytes_per_value( value );
01187
01188 if (size <= 2) {
01189 p.store( FT_SHORT, 4 );
01190 p.store( value, 4 );
01191 }
01192 else {
01193 const int max_packets = 3;
01194 binptr_4 buffer[ max_packets ];
01195
01196 int sign = 1, len = 0;
01197
01198 if (value < 0) {
01199 sign = -1;
01200 value = -value;
01201 }
01202
01203 do {
01204 const int mask = (1 << 15) - 1;
01205 buffer[ len++ ] = (mask & value);
01206 value >>= 15;
01207 } while (value != 0);
01208
01209 p_assert( len > 0 && len <= max_packets, "too many packets" );
01210
01211 sign = sign * len;
01212
01213 p.store( FT_LONGINT, 4 );
01214 p.store( sign );
01215
01216 for (int i = 0; i < len; ++i)
01217 p.store( buffer[i] );
01218 }
01219 }
01220 break;
01221
01222 case FT_STRING:
01223 case IEF_STRING_1:
01224 case IEF_STRING_2:
01225 case IEF_STRING_4:
01226 p.store( FT_STRING, 4 );
01227 p.store( _len, 4 );
01228 p.store( _u.C, _len );
01229 break;
01230
01231 case FT_TUPLE:
01232 case IEF_TUPLE_1:
01233 case IEF_TUPLE_2:
01234 case IEF_TUPLE_4:
01235 {
01236 List<BinRep> &L = to_tuple();
01237
01238 p.store( FT_TUPLE, 4 );
01239 p.store( L.entries(), 4 );
01240
01241 for (Iterator<BinRep> iter = L; iter.valid(); ++iter)
01242 iter.current()._setl_format( p );
01243 }
01244 break;
01245
01246 case FT_SET:
01247 case IEF_SET_1:
01248 case IEF_SET_2:
01249 case IEF_SET_4:
01250 {
01251 Set<BinRep> &S = to_set();
01252
01253 p.store( FT_SET, 4 );
01254 p.store( S.entries(), 4 );
01255
01256 for (Iterator<BinRep> iter = S; iter.valid(); ++iter)
01257 iter.current()._setl_format( p );
01258 }
01259 break;
01260
01261 case IEF_MAP_1:
01262 case IEF_MAP_2:
01263 case IEF_MAP_4:
01264 p_abort( "not supported" );
01265 break;
01266
01267 default:
01268 p_abort( "unknown form code" );
01269 break;
01270 }
01271 }
01272
01273 void
01274 BinRep::setl_format(MemBuf &buf) const
01275 {
01276 int length = _setl_length();
01277
01278 buf.reset();
01279 buf.append_empty( sizeof(binptr_4) + length );
01280
01281 BinPtr p( buf.data_ref() );
01282
01283 p.store( length );
01284 _setl_format( p );
01285 }
01286
01287 void
01288 BinRep::read( istream &ifs )
01289 {
01290 char ch;
01291
01292
01293 _destroy();
01294
01295 ifs.get( ch );
01296
01297 if (ifs.eof())
01298 return;
01299
01300 ifs.putback( ch );
01301
01302 if (ch != IEF_HEADER) {
01303 int length = -1;
01304
01305 ifs.read( (char *) &length, sizeof(length) );
01306
01307 if (length > 0) {
01308 p_assert( length < 9999999, "SETL binstr too long" );
01309
01310 _setl_parse( ifs );
01311
01312 ifs.get( ch );
01313
01314 if (! ifs.eof())
01315 ifs.putback( ch );
01316 }
01317 }
01318 else {
01319 p_assert( ch == IEF_HEADER, "not IEF_HEADER code" );
01320
01321 _ief_parse( ifs );
01322
01323 ifs.get( ch );
01324 if (! ifs.eof())
01325 ifs.putback( ch );
01326 }
01327 }
01328
01329 int
01330 BinRep::structures_OK() const
01331 {
01332
01333
01334
01335
01336 return 1;
01337 }
01338
01339 Boolean
01340 BinRep::is_omega() const
01341 {
01342 return (
01343 #if 0
01344 type() == FT_ALT_OMEGA || type() == FT_OMEGA ||
01345 #endif
01346 type() == IEF_OMEGA );
01347 }
01348
01349 Boolean
01350 BinRep::is_boolean() const
01351 {
01352 return (
01353 #if 0
01354 type() == FT_ATOM ||
01355 #endif
01356 type() == IEF_TRUE || type() == IEF_FALSE );
01357 }
01358
01359 Boolean
01360 BinRep::is_double() const
01361 {
01362 return (
01363 #if 0
01364 type() == FT_DOUBLE ||
01365 #endif
01366 type() == IEF_REAL );
01367 }
01368
01369 Boolean
01370 BinRep::is_integer() const
01371 {
01372 return (
01373 #if 0
01374 type() == FT_LONGINT || type() == FT_SHORT ||
01375 #endif
01376 type() == IEF_INTEGER_1 || type() == IEF_INTEGER_2 ||
01377 type() == IEF_INTEGER_4 );
01378 }
01379
01380 Boolean
01381 BinRep::is_string() const
01382 {
01383 return (
01384 #if 0
01385 type() == FT_STRING ||
01386 #endif
01387 type() == IEF_STRING_1 ||
01388 type() == IEF_STRING_2 || type() == IEF_STRING_4 );
01389 }
01390
01391 Boolean
01392 BinRep::is_tuple() const
01393 {
01394 return (
01395 #if 0
01396 type() == FT_TUPLE ||
01397 #endif
01398 type() == IEF_TUPLE_1 ||
01399 type() == IEF_TUPLE_2 || type() == IEF_TUPLE_4 );
01400 }
01401
01402 Boolean
01403 BinRep::is_set() const
01404 {
01405 return (
01406 #if 0
01407 type() == FT_SET ||
01408 #endif
01409 #if 0
01410 type() == IEF_MAP_1 ||
01411 type() == IEF_MAP_2 || type() == IEF_MAP_4 ||
01412 #endif
01413 type() == IEF_SET_1 ||
01414 type() == IEF_SET_2 || type() == IEF_SET_4 );
01415 }
01416
01417 Boolean
01418 BinRep::to_boolean() const
01419 {
01420 p_assert( is_boolean(), "not a boolean" );
01421
01422 switch ( _fc ) {
01423 case IEF_TRUE:
01424 return True;
01425
01426 case IEF_FALSE:
01427 return False;
01428 default:
01429 return False;
01430 }
01431
01432 return False;
01433 }
01434
01435
01436 double
01437 BinRep::to_double() const
01438 {
01439 p_assert( is_double(), "not a double" );
01440
01441 BinPtr p( _u.C );
01442
01443 double value;
01444
01445 p.fetch( value );
01446
01447 return value;
01448 }
01449
01450 int
01451 BinRep::to_integer() const
01452 {
01453 p_assert( is_integer(), "not an integer" );
01454
01455 BinPtr p( _u.C );
01456
01457 switch ( _fc ) {
01458 case IEF_INTEGER_1:
01459 {
01460 binptr_1 value;
01461 p.fetch( value );
01462
01463 return value;
01464 }
01465
01466 case IEF_INTEGER_2:
01467 {
01468 binptr_2 value;
01469 p.fetch( value );
01470
01471 return value;
01472 }
01473
01474 case IEF_INTEGER_4:
01475 {
01476 binptr_4 value;
01477 p.fetch( value );
01478
01479 return value;
01480 }
01481 default: return 0;
01482 }
01483
01484 return 0;
01485 }
01486
01487
01488 void
01489 BinRep::to_string(String & str) const
01490 {
01491 p_assert( is_string(), "not a string" );
01492
01493 String s( (char *) _u.C, _len );
01494
01495 str = s;
01496 }
01497
01498
01499 List<BinRep> &
01500 BinRep::to_tuple() const
01501 {
01502 p_assert( is_tuple(), "not a tuple" );
01503
01504 return *_u.L;
01505 }
01506
01507 Set<BinRep> &
01508 BinRep::to_set() const
01509 {
01510 p_assert( is_set(), "not a set" );
01511 return *_u.S;
01512 }
01513
01514
01515 Database<String, BinRep> &
01516 BinRep::to_map() const
01517 {
01518 p_assert( is_map(), "not a map" );
01519
01520 return *_u.D;
01521 }
01522
01523
01524 void
01525 BinRep::put_omega()
01526 {
01527 _destroy();
01528
01529 _fc = IEF_OMEGA;
01530 _len = 0;
01531 _u.C = 0;
01532 }
01533
01534 void
01535 BinRep::put_tuple(List<BinRep> *L)
01536 {
01537 _destroy();
01538
01539 _fc = IEF_TUPLE_4;
01540 _len = 0;
01541 _u.L = L;
01542 }
01543
01544 void
01545 BinRep::put_set(Set<BinRep> *S)
01546 {
01547 _destroy();
01548
01549 _fc = IEF_SET_4;
01550 _len = 0;
01551 _u.S = S;
01552 }
01553
01554 void
01555 BinRep::put_map(Database<String,BinRep> *D)
01556 {
01557 p_abort( "not supported" );
01558
01559 _destroy();
01560
01561 _fc = IEF_MAP_4;
01562 _len = 0;
01563 _u.D = D;
01564 }
01565
01566 void
01567 BinRep::put_integer(const int x)
01568 {
01569 _destroy();
01570
01571 switch (bytes_per_value(x)) {
01572 case 1:
01573 {
01574 binptr_1 *value = (binptr_1 *)malloc(sizeof(binptr_1));
01575
01576 _fc = IEF_INTEGER_1;
01577 _len = sizeof( *value );
01578
01579 *value = (char) x;
01580 _u.C = (void *) value;
01581 break;
01582 }
01583
01584 case 2:
01585 {
01586 binptr_2 *value = (binptr_2 *)malloc(sizeof(binptr_2));
01587
01588 _fc = IEF_INTEGER_2;
01589 _len = sizeof( *value );
01590
01591 *value = (binptr_2) x;
01592 _u.C = (void *) value;
01593 break;
01594 }
01595
01596 case 4:
01597 {
01598 binptr_4 *value = (binptr_4 *)malloc(sizeof(binptr_4));
01599
01600 _fc = IEF_INTEGER_4;
01601 _len = sizeof( *value );
01602
01603 *value = (int) x;
01604 _u.C = (void *) value;
01605 break;
01606 }
01607 }
01608 }
01609
01610 void
01611 BinRep::put_boolean(const Boolean b)
01612 {
01613 _destroy();
01614
01615 _fc = (b ? IEF_TRUE : IEF_FALSE);
01616 _len = 0;
01617 _u.C = 0;
01618 }
01619
01620 void
01621 BinRep::put_string(const char *s, int length)
01622 {
01623 _destroy();
01624
01625 char *buffer = (char *)malloc((length + 1) * sizeof(char));
01626 BinPtr p( buffer );
01627
01628 p.store( s, length );
01629
01630 _fc = IEF_STRING_4;
01631 _len = length;
01632 _u.C = (void *) buffer;
01633 }
01634
01635 void
01636 BinRep::put_string(const String & s)
01637 {
01638 const char *p = (const char *) s;
01639 put_string( p, s.len() );
01640 }
01641
01642 void
01643 BinRep::put_string(const char *s)
01644 {
01645 put_string( s, strlen(s) );
01646 }
01647
01648 void
01649 BinRep::put_double(const double d)
01650 {
01651 _destroy();
01652
01653 double *value = (double *)malloc(sizeof(double));
01654
01655 *value = d;
01656
01657 _fc = IEF_REAL;
01658 _len = sizeof( *value );
01659
01660 _u.C = (void *) value;
01661 }
01662
01663
01664 Listable *
01665 BinRep::listable_clone() const
01666 {
01667 return new BinRep( *this );
01668 }
01669
01670 void
01671 BinRep::print(ostream & o) const
01672 {
01673 String str;
01674
01675 ascii_format( str );
01676 o << str;
01677 }
01678
01679 BinRep &
01680 BinRep::operator[] (int i) const
01681 {
01682 p_assert( is_tuple(), "not a tuple" );
01683
01684 List<BinRep> &L = to_tuple();
01685
01686 if (i >= 0 && L.entries() > i)
01687 return L[i];
01688
01689 return _omega();
01690 }
01691
01692 BinRep &
01693 BinRep::operator[] (const char *field) const
01694 {
01695 BinRep *b = find_ref( field );
01696
01697 return ( (b != 0) ? *b : _omega() );
01698 }
01699
01700 void
01701 BinRep::del(int i)
01702 {
01703 p_assert( is_tuple(), "not a tuple" );
01704
01705 List<BinRep> &L = to_tuple();
01706
01707 if (i >= 0 && L.entries() > i)
01708 L.del(i);
01709 }
01710
01711 void
01712 BinRep::del(const char *field)
01713 {
01714 p_assert( is_set() == True || is_map() == True, "not a set or map" );
01715
01716 if (is_set()) {
01717 for (Mutator<BinRep> iter = to_set(); iter.valid(); ++iter) {
01718 p_assert( iter.current().is_tuple(), "not a tuple" );
01719
01720 List<BinRep> &L = iter.current().to_tuple();
01721
01722 if (L.entries() == 2) {
01723 BinRep &key = L[0];
01724
01725 if (key.is_string()) {
01726 String key_string;
01727
01728 key.to_string( key_string );
01729 if (key_string == field) {
01730 iter.del();
01731 return;
01732 }
01733 }
01734 }
01735 }
01736 }
01737 else if (is_map()) {
01738 Database<String,BinRep> &D = to_map();
01739
01740 String s = field;
01741 BinRep *b = D.find_ref( s );
01742
01743 if (b != 0)
01744 D.del( s );
01745 }
01746 }
01747
01748 void
01749 BinRep::ins( BinRep *b )
01750 {
01751 if (is_tuple())
01752 to_tuple().ins_last( b );
01753 else if (is_set())
01754 to_set().ins( b );
01755 else {
01756 p_abort( "not a set or tuple" );
01757 }
01758 }
01759
01760 void
01761 BinRep::ins( const BinRep &b )
01762 {
01763 if (is_tuple())
01764 to_tuple().ins_last( new BinRep(b) );
01765 else if (is_set())
01766 to_set().ins( new BinRep(b) );
01767 else {
01768 p_abort( "not a set or tuple" );
01769 }
01770 }
01771
01772
01773 BinRep *
01774 BinRep::clone() const
01775 {
01776 return new BinRep( *this );
01777 }
01778
01779 BinRep *
01780 BinRep::find_ref(const char *field) const
01781 {
01782 p_assert( is_set() == True || is_map() == True, "not a set or map" );
01783
01784 if (is_set()) {
01785 for (Iterator<BinRep> iter = to_set(); iter.valid(); ++iter) {
01786 p_assert( iter.current().is_tuple(), "not a tuple" );
01787
01788 List<BinRep> &L = iter.current().to_tuple();
01789
01790 if (L.entries() == 2) {
01791 BinRep &key = L[0];
01792
01793 if (key.is_string()) {
01794 String key_string;
01795
01796 key.to_string( key_string );
01797 if (key_string == field)
01798 return &L[1];
01799 }
01800 }
01801 }
01802 }
01803 else if (is_map()) {
01804 Database<String,BinRep> &D = to_map();
01805
01806 String s = field;
01807 BinRep *b = D.find_ref( s );
01808
01809 if (b != 0)
01810 return b;
01811 }
01812
01813 return 0;
01814 }
01815
01816
01817
01818 static char *type_name[] = {
01819 "FT_OMEGA",
01820 "FT_ATOM",
01821 "FT_SHORT",
01822 "(Undefined)",
01823 "(Undefined)",
01824 "(Undefined)",
01825 "(Undefined)",
01826 "(Undefined)",
01827 "(Undefined)",
01828 "(Undefined)",
01829 "FT_DOUBLE",
01830 "FT_LONGINT",
01831 "FT_STRING",
01832 "FT_TUPLE",
01833 "(Undefined)",
01834 "FT_SET"
01835 };
01836
01837 static char *ief_type_name[] = {
01838 "IEF_OMEGA",
01839 "IEF_TRUE",
01840 "IEF_FALSE",
01841 "IEF_REAL",
01842 "IEF_INTEGER_1",
01843 "IEF_INTEGER_2",
01844 "IEF_INTEGER_4",
01845 "IEF_STRING_1",
01846 "IEF_STRING_2",
01847 "IEF_STRING_4",
01848 "IEF_TUPLE_1",
01849 "IEF_TUPLE_2",
01850 "IEF_TUPLE_4",
01851 "IEF_SET_1",
01852 "IEF_SET_2",
01853 "IEF_SET_4",
01854 "IEF_MAP_1",
01855 "IEF_MAP_2",
01856 "IEF_MAP_4",
01857 "IEF_DICT_1",
01858 "IEF_DICT_2",
01859 "IEF_DICT_4",
01860 };
01861
01862 char *
01863 binstr_type_name( BINSTR_TYPE expected_type )
01864 {
01865 int index = (int) expected_type;
01866
01867 if (index >= 0 && index <= 15)
01868 return type_name[index];
01869 else if (index >= 'A' && index <= 'Z')
01870 return ief_type_name[index - 'A'];
01871 else if (index == '$')
01872 return "IEF_HEADER";
01873 else if (index == '#')
01874 return "IEF_BODY";
01875
01876 return "(undefined error)";
01877 }
01878