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 #include <ncbi_pch.hpp>
00033 #include <corelib/ncbi_bswap.hpp>
00034 #include <db/bdb/bdb_types.hpp>
00035 #include <db.h>
00036
00037 BEGIN_NCBI_SCOPE
00038
00039
00040 static
00041 const unsigned char* s_GetLString(const unsigned char* str,
00042 bool check_legacy,
00043 int* str_len)
00044 {
00045 _ASSERT(str);
00046 _ASSERT(str_len);
00047
00048
00049 *str_len = (str[0]) |
00050 (str[1] << 8) |
00051 (str[2] << 16) |
00052 (str[3] << 24);
00053
00054 if (check_legacy) {
00055 if (*str_len < 0) {
00056 *str_len = -(*str_len);
00057 str += 4;
00058 } else {
00059 *str_len = ::strlen((const char*)str);
00060 }
00061 } else {
00062 if (*str_len <= 0) {
00063 *str_len = -(*str_len);
00064 str += 4;
00065 } else {
00066 _ASSERT(0);
00067 }
00068 }
00069
00070 return str;
00071
00072 }
00073
00074 static
00075 const unsigned char* s_GetLString(const DBT* val,
00076 bool check_legacy,
00077 int* str_len)
00078 {
00079 const unsigned char* str = (const unsigned char*)val->data;
00080
00081 if (val->size <= 4) {
00082 _ASSERT(check_legacy);
00083 *str_len = ::strlen((const char*)str);
00084 return str;
00085 }
00086
00087 return s_GetLString(str, check_legacy, str_len);
00088 }
00089
00090
00091
00092 extern "C"
00093 {
00094
00095
00096
00097
00098
00099 int BDB_UintCompare(DB* db, const DBT* val1, const DBT* val2)
00100 {
00101 return BDB_Uint4Compare(db, val1, val2);
00102 }
00103
00104 int BDB_Uint4Compare(DB*, const DBT* val1, const DBT* val2)
00105 {
00106 Uint4 v1, v2;
00107 #ifdef HAVE_UNALIGNED_READS
00108 v1 = *((Uint4*) val1->data);
00109 v2 = *((Uint4*) val2->data);
00110 #else
00111 ::memcpy(&v1, val1->data, sizeof(Uint4));
00112 ::memcpy(&v2, val2->data, sizeof(Uint4));
00113 #endif
00114 return (v1 < v2) ? -1
00115 : ((v2 < v1) ? 1 : 0);
00116 }
00117
00118 int BDB_Int8Compare(DB*, const DBT* val1, const DBT* val2)
00119 {
00120 Int8 v1, v2;
00121 #ifdef HAVE_UNALIGNED_READS
00122 v1 = *((Int8*) val1->data);
00123 v2 = *((Int8*) val2->data);
00124 #else
00125 ::memcpy(&v1, val1->data, sizeof(Int8));
00126 ::memcpy(&v2, val2->data, sizeof(Int8));
00127 #endif
00128 return (v1 < v2) ? -1
00129 : ((v2 < v1) ? 1 : 0);
00130 }
00131
00132 int BDB_Uint8Compare(DB*, const DBT* val1, const DBT* val2)
00133 {
00134 Uint8 v1, v2;
00135 #ifdef HAVE_UNALIGNED_READS
00136 v1 = *((Uint8*) val1->data);
00137 v2 = *((Uint8*) val2->data);
00138 #else
00139 ::memcpy(&v1, val1->data, sizeof(Uint8));
00140 ::memcpy(&v2, val2->data, sizeof(Uint8));
00141 #endif
00142 return (v1 < v2) ? -1
00143 : ((v2 < v1) ? 1 : 0);
00144 }
00145
00146 int BDB_IntCompare(DB* db, const DBT* val1, const DBT* val2)
00147 {
00148 return BDB_Int4Compare(db, val1, val2);
00149 }
00150
00151 int BDB_Int4Compare(DB*, const DBT* val1, const DBT* val2)
00152 {
00153 Int4 v1, v2;
00154 #ifdef HAVE_UNALIGNED_READS
00155 v1 = *((Int4*) val1->data);
00156 v2 = *((Int4*) val2->data);
00157 #else
00158 ::memcpy(&v1, val1->data, sizeof(Int4));
00159 ::memcpy(&v2, val2->data, sizeof(Int4));
00160 #endif
00161 return (v1 < v2) ? -1
00162 : ((v2 < v1) ? 1 : 0);
00163 }
00164
00165 int BDB_Int2Compare(DB*, const DBT* val1, const DBT* val2)
00166 {
00167 Int2 v1, v2;
00168 #ifdef HAVE_UNALIGNED_READS
00169 v1 = *((Int2*) val1->data);
00170 v2 = *((Int2*) val2->data);
00171 #else
00172 ::memcpy(&v1, val1->data, sizeof(Int2));
00173 ::memcpy(&v2, val2->data, sizeof(Int2));
00174 #endif
00175 return (v1 < v2) ? -1
00176 : ((v2 < v1) ? 1 : 0);
00177 }
00178
00179 int BDB_Uint2Compare(DB*, const DBT* val1, const DBT* val2)
00180 {
00181 Uint2 v1, v2;
00182 #ifdef HAVE_UNALIGNED_READS
00183 v1 = *((Uint2*) val1->data);
00184 v2 = *((Uint2*) val2->data);
00185 #else
00186 ::memcpy(&v1, val1->data, sizeof(Uint2));
00187 ::memcpy(&v2, val2->data, sizeof(Uint2));
00188 #endif
00189 return (v1 < v2) ? -1
00190 : ((v2 < v1) ? 1 : 0);
00191 }
00192
00193 int BDB_CharCompare(DB*, const DBT* val1, const DBT* val2)
00194 {
00195 const char& v1=*static_cast<char*>(val1->data);
00196 const char& v2=*static_cast<char*>(val2->data);
00197
00198 return (v1 < v2) ? -1
00199 : ((v2 < v1) ? 1 : 0);
00200 }
00201
00202 int BDB_UCharCompare(DB*, const DBT* val1, const DBT* val2)
00203 {
00204 const unsigned char& v1=*static_cast<unsigned char*>(val1->data);
00205 const unsigned char& v2=*static_cast<unsigned char*>(val2->data);
00206
00207 return (v1 < v2) ? -1
00208 : ((v2 < v1) ? 1 : 0);
00209 }
00210
00211 int BDB_FloatCompare(DB*, const DBT* val1, const DBT* val2)
00212 {
00213 float v1, v2;
00214 #ifdef HAVE_UNALIGNED_READS
00215 v1 = *((float*) val1->data);
00216 v2 = *((float*) val2->data);
00217 #else
00218 ::memcpy(&v1, val1->data, sizeof(v1));
00219 ::memcpy(&v2, val2->data, sizeof(v2));
00220 #endif
00221 return (v1 < v2) ? -1
00222 : ((v2 < v1) ? 1 : 0);
00223 }
00224
00225 int BDB_DoubleCompare(DB*, const DBT* val1, const DBT* val2)
00226 {
00227 double v1, v2;
00228 #ifdef HAVE_UNALIGNED_READS
00229 v1 = *((double*) val1->data);
00230 v2 = *((double*) val2->data);
00231 #else
00232 ::memcpy(&v1, val1->data, sizeof(v1));
00233 ::memcpy(&v2, val2->data, sizeof(v2));
00234 #endif
00235 return (v1 < v2) ? -1
00236 : ((v2 < v1) ? 1 : 0);
00237 }
00238
00239 int BDB_StringCompare(DB*, const DBT* val1, const DBT* val2)
00240 {
00241 return ::strcmp((const char*)val1->data, (const char*)val2->data);
00242 }
00243
00244 int BDB_FixedByteStringCompare(DB* db, const DBT* val1, const DBT* val2)
00245 {
00246 _ASSERT(val1->size == val2->size);
00247
00248 int r = ::memcmp(val1->data, val2->data, val1->size);
00249 return r;
00250 }
00251
00252
00253
00254 int BDB_LStringCompare(DB* db, const DBT* val1, const DBT* val2)
00255 {
00256 const CBDB_BufferManager* fbuf1 =
00257 static_cast<CBDB_BufferManager*> (db->app_private);
00258
00259 bool check_legacy = fbuf1->IsLegacyStrings();
00260
00261 const unsigned char* str1;
00262 const unsigned char* str2;
00263 int str_len1;
00264 int str_len2;
00265
00266 str1 = s_GetLString(val1, check_legacy, &str_len1);
00267 str2 = s_GetLString(val2, check_legacy, &str_len2);
00268
00269 int cmp_len = min(str_len1, str_len2);
00270 int r = ::memcmp(str1, str2, cmp_len);
00271 if (r == 0) {
00272 return (str_len1 < str_len2) ? -1
00273 : ((str_len2 < str_len1) ? 1 : 0);
00274 }
00275 return r;
00276 }
00277
00278
00279 int BDB_StringCaseCompare(DB*, const DBT* val1, const DBT* val2)
00280 {
00281 return NStr::strcasecmp((const char*)val1->data, (const char*)val2->data);
00282 }
00283
00284 int BDB_Compare(DB* db, const DBT* val1, const DBT* val2)
00285 {
00286 const CBDB_BufferManager* fbuf1 =
00287 static_cast<CBDB_BufferManager*> (db->app_private);
00288
00289 bool byte_swapped = fbuf1->IsByteSwapped();
00290
00291 _ASSERT(fbuf1);
00292
00293 const char* p1 = static_cast<char*> (val1->data);
00294 const char* p2 = static_cast<char*> (val2->data);
00295
00296 unsigned int cmp_limit = fbuf1->GetFieldCompareLimit();
00297 if (cmp_limit == 0) {
00298 cmp_limit = fbuf1->FieldCount();
00299 } else {
00300 _ASSERT(cmp_limit <= fbuf1->FieldCount());
00301 }
00302
00303 for (unsigned int i = 0; i < cmp_limit; ++i) {
00304 const CBDB_Field& fld1 = fbuf1->GetField(i);
00305 int ret = fld1.Compare(p1, p2, byte_swapped);
00306 if ( ret )
00307 return ret;
00308
00309 p1 += fld1.GetDataLength(p1);
00310 p2 += fld1.GetDataLength(p2);
00311 }
00312
00313 return 0;
00314 }
00315
00316
00317
00318 unsigned int
00319 BDB_Hash(DB *, const void *bytes, unsigned length)
00320 {
00321 const unsigned char* buf = (const unsigned char*)bytes;
00322 const unsigned char* buf_end = buf + length;
00323
00324
00325 unsigned ha = 0;
00326 for (; buf != buf_end; ++buf) {
00327 ha = ((ha << 4) + ha) + *buf;
00328 }
00329 return ha;
00330 }
00331
00332 unsigned int
00333 BDB_Uint4Hash(DB *db, const void *bytes, unsigned length)
00334 {
00335 if (length == 4) {
00336 unsigned ha;
00337 ::memcpy(&ha, bytes, 4);
00338 return ha;
00339 } else {
00340 return BDB_Hash(db, bytes, length);
00341 }
00342 }
00343
00344
00345
00346 int BDB_ByteSwap_UintCompare(DB* db, const DBT* val1, const DBT* val2)
00347 {
00348 return BDB_ByteSwap_Uint4Compare(db, val1, val2);
00349 }
00350
00351 int BDB_ByteSwap_Uint4Compare(DB*, const DBT* val1, const DBT* val2)
00352 {
00353 unsigned int v1, v2;
00354 v1 = (unsigned int) CByteSwap::GetInt4((unsigned char*)val1->data);
00355 v2 = (unsigned int) CByteSwap::GetInt4((unsigned char*)val2->data);
00356 return (v1 < v2) ? -1
00357 : ((v2 < v1) ? 1 : 0);
00358 }
00359
00360 int BDB_ByteSwap_Int8Compare(DB*, const DBT* val1, const DBT* val2)
00361 {
00362 Int8 v1, v2;
00363 v1 = CByteSwap::GetInt8((unsigned char*)val1->data);
00364 v2 = CByteSwap::GetInt8((unsigned char*)val2->data);
00365 return (v1 < v2) ? -1
00366 : ((v2 < v1) ? 1 : 0);
00367 }
00368
00369 int BDB_ByteSwap_Uint8Compare(DB*, const DBT* val1, const DBT* val2)
00370 {
00371 Uint8 v1, v2;
00372 v1 = CByteSwap::GetInt8((unsigned char*)val1->data);
00373 v2 = CByteSwap::GetInt8((unsigned char*)val2->data);
00374 return (v1 < v2) ? -1
00375 : ((v2 < v1) ? 1 : 0);
00376 }
00377
00378 int BDB_ByteSwap_IntCompare(DB* db, const DBT* val1, const DBT* val2)
00379 {
00380 return BDB_ByteSwap_Int4Compare(db, val1, val2);
00381 }
00382
00383 int BDB_ByteSwap_Int4Compare(DB*, const DBT* val1, const DBT* val2)
00384 {
00385 int v1, v2;
00386 v1 = CByteSwap::GetInt4((unsigned char*)val1->data);
00387 v2 = CByteSwap::GetInt4((unsigned char*)val2->data);
00388 return (v1 < v2) ? -1
00389 : ((v2 < v1) ? 1 : 0);
00390 }
00391
00392 int BDB_ByteSwap_Int2Compare(DB*, const DBT* val1, const DBT* val2)
00393 {
00394 Int2 v1, v2;
00395 v1 = CByteSwap::GetInt2((unsigned char*)val1->data);
00396 v2 = CByteSwap::GetInt2((unsigned char*)val2->data);
00397 return (v1 < v2) ? -1
00398 : ((v2 < v1) ? 1 : 0);
00399 }
00400
00401 int BDB_ByteSwap_Uint2Compare(DB*, const DBT* val1, const DBT* val2)
00402 {
00403 Uint2 v1, v2;
00404 v1 = CByteSwap::GetInt2((unsigned char*)val1->data);
00405 v2 = CByteSwap::GetInt2((unsigned char*)val2->data);
00406 return (v1 < v2) ? -1
00407 : ((v2 < v1) ? 1 : 0);
00408 }
00409
00410
00411 int BDB_ByteSwap_FloatCompare(DB*, const DBT* val1, const DBT* val2)
00412 {
00413 float v1, v2;
00414 v1 = CByteSwap::GetFloat((unsigned char*)val1->data);
00415 v2 = CByteSwap::GetFloat((unsigned char*)val2->data);
00416 return (v1 < v2) ? -1
00417 : ((v2 < v1) ? 1 : 0);
00418 }
00419
00420
00421 int BDB_ByteSwap_DoubleCompare(DB*, const DBT* val1, const DBT* val2)
00422 {
00423 double v1, v2;
00424 v1 = CByteSwap::GetDouble((unsigned char*)val1->data);
00425 v2 = CByteSwap::GetDouble((unsigned char*)val2->data);
00426 return (v1 < v2) ? -1
00427 : ((v2 < v1) ? 1 : 0);
00428
00429 }
00430
00431
00432
00433
00434 }
00435
00436
00437
00438
00439
00440 IBDB_Field::~IBDB_Field()
00441 {
00442 }
00443
00444
00445
00446
00447
00448 CBDB_Field::CBDB_Field(ELengthType length_type)
00449 : m_BufferManager(0),
00450 m_Buffer(0),
00451 m_BufferSize(0),
00452 m_BufferIdx(0)
00453 {
00454 m_Flags.VariableLength = (length_type == eFixedLength) ? 0 : 1;
00455 m_Flags.Attached = 0;
00456 m_Flags.Nullable = 0;
00457 }
00458
00459 BDB_CompareFunction
00460 CBDB_Field::GetCompareFunction(bool ) const
00461 {
00462 return BDB_Compare;
00463 }
00464
00465
00466 size_t CBDB_Field::GetExtraDataLength()
00467 {
00468 return 0;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 CBDB_BufferManager::CBDB_BufferManager()
00478 : m_Buffer(0),
00479 m_BufferSize(0),
00480 m_PackedSize(0),
00481 m_DBT_Size(0),
00482 m_Packable(false),
00483 m_ByteSwapped(false),
00484 m_Nullable(false),
00485 m_NullSetSize(0),
00486 m_CompareLimit(0),
00487 m_LegacyString(false),
00488 m_OwnFields(false),
00489 m_PackOptComputed(false),
00490 m_FirstVarFieldIdx(0),
00491 m_FirstVarFieldIdxOffs(0)
00492 {
00493 }
00494
00495 CBDB_BufferManager::~CBDB_BufferManager()
00496 {
00497 delete [] m_Buffer;
00498
00499 if (m_OwnFields) {
00500 for (size_t i = 0; i < m_Fields.size(); ++i) {
00501 CBDB_Field* field = m_Fields[i];
00502 delete field;
00503 }
00504 }
00505 }
00506
00507 void CBDB_BufferManager::Bind(CBDB_Field* field, ENullable is_nullable)
00508 {
00509 m_Fields.push_back(field);
00510 m_Ptrs.push_back(0);
00511
00512 unsigned field_idx = (unsigned)(m_Fields.size() - 1);
00513 field->SetBufferIdx(field_idx);
00514
00515 if ( !m_Packable ) {
00516
00517 m_Packable = field->IsVariableLength();
00518 }
00519
00520 if (is_nullable == eNullable)
00521 field->SetNullable();
00522 }
00523
00524 int CBDB_BufferManager::GetFieldIndex(const string& name) const
00525 {
00526 for (size_t i = 0; i < m_Fields.size(); ++i) {
00527 const CBDB_Field& field = *m_Fields[i];
00528 const string& fname = field.GetName();
00529 if (NStr::CompareNocase(name, fname) == 0) {
00530 return i;
00531 }
00532 }
00533 return -1;
00534 }
00535
00536 size_t CBDB_BufferManager::ComputeBufferSize() const
00537 {
00538 size_t buf_len = 0;
00539 for (size_t i = 0; i < m_Fields.size(); ++i) {
00540 const CBDB_Field& field = *m_Fields[i];
00541 buf_len += field.GetBufferSize();
00542 }
00543 return buf_len;
00544 }
00545
00546
00547 void CBDB_BufferManager::CheckNullConstraint() const
00548 {
00549 if ( !IsNullable() )
00550 return;
00551
00552 for (size_t i = 0; i < m_Fields.size(); ++i) {
00553 const CBDB_Field& fld = *m_Fields[i];
00554 if (!fld.IsNullable() && TestNullBit((unsigned)i)) {
00555 string message("NULL field in database operation.");
00556 const string& field_name = fld.GetName();
00557 if ( !field_name.empty() ) {
00558 message.append("(Field:");
00559 message.append(field_name);
00560 message.append(")");
00561 }
00562 BDB_THROW(eNull, message);
00563 }
00564 }
00565 }
00566
00567
00568 void CBDB_BufferManager::Construct()
00569 {
00570 _ASSERT(m_Fields.size());
00571
00572
00573 m_BufferSize = ComputeBufferSize();
00574
00575 if ( IsNullable() ) {
00576 m_NullSetSize = ComputeNullSetSize();
00577 m_BufferSize += m_NullSetSize;
00578 }
00579
00580 delete [] m_Buffer; m_Buffer = 0;
00581 m_Buffer = new char[m_BufferSize];
00582 ::memset(m_Buffer, 0, m_BufferSize);
00583
00584
00585 char* buf_ptr = (char*) m_Buffer;
00586 buf_ptr += m_NullSetSize;
00587
00588 for (size_t i = 0; i < m_Fields.size(); ++i) {
00589 CBDB_Field& df = *m_Fields[i];
00590 m_Ptrs[i] = buf_ptr;
00591
00592 df.SetBufferManager(this);
00593 df.SetBuffer(buf_ptr);
00594
00595 buf_ptr += df.GetBufferSize();
00596 }
00597
00598 m_PackedSize = 0;
00599 }
00600
00601
00602 BDB_CompareFunction
00603 CBDB_BufferManager::GetCompareFunction() const
00604 {
00605 if (m_Fields.size() > 1)
00606 return BDB_Compare;
00607 bool byte_swapped = IsByteSwapped();
00608 return m_Fields[0]->GetCompareFunction(byte_swapped);
00609 }
00610
00611
00612 BDB_HashFunction
00613 CBDB_BufferManager::GetHashFunction() const
00614 {
00615 return BDB_Hash;
00616 }
00617
00618
00619 void CBDB_BufferManager::ArrangePtrsPacked()
00620 {
00621 _ASSERT(m_Fields.size());
00622
00623 if ( !IsPackable() ) {
00624 m_PackedSize = m_BufferSize;
00625 return;
00626 }
00627
00628 char* buf_ptr = m_Buffer;
00629 buf_ptr += m_NullSetSize;
00630 m_PackedSize = m_NullSetSize;
00631
00632 for (size_t i = 0; i < m_Fields.size(); ++i) {
00633 CBDB_Field& df = *m_Fields[i];
00634 df.SetBuffer(buf_ptr);
00635 size_t len = df.GetDataLength(buf_ptr);
00636 buf_ptr += len;
00637 m_PackedSize += len;
00638 }
00639 }
00640
00641 void CBDB_BufferManager::x_ComputePackOpt()
00642 {
00643 unsigned int offset = m_NullSetSize;
00644
00645 for (TFieldVector::size_type i = 0; i < m_Fields.size(); ++i) {
00646 CBDB_Field& df = *m_Fields[i];
00647
00648 if (df.IsVariableLength()) {
00649 m_FirstVarFieldIdx = i;
00650 break;
00651 }
00652
00653 size_t actual_len = df.GetLength();
00654 offset += actual_len;
00655 }
00656
00657 m_FirstVarFieldIdxOffs = offset;
00658 m_PackOptComputed = true;
00659 }
00660
00661
00662 unsigned int CBDB_BufferManager::Pack()
00663 {
00664 _ASSERT(m_Fields.size());
00665 if (m_PackedSize != 0)
00666 return (unsigned)m_PackedSize;
00667 if ( !IsPackable() ) {
00668 m_PackedSize = m_BufferSize;
00669 return (unsigned)m_PackedSize;
00670 }
00671
00672 if (!m_PackOptComputed) {
00673 x_ComputePackOpt();
00674 }
00675
00676 char* new_ptr = m_Buffer;
00677 new_ptr += m_FirstVarFieldIdxOffs;
00678 m_PackedSize = m_FirstVarFieldIdxOffs;
00679
00680 for (size_t i = m_FirstVarFieldIdx; i < m_Fields.size(); ++i) {
00681 CBDB_Field& df = *m_Fields[i];
00682 size_t actual_len = df.GetLength();
00683 void* old_ptr = m_Ptrs[i];
00684
00685 if (new_ptr != old_ptr) {
00686 ::memmove(new_ptr, old_ptr, actual_len);
00687 df.SetBuffer(new_ptr);
00688 }
00689
00690 if ( m_NullSetSize ) {
00691 if (df.IsVariableLength() && TestNullBit((unsigned)i)) {
00692 actual_len = 1;
00693 *new_ptr = '\0';
00694 }
00695 }
00696
00697 new_ptr += actual_len;
00698 m_PackedSize += actual_len;
00699 }
00700
00701 return (unsigned)m_PackedSize;
00702 }
00703
00704
00705 unsigned int CBDB_BufferManager::Unpack()
00706 {
00707 _ASSERT(m_Fields.size());
00708 if (m_PackedSize == 0)
00709 return (unsigned)m_BufferSize;
00710 if ( !IsPackable() ) {
00711 m_PackedSize = 0;
00712 return (unsigned)m_PackedSize;
00713 }
00714 if (!m_PackOptComputed) {
00715 x_ComputePackOpt();
00716 }
00717
00718 _ASSERT(!m_Fields.empty());
00719 for (size_t i = m_Fields.size() - 1; true; --i) {
00720 CBDB_Field& df = *m_Fields[i];
00721 size_t actual_len = df.GetLength();
00722 void* new_ptr = m_Ptrs[i];
00723 const void* old_ptr = df.GetBuffer();
00724 if (new_ptr != old_ptr) {
00725 ::memmove(new_ptr, old_ptr, actual_len);
00726 df.SetBuffer(new_ptr);
00727 }
00728 m_PackedSize -= actual_len;
00729
00730 if (i == m_FirstVarFieldIdx) {
00731 m_PackedSize -= m_FirstVarFieldIdxOffs;
00732 break;
00733 }
00734 }
00735
00736
00737 _ASSERT(m_PackedSize == 0);
00738 return (unsigned)m_BufferSize;
00739 }
00740
00741 void CBDB_BufferManager::PrepareDBT_ForWrite(DBT* dbt)
00742 {
00743 Pack();
00744 dbt->data = m_Buffer;
00745 dbt->size = (unsigned)m_PackedSize;
00746 dbt->ulen = (unsigned)m_BufferSize;
00747 dbt->flags = DB_DBT_USERMEM;
00748 }
00749
00750 void CBDB_BufferManager::PrepareDBT_ForRead(DBT* dbt)
00751 {
00752 dbt->data = m_Buffer;
00753 dbt->size = (unsigned)m_PackedSize;
00754 dbt->ulen = (unsigned)m_BufferSize;
00755 dbt->flags = DB_DBT_USERMEM;
00756 }
00757
00758 int
00759 CBDB_BufferManager::Compare(const CBDB_BufferManager& buf_mgr,
00760 unsigned int field_count) const
00761 {
00762 if ( !field_count ) {
00763 field_count = FieldCount();
00764 }
00765 _ASSERT(field_count <= FieldCount());
00766
00767 for (unsigned int i = 0; i < field_count; ++i) {
00768 const CBDB_Field& df1 = GetField(i);
00769 const CBDB_Field& df2 = buf_mgr.GetField(i);
00770
00771 int ret = df1.CompareWith(df2);
00772 if ( ret )
00773 return ret;
00774 }
00775
00776 return 0;
00777 }
00778
00779
00780 void CBDB_BufferManager::DuplicateStructureFrom(const CBDB_BufferManager& buf_mgr)
00781 {
00782 _ASSERT(FieldCount() == 0);
00783 for (unsigned int i = 0; i < buf_mgr.FieldCount(); ++i) {
00784 const CBDB_Field& src_fld = buf_mgr.GetField(i);
00785
00786
00787 auto_ptr<CBDB_Field> dst_fld(src_fld.Construct(0));
00788
00789 dst_fld->SetName(src_fld.GetName().c_str());
00790 Bind(dst_fld.get());
00791 dst_fld.release();
00792 }
00793 m_LegacyString = buf_mgr.IsLegacyStrings();
00794 }
00795
00796
00797 void CBDB_BufferManager::CopyFrom(const CBDB_BufferManager& buf_mgr)
00798 {
00799 CopyFieldsFrom(buf_mgr);
00800 }
00801
00802 void CBDB_BufferManager::CopyPackedFrom(void* data, size_t data_size)
00803 {
00804 _ASSERT(data);
00805 _ASSERT(data_size <= m_BufferSize);
00806
00807 memcpy(m_Buffer, data, data_size);
00808 SetDBT_Size(data_size);
00809 ArrangePtrsPacked();
00810 }
00811
00812
00813
00814
00815
00816 CBDB_FieldFixedByteString::CBDB_FieldFixedByteString()
00817 : CBDB_Field(eFixedLength)
00818 {
00819 SetBufferSize(256 + 4);
00820 }
00821
00822 CBDB_FieldFixedByteString&
00823 CBDB_FieldFixedByteString::operator=(const CBDB_FieldFixedByteString& str)
00824 {
00825 void* buf = GetBuffer();
00826 if (this == &str)
00827 return *this;
00828
00829 size_t len = str.GetDataLength(buf);
00830 if ( len > (GetBufferSize()) ) {
00831
00832 BDB_THROW(eOverflow, "Fixed string field overflow.");
00833 }
00834 Unpack();
00835 ::memcpy(buf, str.GetBuffer(), len);
00836
00837 if ( str.IsNull() ) {
00838 SetNull();
00839 } else {
00840 SetNotNull();
00841 }
00842
00843 return *this;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853 CBDB_FieldLString::CBDB_FieldLString()
00854 : CBDB_FieldStringBase()
00855 {
00856 SetBufferSize(256 + 4);
00857 }
00858
00859 CBDB_Field* CBDB_FieldLString::Construct(size_t buf_size) const
00860 {
00861 CBDB_FieldLString* fld = new CBDB_FieldLString();
00862 fld->SetBufferSize(buf_size ? buf_size + 4 : GetBufferSize());
00863 return fld;
00864 }
00865
00866
00867 const unsigned char*
00868 CBDB_FieldLString::GetLString(const unsigned char* str,
00869 bool check_legacy,
00870 int* str_len) const
00871 {
00872 size_t DBT_size = m_BufferManager->GetDBT_Size();
00873
00874 if (DBT_size > 0 && DBT_size <= 4) {
00875 _ASSERT(check_legacy);
00876 *str_len = (int)::strlen((const char*)str);
00877 } else {
00878 str = s_GetLString(str, check_legacy, str_len);
00879 }
00880 return str;
00881 }
00882
00883
00884 size_t CBDB_FieldLString::GetExtraDataLength()
00885 {
00886 return 4;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 CBDB_FieldLString&
00910 CBDB_FieldLString::operator=(const CBDB_FieldLString& str)
00911 {
00912 void* buf = GetBuffer();
00913 if (this == &str)
00914 return *this;
00915
00916 size_t len = str.GetDataLength(buf);
00917 if ( len > (GetBufferSize() - 4) ) {
00918
00919 BDB_THROW(eOverflow, "String field overflow.");
00920 }
00921 Unpack();
00922 ::memcpy(buf, str.GetBuffer(), len);
00923
00924 if ( str.IsNull() ) {
00925 SetNull();
00926 } else {
00927 SetNotNull();
00928 }
00929
00930 return *this;
00931 }
00932
00933 void CBDB_FieldLString::Set(const char* str, size_t size,
00934 EOverflowAction if_overflow)
00935 {
00936 if ( !size )
00937 str = kEmptyCStr;
00938
00939 unsigned int new_len = (unsigned)size;
00940
00941
00942 unsigned eff_buffer_size = GetBufferSize() - 4;
00943 if (new_len > eff_buffer_size) {
00944 if (if_overflow == eTruncateOnOverflow) {
00945 new_len = eff_buffer_size;
00946 } else {
00947 string message("String field overflow. Max length is ");
00948 message += NStr::IntToString(eff_buffer_size);
00949 message += ", requested length is ";
00950 message += NStr::IntToString(new_len);
00951 BDB_THROW(eOverflow, message);
00952 }
00953 }
00954 Unpack();
00955 unsigned char* str_buf = (unsigned char*) GetBuffer();
00956
00957 int s_len = -(int)new_len;
00958 str_buf[0] = (unsigned char) (s_len);
00959 str_buf[1] = (unsigned char) (s_len >> 8);
00960 str_buf[2] = (unsigned char) (s_len >> 16);
00961 str_buf[3] = (unsigned char) (s_len >> 24);
00962
00963 str_buf += 4;
00964
00965 ::memcpy(str_buf, str, new_len);
00966
00967 SetNotNull();
00968 }
00969
00970
00971 void CBDB_FieldLString::Set(const char* str, EOverflowAction if_overflow)
00972 {
00973 if ( !str )
00974 str = kEmptyCStr;
00975
00976 this->Set(str, ::strlen(str), if_overflow);
00977 }
00978
00979 void CBDB_FieldLString::SetString(const char* str)
00980 {
00981 operator=(str);
00982 }
00983
00984
00985 int CBDB_FieldLString::Compare(const void* p1,
00986 const void* p2,
00987 bool ) const
00988 {
00989 _ASSERT(p1 && p2);
00990
00991 bool check_legacy = m_BufferManager->IsLegacyStrings();
00992
00993 const unsigned char* str1;
00994 const unsigned char* str2;
00995 int str_len1;
00996 int str_len2;
00997
00998 str1 = GetLString((const unsigned char*)p1, check_legacy, &str_len1);
00999 str2 = GetLString((const unsigned char*)p2, check_legacy, &str_len2);
01000
01001 int cmp_len = min(str_len1, str_len2);
01002 int r = ::memcmp(str1, str2, cmp_len);
01003 if (r == 0) {
01004 return (str_len1 < str_len2) ? -1
01005 : ((str_len2 < str_len1) ? 1 : 0);
01006 }
01007 return r;
01008 }
01009
01010
01011 void CBDB_FieldLString::SetMinVal()
01012 {
01013 Set("", eTruncateOnOverflow);
01014 }
01015
01016
01017 void CBDB_FieldLString::SetMaxVal()
01018 {
01019 void* buf = Unpack();
01020 int buf_size = GetBufferSize();
01021
01022 ::memset(buf, 0x7F, buf_size);
01023 ((char*) buf)[buf_size - 1] = '\0';
01024
01025 int s_len = -(buf_size - 4);
01026 unsigned char* str_buf = (unsigned char*) buf;
01027
01028 str_buf[0] = (unsigned char) (s_len);
01029 str_buf[1] = (unsigned char) (s_len >> 8);
01030 str_buf[2] = (unsigned char) (s_len >> 16);
01031 str_buf[3] = (unsigned char) (s_len >> 24);
01032
01033 SetNotNull();
01034 }
01035
01036
01037 bool CBDB_FieldLString::IsEmpty() const
01038 {
01039 const unsigned char* str = (const unsigned char*) GetBuffer();
01040 bool check_legacy = m_BufferManager->IsLegacyStrings();
01041 int str_len;
01042
01043 str = GetLString(str, check_legacy, &str_len);
01044
01045 return (str_len == 0);
01046 }
01047
01048 bool CBDB_FieldLString::IsBlank() const
01049 {
01050 const unsigned char* str = (const unsigned char*) GetBuffer();
01051 bool check_legacy = m_BufferManager->IsLegacyStrings();
01052 int str_len;
01053
01054 str = GetLString(str, check_legacy, &str_len);
01055
01056 for (int i = 0; i < str_len; ++i) {
01057 if (!isspace((unsigned char) str[i]))
01058 return false;
01059 }
01060
01061 return true;
01062 }
01063
01064
01065 size_t CBDB_FieldLString::GetDataLength(const void* buf) const
01066 {
01067 const unsigned char* str = (const unsigned char*) buf;
01068 bool check_legacy = m_BufferManager->IsLegacyStrings();
01069 int str_len;
01070
01071 str = GetLString(str, check_legacy, &str_len);
01072 if (str != (const unsigned char*) buf)
01073 str_len += 4;
01074
01075
01076
01077 return str_len;
01078 }
01079
01080 CBDB_FieldLString& CBDB_FieldLString::operator= (const char* str)
01081 {
01082 Set(str, eThrowOnOverflow);
01083 return *this;
01084 }
01085
01086 CBDB_FieldLString& CBDB_FieldLString::operator= (const string& str)
01087 {
01088 SetStdString(str);
01089 return *this;
01090 }
01091
01092
01093 string CBDB_FieldLString::Get() const
01094 {
01095 _ASSERT(!IsNull());
01096
01097 const unsigned char* buf = (const unsigned char*) GetBuffer();
01098 bool check_legacy = m_BufferManager->IsLegacyStrings();
01099
01100 const unsigned char* str;
01101 int str_len;
01102
01103 str = GetLString(buf, check_legacy, &str_len);
01104 if (str_len == 0) {
01105 return kEmptyStr;
01106 }
01107 string ret((const char*) str, str_len);
01108 return ret;
01109 }
01110
01111 void CBDB_FieldLString::ToString(string& ostr) const
01112 {
01113 const unsigned char* buf = (const unsigned char*) GetBuffer();
01114 bool check_legacy = m_BufferManager->IsLegacyStrings();
01115
01116 const unsigned char* str;
01117 int str_len;
01118
01119 ostr.resize(0);
01120
01121 str = GetLString(buf, check_legacy, &str_len);
01122 if (str_len == 0) {
01123 return;
01124 }
01125 ostr.append((const char*) str, str_len);
01126 }
01127
01128 void CBDB_FieldLString::SetStdString(const string& str)
01129 {
01130 unsigned int str_len = str.length();
01131 if (str_len == 0) {
01132 Set("", eThrowOnOverflow);
01133 return;
01134 }
01135
01136 unsigned eff_buffer_size = GetBufferSize() - 4;
01137
01138 if (str_len > eff_buffer_size) {
01139 string message("String field overflow. Max length is ");
01140 message += NStr::IntToString(eff_buffer_size);
01141 message += ", requested length is ";
01142 message += NStr::IntToString(str_len);
01143 BDB_THROW(eOverflow, message);
01144 }
01145
01146 const char* str_data = str.data();
01147
01148 unsigned char* str_buf = (unsigned char*) Unpack();
01149
01150 int s_len = -(int)str_len;
01151 str_buf[0] = (unsigned char) (s_len);
01152 str_buf[1] = (unsigned char) (s_len >> 8);
01153 str_buf[2] = (unsigned char) (s_len >> 16);
01154 str_buf[3] = (unsigned char) (s_len >> 24);
01155
01156 str_buf += 4;
01157
01158 ::memcpy(str_buf, str_data, str_len);
01159
01160 SetNotNull();
01161 }
01162
01163
01164
01165
01166
01167 CBDB_FieldFactory::CBDB_FieldFactory()
01168 {}
01169
01170 CBDB_FieldFactory::EType CBDB_FieldFactory::GetType(const string& type) const
01171 {
01172 if (NStr::CompareNocase(type, "string")==0) {
01173 return eString;
01174 } else
01175 if (NStr::CompareNocase(type, "lstring")==0) {
01176 return eLString;
01177 } else
01178 if (NStr::CompareNocase(type, "int8")==0) {
01179 return eInt8;
01180 } else
01181 if (NStr::CompareNocase(type, "int4")==0) {
01182 return eInt4;
01183 } else
01184 if (NStr::CompareNocase(type, "uint4")==0) {
01185 return eUint4;
01186 } else
01187 if (NStr::CompareNocase(type, "int2")==0) {
01188 return eInt2;
01189 } else
01190 if (NStr::CompareNocase(type, "uint1")==0) {
01191 return eUint1;
01192 } else
01193 if (NStr::CompareNocase(type, "float")==0) {
01194 return eFloat;
01195 } else
01196 if (NStr::CompareNocase(type, "double")==0) {
01197 return eDouble;
01198 } else
01199 if (NStr::CompareNocase(type, "uchar")==0) {
01200 return eUChar;
01201 } else
01202 if (NStr::CompareNocase(type, "blob")==0) {
01203 return eBlob;
01204 } else
01205 if (NStr::CompareNocase(type, "lob")==0) {
01206 return eBlob;
01207 } else {
01208 return eUnknown;
01209 }
01210 }
01211
01212 CBDB_Field* CBDB_FieldFactory::Create(EType etype) const
01213 {
01214 switch (etype)
01215 {
01216 case eString:
01217 return new CBDB_FieldString();
01218 case eLString:
01219 return new CBDB_FieldLString();
01220 case eInt8:
01221 return new CBDB_FieldInt8();
01222 case eInt4:
01223 return new CBDB_FieldInt4();
01224 case eInt2:
01225 return new CBDB_FieldInt2();
01226 case eUint1:
01227 return new CBDB_FieldUint1();
01228 case eFloat:
01229 return new CBDB_FieldFloat();
01230 case eDouble:
01231 return new CBDB_FieldDouble();
01232 case eUChar:
01233 return new CBDB_FieldUChar();
01234 default:
01235 BDB_THROW(eInvalidType, "Type is not supported.");
01236 };
01237
01238 return 0;
01239 }
01240
01241 CBDB_Field* CBDB_FieldFactory::Create(const string& type) const
01242 {
01243 EType et = GetType(type);
01244 try
01245 {
01246 return Create(et);
01247 }
01248 catch (CBDB_LibException& )
01249 {
01250 BDB_THROW(eInvalidType, type);
01251 }
01252 }
01253
01254
01255 END_NCBI_SCOPE
01256
01257
01258
01259