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