00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include <stdlib.h>
00025 #include <ctype.h>
00026
00027 #include "clib.h"
00028 #include "WordKey.h"
00029 #include "ber.h"
00030 #include "HtMaxMin.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 int WordKey::Equal(const WordKey& other) const
00047 {
00048 const WordKeyInfo& info = context->GetKeyInfo();
00049
00050
00051
00052
00053 for(int j = 0; j < info.nfields; j++)
00054 {
00055
00056
00057
00058 if(!IsDefined(j) || !other.IsDefined(j)) continue;
00059
00060 if(Get(j) != other.Get(j)) return 0;
00061 }
00062 return 1;
00063 }
00064
00065 int
00066 WordKey::Cmp(const WordKey& other) const
00067 {
00068 const WordKeyInfo& info = context->GetKeyInfo();
00069
00070 for(int j = 0; j < info.nfields; j++) {
00071 if(!IsDefined(j) || !other.IsDefined(j)) continue;
00072
00073 if(Get(j) != other.Get(j)) {
00074 return Get(j) > other.Get(j) ? 1 : -1;
00075 }
00076 }
00077 return 0;
00078 }
00079
00080
00081
00082
00083
00084 int
00085 WordKey::Compare(WordContext* context, const unsigned char *a, int a_length, const unsigned char *b, int b_length)
00086 {
00087 const WordKeyInfo& info = context->GetKeyInfo();
00088 int bytes;
00089 ber_t a_value;
00090 ber_t b_value;
00091
00092 for(int j = 0; j < info.nfields; j++) {
00093 if((bytes = ber_buf2value(a, a_length, a_value)) < 1) {
00094 fprintf(stderr, "WordKey::Compare: failed to retrieve field %d for a\n", j);
00095 abort();
00096 }
00097 a += bytes;
00098 a_length -= bytes;
00099 if((bytes = ber_buf2value(b, b_length, b_value)) < 1) {
00100 fprintf(stderr, "WordKey::Compare: failed to retrieve field %d for b\n", j);
00101 abort();
00102 }
00103 b += bytes;
00104 b_length -= bytes;
00105
00106 if(a_value != b_value)
00107 return a_value > b_value ? 1 : -1;
00108 }
00109
00110
00111
00112
00113 return 0;
00114 }
00115
00116
00117
00118
00119
00120 int
00121 WordKey::Compare(WordContext* context, const String& a, const String& b)
00122 {
00123 return WordKey::Compare(context, (const unsigned char*)a, a.length(), (const unsigned char*)b, b.length());
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 int
00133 word_db_cmp(const DBT *a, const DBT *b)
00134 {
00135 WordContext* context = (WordContext*)a->app_private;
00136 if(context == 0) {
00137 fprintf(stderr, "word_db_cmp: null context\n");
00138 abort();
00139 }
00140 return WordKey::Compare(context, (const unsigned char*)a->data, a->size, (const unsigned char*)b->data, b->size);
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150 int WordKey::Diff(const WordKey& other, int& position, int& lower)
00151 {
00152 position = -1;
00153
00154 int nfields=WordKey::NFields();
00155
00156 int i;
00157 for(i = 0; i < nfields; i++) {
00158 if(IsDefined(i) && other.IsDefined(i) &&
00159 Get(i) != other.Get(i)) {
00160 lower = Get(i) < other.Get(i);
00161 break;
00162 }
00163 }
00164 if(i < nfields)
00165 position = i;
00166
00167 return position >= 0;
00168 }
00169
00170
00171
00172
00173 int
00174 WordKey::PackEqual(const WordKey& other) const
00175 {
00176 String this_pack;
00177 Pack(this_pack);
00178
00179 String other_pack;
00180 other.Pack(other_pack);
00181
00182 return this_pack == other_pack;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 int WordKey::SetToFollowing(int position )
00213 {
00214 if(position == WORD_FOLLOWING_MAX)
00215 position = NFields() - 1;
00216
00217 if(position < 0 || position >= NFields()) {
00218 fprintf(stderr, "WordKey::SetToFollowing invalid position = %d\n", position);
00219 return NOTOK;
00220 }
00221
00222 int i = position;
00223 while(i >= 0) {
00224 if(IsDefined(i)) {
00225 if(Overflow(i, 1))
00226 Set(i, 0);
00227 else
00228 break;
00229 }
00230 i--;
00231 }
00232
00233 if(i < 0) {
00234 fprintf(stderr, "WordKey::SetToFollowing cannot increment\n");
00235 return NOTOK;
00236 }
00237
00238 Get(i)++;
00239
00240 for(i = position + 1; i < NFields(); i++)
00241 if(IsDefined(i)) Set(i,0);
00242
00243 return OK;
00244 }
00245
00246 int
00247 WordKey::Prefix() const
00248 {
00249 const WordKeyInfo& info = context->GetKeyInfo();
00250
00251
00252
00253
00254 if(Filled()) return OK;
00255
00256
00257
00258 if(!IsDefined(0)) return NOTOK;
00259
00260 int found_unset = 0;
00261
00262 for(int j = 0; j < info.nfields; j++) {
00263
00264
00265
00266 if(IsDefined(j)) {
00267 if(found_unset) return NOTOK;
00268 } else {
00269
00270
00271
00272
00273 found_unset++;
00274 }
00275 }
00276
00277 return OK;
00278 }
00279
00280
00281
00282
00283
00284
00285 int
00286 WordKey::PrefixOnly()
00287 {
00288 const WordKeyInfo& info = context->GetKeyInfo();
00289
00290
00291
00292 if(Filled()) return OK;
00293
00294
00295
00296 if(!IsDefined(0))
00297 return NOTOK;
00298
00299 int found_unset = 0;
00300
00301
00302
00303
00304 for(int j = 0; j < info.nfields; j++) {
00305
00306
00307
00308 if(IsDefined(j)) {
00309 if(found_unset) {
00310 Set(j,0);
00311 Undefined(j);
00312 }
00313 } else {
00314 found_unset = 1;
00315 }
00316 }
00317
00318 return OK;
00319 }
00320
00321
00322
00323
00324 int
00325 WordKey::Unpack(const char* string, int length)
00326 {
00327 const WordKeyInfo& info = context->GetKeyInfo();
00328
00329 const unsigned char* p = (const unsigned char*)string;
00330 int p_length = length;
00331 ber_t value;
00332
00333 for(int j = 0; j < info.nfields; j++) {
00334 int bytes = ber_buf2value(p, p_length, value);
00335 if(bytes < 1) {
00336 fprintf(stderr, "WordKey::Unpack: ber_buf2value failed at %d\n", j);
00337 return NOTOK;
00338 }
00339 p_length -= bytes;
00340 if(p_length < 0) {
00341 fprintf(stderr, "WordKey::Unpack: ber_buf2value overflow at %d\n", j);
00342 return NOTOK;
00343 }
00344 p += bytes;
00345 Set(j, value);
00346 }
00347
00348 return OK;
00349 }
00350
00351
00352
00353
00354 int
00355 WordKey::Pack(String& packed) const
00356 {
00357 const WordKeyInfo& info = context->GetKeyInfo();
00358
00359 unsigned char* string;
00360
00361
00362
00363 int length = BER_MAX_BYTES * info.nfields;
00364
00365 if((string = (unsigned char*)malloc(length)) == 0) {
00366 fprintf(stderr, "WordKey::Pack: malloc returned 0\n");
00367 return NOTOK;
00368 }
00369
00370 unsigned char* p = string;
00371 int p_length = length;
00372
00373 for(int i = 0; i < info.nfields; i++) {
00374 int bytes = ber_value2buf(p, p_length, Get(i));
00375 if(bytes < 1) {
00376 fprintf(stderr, "WordKey::Pack: ber_value2buf failed at %d\n", i);
00377 return NOTOK;
00378 }
00379 p_length -= bytes;
00380 if(p_length < 0) {
00381 fprintf(stderr, "WordKey::Pack: ber_value2buf overflow at %d\n", i);
00382 return NOTOK;
00383 }
00384 p += bytes;
00385 }
00386
00387 packed.set((const char*)string, p - string);
00388
00389 free(string);
00390
00391 return OK;
00392 }
00393
00394
00395
00396
00397
00398 int WordKey::Merge(const WordKey& other)
00399 {
00400 const WordKeyInfo& info = context->GetKeyInfo();
00401
00402 for(int j = 0; j < info.nfields; j++) {
00403 if(!IsDefined(j) && other.IsDefined(j)) {
00404 Set(j,other.Get(j));
00405 }
00406 }
00407
00408 return OK;
00409 }
00410
00411
00412
00413
00414 int
00415 WordKey::Get(String& buffer) const
00416 {
00417 buffer.trunc();
00418 const WordKeyInfo& info = context->GetKeyInfo();
00419
00420
00421
00422
00423
00424 for(int j = 0; j < info.nfields; j++) {
00425 if(!IsDefined(j)) {
00426 buffer << "<UNDEF>";
00427 } else {
00428 buffer << Get(j);
00429 }
00430 buffer << "\t";
00431 }
00432 return OK;
00433 }
00434
00435 String
00436 WordKey::Get() const
00437 {
00438 String tmp;
00439 Get(tmp);
00440 return tmp;
00441 }
00442
00443
00444
00445
00446 int
00447 WordKey::Set(const String& buffer)
00448 {
00449 StringList fields(buffer, "\t ");
00450 return SetList(fields);
00451 }
00452
00453
00454
00455
00456 int
00457 WordKey::SetList(StringList& fields)
00458 {
00459 const WordKeyInfo& info = context->GetKeyInfo();
00460 int length = fields.Count();
00461
00462 if(length < info.nfields) {
00463 fprintf(stderr, "WordKey::SetList: expected at least %d fields and found %d (ignored)\n", info.nfields, length);
00464 return NOTOK;
00465 }
00466 if(length < 1) {
00467 fprintf(stderr, "WordKey::SetList: expected at least one field in line\n");
00468 return NOTOK;
00469 }
00470
00471 Clear();
00472
00473
00474
00475
00476 int i;
00477 for(i = 0; i < info.nfields; i++) {
00478 String* field = (String*)fields.Get_First();
00479
00480 if(field == 0) {
00481 fprintf(stderr, "WordKey::Set: failed to retrieve field %d\n", i);
00482 return NOTOK;
00483 }
00484
00485 if(field->nocase_compare("<undef>") == 0) {
00486 Undefined(i);
00487 } else {
00488 WordKeyNum value = strtoul(field->get(), 0, 10);
00489 Set(i, value);
00490 }
00491 fields.Remove(0);
00492 }
00493
00494 return OK;
00495 }
00496
00497 int WordKey::Write(FILE* f) const
00498 {
00499 String tmp;
00500 Get(tmp);
00501 fprintf(f, "%s", (char*)tmp);
00502 return 0;
00503 }
00504
00505 void WordKey::Print() const
00506 {
00507 Write(stderr);
00508 }
00509