00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 #include "w_defines.h"
00054 
00055 
00056 
00057 #ifdef __GNUC__
00058 #pragma implementation "vec_t.h"
00059 #endif
00060 
00061 #define VEC_T_C
00062 #include <cstdlib>
00063 #include <cstring>
00064 #include <w_stream.h>
00065 #include <w_base.h>
00066 #include <w_minmax.h>
00067 #include "basics.h"
00068 #include "vec_t.h"
00069 #include "umemcmp.h"
00070 
00071 
00072 #ifdef EXPLICIT_TEMPLATE
00073 
00074 
00075 template class w_auto_delete_array_t<cvec_t>;
00076 template class w_auto_delete_array_t<vec_t>;
00077 #endif
00078 
00079 
00080 
00081 cvec_t                cvec_t::pos_inf;
00082 cvec_t                cvec_t::neg_inf;
00083 CADDR_T               cvec_t::zero_location=(CADDR_T)&(cvec_t::neg_inf);
00084 vec_t&                vec_t::pos_inf = *(vec_t*) &cvec_t::pos_inf;
00085 vec_t&                vec_t::neg_inf = *(vec_t*) &cvec_t::neg_inf;
00086 
00087 cvec_t::cvec_t(const cvec_t& )
00088 {
00089     cerr << "cvec_t: disabled member called" << endl;
00090     cerr << "failed at \"" << __FILE__ << ":" << __LINE__ 
00091          << "\"" << endl;
00092     abort();
00093 }
00094 
00095 cvec_t::~cvec_t()
00096 {
00097     if (_is_large()) {
00098         free(_base);
00099     }
00100 }
00101 
00102 void cvec_t::split(size_t l1, cvec_t& v1, cvec_t& v2) const
00103 {
00104     size_t min = 0;
00105     int i;
00106     for (i = 0; i < _cnt; i++)  {
00107         if (l1 > 0)  {
00108             min = (_base[i].len > l1) ? l1 : _base[i].len;
00109             v1.put(_base[i].ptr, min);
00110             l1 -= min; 
00111         }
00112         if (l1 <= 0) break;
00113     }
00114     
00115     for ( ; i < _cnt; i++)  {
00116         v2.put(_base[i].ptr + min, _base[i].len - min);
00117         min = 0;
00118     }
00119 }
00120 
00121 cvec_t& cvec_t::put(const cvec_t& v, size_t start, size_t num_bytes)
00122 {
00123     int i;
00124     size_t start_byte, start_elem, total;
00125 
00126     if (v.size() < start+num_bytes) {
00127         w_assert3(v.size() >= start+num_bytes );
00128     }
00129 
00130     
00131     for (i = 0, total = 0; i < v._cnt && total <= start; i++) {
00132         total += v._base[i].len;
00133     }
00134    
00135     
00136     if (_cnt+v._cnt > max_small) {
00137         _grow(_cnt+v._cnt);
00138     }
00139 
00140     start_elem = i-1;
00141     
00142     start_byte = start - (total - v._base[start_elem].len);
00143 
00144     
00145     _base[_cnt].ptr = v._base[start_elem].ptr+start_byte;
00146     _base[_cnt].len = v._base[start_elem].len-start_byte;
00147     _cnt++;
00148     w_assert3(_cnt <= _max_cnt()); 
00149     for (i = 1, total = _base[_cnt-1].len; total < num_bytes; i++) {
00150         _base[_cnt].ptr = v._base[start_elem+i].ptr;
00151         _base[_cnt].len = v._base[start_elem+i].len;
00152         total += _base[_cnt++].len;
00153         w_assert3(_cnt <= _max_cnt()); 
00154     }
00155     _base[_cnt - 1].len -= total-num_bytes;
00156 
00157     _size += num_bytes;
00158     w_assert3(check_size());
00159     return *this;
00160 }
00161 
00162 cvec_t& cvec_t::put(const void* p, size_t l)  
00163 {
00164     if (_cnt+1 > max_small) {
00165         _grow(_cnt+1);
00166     }
00167 
00168     
00169     _base[_cnt].ptr = (unsigned char*)p; 
00170     _base[_cnt].len = l;
00171     if(l>0) {
00172         _cnt++;
00173            w_assert3(_cnt <= _max_cnt()); 
00174         _size += l;
00175     }
00176     return *this;
00177 }
00178 
00179 bool cvec_t::check_size() const
00180 {
00181     w_assert1(_size == recalc_size());
00182     return true;
00183 }
00184 
00185 size_t cvec_t::recalc_size() const 
00186 {
00187     
00188     size_t l;
00189     int i;
00190     for (i = 0, l = 0; i < _cnt; l += _base[i++].len) ;
00191     return l;
00192 }
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 const vec_t& vec_t::copy_from(
00202     const void* p,
00203     size_t limit,
00204     size_t offset)                 const
00205 {
00206     w_assert1(! is_pos_inf() && ! is_neg_inf() && !is_null() );
00207     w_assert1( _base[0].ptr != zero_location );
00208 
00209     char* s = (char*) p;
00210     for (int i = 0; (i < _cnt) && (limit>0); i++) {
00211         if ( offset < _base[i].len ) {
00212             size_t elemlen = ((_base[i].len - offset > limit)?
00213                                  limit : (_base[i].len - offset)) ;
00214             memcpy((char*)_base[i].ptr + offset, s, elemlen); 
00215             w_assert3(limit >= elemlen);
00216             limit -= elemlen;
00217             s += elemlen;
00218         } 
00219         if (_base[i].len > offset) {
00220             offset = 0;
00221         } else {
00222             offset -= _base[i].len;
00223         }
00224     }
00225     return *this;
00226 }
00227 
00228 
00229 size_t cvec_t::copy_to(void* p, size_t limit) const 
00230 {
00231     w_assert1(! is_pos_inf() && ! is_neg_inf() );
00232     char* s = (char*) p;
00233     for (int i = 0; i < _cnt && limit > 0; i++) {
00234         size_t n = limit > _base[i].len ? _base[i].len : limit;
00235         if(_base[i].ptr == zero_location) {
00236             memset(s, '\0', n);
00237         } else {
00238             memcpy(s, _base[i].ptr, n);
00239         }
00240         w_assert3(limit >= n);
00241         limit -= n;
00242         s += n;
00243     }
00244     return s - (char*)p;
00245 }
00246 
00247 
00248 vec_t& vec_t::copy_from(const cvec_t& s) 
00249 {
00250     bool        zeroing=false;
00251     int         j = 0;
00252     char*         p = (char*) _base[j].ptr;
00253     size_t         l = _base[j].len;
00254 
00255     w_assert1(size() >= s.size());
00256     w_assert1(_base[0].ptr != zero_location);
00257     
00258     for (int i = 0; i < s._cnt; i++)  {
00259         const unsigned char* pp = s._base[i].ptr;
00260         if(pp == zero_location) zeroing = true;
00261         size_t left = s._base[i].len;
00262         while (l <= left && j < _cnt)  {
00263             if( zeroing) {
00264                 memset(p, '\0', l);
00265             } else {
00266                 memcpy(p, pp, l);
00267             }
00268             pp += l;
00269             left -= l;
00270             j++;
00271             if (j >= _cnt) break;  
00272             l = _base[j].len;
00273             p = (char*) _base[j].ptr;
00274         }
00275         if (left)  {
00276             if( zeroing) {
00277                 memset(p, '\0', left);
00278             } else {
00279                 memcpy(p, pp, left);
00280             }
00281             pp += left;
00282             w_assert3(l >= left);
00283             l -= left;
00284         }
00285     }
00286     return *this;
00287 }
00288 
00289 vec_t& vec_t::copy_from(const cvec_t& ss, size_t offset, size_t limit, size_t myoffset)
00290 {
00291     bool        zeroing=false;
00292     vec_t s;
00293     s.put(ss, offset, limit);
00294 
00295     w_assert1(size() >= s.size());
00296     w_assert1(_base[0].ptr != zero_location);
00297 
00298     size_t ssz = s.size(), dsz = size();
00299     if (offset > ssz)                 offset = ssz;
00300     if (limit > ssz - offset)   limit = ssz - offset;
00301     if (myoffset > dsz)                offset = dsz;
00302 
00303     int j;
00304     for (j = 0; j < _cnt; j++)  {
00305         if (myoffset > _base[j].len)
00306             myoffset -= _base[j].len;
00307         else  
00308             break;
00309     }
00310     char* p = ((char*)_base[j].ptr) + myoffset;
00311     size_t l = _base[j].len - myoffset;
00312 
00313     w_assert1(dsz <= limit);
00314 
00315     size_t done;
00316     int i;
00317     for (i = 0, done = 0; i < s._cnt && done < limit; i++)  {
00318         const unsigned char* pp = s._base[i].ptr;
00319         if(pp == zero_location) zeroing = true;
00320         size_t left = s._base[i].len;
00321         if (limit - done < left)  left = limit - done;
00322         while (l < left)  {
00323             if(zeroing) {
00324                 memset(p, '\0', l);
00325             } else {
00326                 memcpy(p, pp, l);
00327             }
00328             done += l, pp += l;
00329             left -= l;
00330             j++;
00331             if (j >= _cnt) break;  
00332             l = _base[j].len;
00333             p = (char*) _base[j].ptr;
00334         }
00335         if (left)  {
00336             if(zeroing) {
00337                 memset(p, '\0', left);
00338             } else {
00339                 memcpy(p, pp, left);
00340             }
00341             pp += left;
00342             l -= left;
00343             done += left;
00344         }
00345     }
00346     return *this;
00347 }
00348 
00349 cvec_t& cvec_t::put(const cvec_t& v)
00350 {
00351     w_assert1(! is_pos_inf() && ! is_neg_inf());
00352     if (_cnt+v._cnt > max_small) {
00353         _grow(_cnt+v._cnt);
00354     }
00355     for (int i = 0; i < v._cnt; i++)  {
00356         _base[_cnt + i].ptr = v._base[i].ptr;
00357         _base[_cnt + i].len = v._base[i].len;
00358     }
00359     _cnt += v._cnt;
00360     w_assert3(_cnt <= _max_cnt()); 
00361     _size += v._size;
00362 
00363     w_assert3(check_size());
00364     return *this;
00365 }
00366 
00367 int cvec_t::cmp(const void* s, size_t l) const
00368 {
00369     if (is_pos_inf()) return 1;
00370     if (is_neg_inf()) return -1;
00371     if (is_null()) {
00372         if(l==0) return 0;
00373         
00374         return -1;
00375     }
00376 
00377     size_t acc = 0;
00378     for (int i = 0; i < _cnt && acc < l; i++)  {
00379         int d = umemcmp(_base[i].ptr, ((char*)s) + acc,
00380                        _base[i].len < l - acc ? _base[i].len : l - acc);
00381         if (d) return d;
00382         acc += _base[i].len;
00383     }
00384     return acc - l;        
00385 }
00386 
00387 int cvec_t::cmp(const cvec_t& v, size_t* common_size) const
00388 {
00389     
00390     
00391 
00392     
00393     if (&v == this) {        
00394         if (common_size) *common_size = v.size();
00395         return 0; 
00396     }
00397 
00398     
00399     if (is_null() && !v.is_null())  return -1;
00400     if (is_neg_inf() || v.is_pos_inf())  return -1;
00401     if (is_pos_inf() || v.is_neg_inf())  return 1;
00402 
00403         
00404     
00405     
00406     
00407     
00408     
00409     
00410     
00411 
00412     int result = 0;
00413 
00414     
00415     
00416 
00417     size_t l1 = size();
00418     size_t l2 = v.size();
00419     int i1 = 0;
00420     int i2 = 0;
00421     size_t j1 = 0, j2 = 0;
00422     
00423     while (l1 && l2)  {
00424         w_assert3(i1 < _cnt);
00425         w_assert3(i2 < v._cnt);
00426         size_t min = _base[i1].len - j1;
00427         if (v._base[i2].len - j2 < min)  min = v._base[i2].len - j2;
00428 
00429         w_assert3(min > 0);
00430         result = umemcmp(&_base[i1].ptr[j1], &v._base[i2].ptr[j2], min);
00431         if (result) break;
00432         
00433         if ((j1 += min) >= _base[i1].len)        { j1 = 0; ++i1; }
00434         if ((j2 += min) >= v._base[i2].len)        { j2 = 0; ++i2; }
00435 
00436         l1 -= min, l2 -= min;
00437     }
00438 
00439     if (result)  {
00440         if (common_size)  {
00441             while (_base[i1].ptr[j1] == v._base[i2].ptr[j2])  {
00442                 ++j1, ++j2;
00443                 --l1;
00444             }
00445             *common_size = (l1 < size() ? size() - l1 : 0);
00446         }
00447     } else {
00448         result = l1 - l2; 
00449         if (result && common_size)  {
00450             
00451             if (l1 == 0) {
00452                 *common_size = size();
00453             } else {
00454                 w_assert3(l2 == 0);
00455                 *common_size = v.size();
00456             }
00457             w_assert3(*common_size == MIN(size(), v.size()));
00458         }
00459     }
00460     return result;
00461 }
00462 
00463 int cvec_t::checksum() const 
00464 {
00465     int sum = 0;
00466     w_assert1(! is_pos_inf() && ! is_neg_inf());
00467     for (int i = 0; i < _cnt; i++) {
00468         for(size_t j=0; j<_base[i].len; j++) sum += ((char*)_base[i].ptr)[j];
00469     }
00470     return sum;
00471 }
00472 
00473 void cvec_t::calc_kvl(w_base_t::uint4_t& rh) const
00474 {
00475     if (size() <= sizeof(w_base_t::uint4_t))  {
00476         rh = 0;
00477         copy_to(&rh, size());
00478     } else {
00479         w_base_t::uint4_t h = 0;
00480         for (int i = 0; i < _cnt; i++)  {
00481             const unsigned char* s = _base[i].ptr;
00482             for (size_t j = 0; j < _base[i].len; j++)  {
00483                 if (h & 0xf8000000)  
00484                 {
00485                     h = (h & ~0xf8000000) + (h >> 27);
00486                 }
00487                 h = (h << 5) + *s++;
00488             }
00489         }
00490         rh = h;
00491     }
00492 }
00493 
00494 void cvec_t::_grow(int total_cnt)
00495 {
00496     w_assert3(total_cnt > max_small);
00497     w_assert3(_cnt <= _max_cnt()); 
00498 
00499     int prev_max = _max_cnt();
00500   
00501     if (total_cnt > prev_max) {
00502         
00503 
00504         int grow_to = MAX(prev_max*2, total_cnt);
00505         vec_pair_t* tmp = NULL;
00506 
00507         if (_is_large()) {
00508             tmp = (vec_pair_t*) realloc((char*)_base, grow_to * sizeof(*_base));
00509             if (!tmp) W_FATAL(fcOUTOFMEMORY);
00510         } else {
00511             tmp = (vec_pair_t*) malloc(grow_to * sizeof(*_base));
00512             if (!tmp) W_FATAL(fcOUTOFMEMORY);
00513             for (int i = 0; i < prev_max; i++) {
00514                 tmp[i] = _base[i];
00515             }
00516         }
00517         _pair[0].len = grow_to;
00518         _base = tmp;
00519     }
00520 }
00521 
00522 #include <cctype>
00523 
00524 ostream& operator<<(ostream& o, const cvec_t& v)
00525 {
00526     char        *p;
00527     u_char         c, oldc;
00528     int                repeated;
00529     int                nparts = v.count();
00530     int                i = 0;
00531     size_t        j = 0;
00532     size_t        l = 0;
00533 
00534     o << "{ ";
00535     for(i=0; i< nparts; i++) {
00536         
00537         l = (i < v._cnt) ? v._base[i].len : 0;
00538 
00539         
00540         p = (i < v._cnt) ? (char *)v._base[i].ptr : (char *)NULL; 
00541 
00542         o << "{" << l << " " << "\"" ;
00543 
00544         repeated=0;
00545         oldc = '\0';
00546         for(j=0; j<l; j++,p++) {
00547             c = *p;
00548             if(c == oldc) {
00549                 repeated++;
00550             } else {
00551                 if(repeated>0) {
00552                     o << "<" <<repeated << " times>";
00553                     repeated = 0;
00554                 }
00555                 if( c == '"' ) {
00556                     o << "\\\"" ;
00557                 } else if( isprint(c) ) {
00558                     if( isascii(c) ) {
00559                         o << c ;
00560                     } else {
00561                         
00562                         o << "\\0" << oct << c << dec ;
00563                     }
00564                 } else if(c=='\0') {
00565                     o << "\\0" ;
00566                 } else {
00567                     o << "\\0" << oct << (unsigned int)c << dec ;
00568                 }
00569             }
00570             oldc = c;
00571         }
00572         if(repeated>0) {
00573             o << "<" <<repeated << " times>";
00574             repeated = 0;
00575         }
00576         o <<"\" }";
00577         w_assert3(j==l);
00578         w_assert3(j==v._base[i].len);
00579     }
00580     o <<"}";
00581     return o;
00582 }
00583 
00584 istream& operator>>(istream& is, cvec_t& v)
00585 {
00586     char        c=' ';
00587     size_t      len=0;
00588     int         err = 0;
00589     char        *temp = 0;
00590     const char leftbracket='{';
00591     const char rightbracket='}';
00592 
00593     is.clear();
00594     v.reset();
00595 
00596     enum        {
00597         starting=0,
00598         getting_nparts, got_nparts,
00599         getting_pair, got_len,got_string,
00600         done
00601     } state;
00602 
00603     state = starting;
00604     while(state != done) {
00605         is >> ws; 
00606         c = is.peek();
00607         
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617         if(is.eof()) {
00618             err ++;
00619         } else {
00620             switch(state) {
00621             case done:
00622                 break;
00623 
00624             case starting:
00625                 if(c==leftbracket) {
00626                     is >> c;
00627                     state = getting_nparts;
00628                 } else err ++;
00629                 break;
00630 
00631             case getting_nparts:
00632                 is >> ws; 
00633                 if(is.bad()) { err ++; }
00634                 else state = got_nparts;
00635                 break;
00636 
00637             case got_nparts:
00638                 is >> ws; 
00639                 if(is.peek() == leftbracket) {
00640                     state = getting_pair;
00641                 } else {
00642                     err ++;
00643                 }
00644                 break;
00645 
00646             case getting_pair:
00647                 is >> ws; 
00648                 is >> c;
00649                 if( c == leftbracket ) {
00650                     is >> ws; 
00651                     is >> len; 
00652                     if(is.bad()) { 
00653                         err ++;
00654                     } else state = got_len;
00655                 } else if( c== rightbracket ) {
00656                     state = done;
00657                 } else {
00658                     err ++;
00659                 } 
00660                 break;
00661 
00662             case got_len:
00663                 if(c == '"') {
00664                     (void) is.get();
00665 
00666                     char *t;
00667                     
00668                     
00669                     temp = new char[len];
00670                     size_t j = 0;
00671                     for(t=temp; j<len; j++, t++) {
00672                         is >> *t;
00673                     }
00674                     state = got_string;
00675                     c = is.peek();
00676                 }
00677                 if(c != '"') {
00678                     err++;
00679                 } else {
00680                     (void) is.get();
00681                 }
00682                 break;
00683 
00684             case got_string:
00685                 is >> c; 
00686                 if(c != rightbracket ) {
00687                     err ++;
00688                 } else {
00689                     v.put(temp, len);
00690                     
00691                     
00692                     temp = 0;
00693                     len = 0;
00694                     state = getting_pair;
00695                 }
00696                 break;
00697 
00698             }
00699             
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708         }
00709         if(err >0) {
00710 #if defined(__SUNPRO_CC)
00711             
00712             is.clear(is.rdstate() | ios::badbit);
00713 #elif defined(__GNUC__)
00714 #if W_GCC_THIS_VER >= W_GCC_VER(3,0)
00715             
00716             is.setstate(ios::badbit);
00717 #else
00718             is.set(ios::badbit);
00719 #endif
00720 #else
00721             is.set(ios::badbit);
00722 #endif
00723 
00724             state = done;
00725             err = is.tellg();
00726             
00727         }
00728     }
00729     return is;
00730 }
00731 
00732