bdb_types.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:24k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bdb_types.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:37:36  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.23
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: bdb_types.cpp,v 1000.3 2004/06/01 18:37:36 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Anatoliy Kuznetsov
  35.  *
  36.  * File Description:  BDB libarary types implementations.
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbi_bswap.hpp>
  41. #include <bdb/bdb_types.hpp>
  42. #include <db.h>
  43. BEGIN_NCBI_SCOPE
  44. static
  45. const unsigned char* s_GetLString(const unsigned char* str, 
  46.                                   bool  check_legacy, 
  47.                                   int*  str_len)
  48. {
  49.     _ASSERT(str);
  50.     _ASSERT(str_len);
  51.     // string length reconstruction
  52.     *str_len = (str[0])       | 
  53.                (str[1] << 8)  |
  54.                (str[2] << 16) |
  55.                (str[3] << 24);
  56.     
  57.     if (check_legacy) {
  58.         if (*str_len < 0) { // true L-string
  59.             *str_len = -(*str_len);
  60.             str += 4;
  61.         } else {
  62.             *str_len = ::strlen((const char*)str);
  63.         }
  64.     } else {  // no legacy strings
  65.         if (*str_len < 0) { // true L-string
  66.             *str_len = -(*str_len);
  67.             str += 4;
  68.         } else {
  69.             _ASSERT(0); // positive length !
  70.         }
  71.     }
  72.     return str;
  73. }
  74. static 
  75. const unsigned char* s_GetLString(const DBT* val, 
  76.                                   bool  check_legacy, 
  77.                                   int*  str_len)
  78. {
  79.     const unsigned char* str = (const unsigned char*)val->data;
  80.     if (val->size <= 4) {  // looks like legacy C-string
  81.         _ASSERT(check_legacy);
  82.         *str_len = ::strlen((const char*)str);
  83.         return str;
  84.     }
  85.     return s_GetLString(str, check_legacy, str_len);
  86. }
  87. extern "C"
  88. {
  89. /////////////////////////////////////////////////////////////////////////////
  90. //  BDB comparison functions
  91. //
  92. int BDB_UintCompare(DB*, const DBT* val1, const DBT* val2)
  93. {
  94.     unsigned int v1, v2;
  95.     ::memcpy(&v1, val1->data, sizeof(unsigned));
  96.     ::memcpy(&v2, val2->data, sizeof(unsigned));
  97.     return (v1 < v2) ? -1
  98.                      : ((v2 < v1) ? 1 : 0);
  99. }
  100. int BDB_IntCompare(DB*, const DBT* val1, const DBT* val2)
  101. {
  102.     int v1, v2;
  103.     ::memcpy(&v1, val1->data, sizeof(int));
  104.     ::memcpy(&v2, val2->data, sizeof(int));
  105.     return (v1 < v2) ? -1
  106.                      : ((v2 < v1) ? 1 : 0);
  107. }
  108. int BDB_Int2Compare(DB*, const DBT* val1, const DBT* val2)
  109. {
  110.     Int2 v1, v2;
  111.     ::memcpy(&v1, val1->data, sizeof(Int2));
  112.     ::memcpy(&v2, val2->data, sizeof(Int2));
  113.     return (v1 < v2) ? -1
  114.                      : ((v2 < v1) ? 1 : 0);
  115. }
  116. int BDB_UCharCompare(DB*, const DBT* val1, const DBT* val2)
  117. {
  118.     const unsigned char& v1=*static_cast<unsigned char*>(val1->data);
  119.     const unsigned char& v2=*static_cast<unsigned char*>(val2->data);
  120.     return (v1 < v2) ? -1
  121.                      : ((v2 < v1) ? 1 : 0);
  122. }
  123. int BDB_FloatCompare(DB*, const DBT* val1, const DBT* val2)
  124. {
  125.     float v1, v2;
  126.     ::memcpy(&v1, val1->data, sizeof(v1));
  127.     ::memcpy(&v2, val2->data, sizeof(v2));
  128.     return (v1 < v2) ? -1
  129.                      : ((v2 < v1) ? 1 : 0);
  130. }
  131. int BDB_DoubleCompare(DB*, const DBT* val1, const DBT* val2)
  132. {
  133.     double v1, v2;
  134.     ::memcpy(&v1, val1->data, sizeof(v1));
  135.     ::memcpy(&v2, val2->data, sizeof(v2));
  136.     return (v1 < v2) ? -1
  137.                      : ((v2 < v1) ? 1 : 0);
  138. }
  139. int BDB_StringCompare(DB*, const DBT* val1, const DBT* val2)
  140. {
  141.     return ::strcmp((const char*)val1->data, (const char*)val2->data);
  142. }
  143. int BDB_LStringCompare(DB* db, const DBT* val1, const DBT* val2)
  144. {
  145.     const CBDB_BufferManager* fbuf1 =
  146.           static_cast<CBDB_BufferManager*> (db->app_private);
  147.     bool check_legacy = fbuf1->IsLegacyStrings();
  148.     
  149.     const unsigned char* str1;
  150.     const unsigned char* str2;
  151.     int str_len1; 
  152.     int str_len2;
  153.     str1 = s_GetLString(val1, check_legacy, &str_len1); 
  154.     str2 = s_GetLString(val2, check_legacy, &str_len2); 
  155.     int cmp_len = min(str_len1, str_len2);
  156.     int r = ::memcmp(str1, str2, cmp_len);
  157.     if (r == 0) {
  158.         return (str_len1 < str_len2) ? -1
  159.                                      : ((str_len2 < str_len1) ? 1 : 0);
  160.     }
  161.     return r;
  162. }
  163. int BDB_StringCaseCompare(DB*, const DBT* val1, const DBT* val2)
  164. {
  165.     return NStr::strcasecmp((const char*)val1->data, (const char*)val2->data);
  166. }
  167. int BDB_Compare(DB* db, const DBT* val1, const DBT* val2)
  168. {
  169.     const CBDB_BufferManager* fbuf1 =
  170.           static_cast<CBDB_BufferManager*> (db->app_private);
  171.     bool byte_swapped = fbuf1->IsByteSwapped();
  172.     _ASSERT(fbuf1);
  173.     const char* p1 = static_cast<char*> (val1->data);
  174.     const char* p2 = static_cast<char*> (val2->data);
  175.     unsigned int cmp_limit = fbuf1->GetFieldCompareLimit();
  176.     if (cmp_limit == 0) {
  177.         cmp_limit = fbuf1->FieldCount();
  178.     } else {
  179.         _ASSERT(cmp_limit <= fbuf1->FieldCount());
  180.     }
  181.     for (unsigned int i = 0;  i < cmp_limit;  ++i) {
  182.         const CBDB_Field& fld1 = fbuf1->GetField(i);
  183.         int ret = fld1.Compare(p1, p2, byte_swapped);
  184.         if ( ret )
  185.             return ret;
  186.         p1 += fld1.GetDataLength(p1);
  187.         p2 += fld1.GetDataLength(p2);
  188.     }
  189.     return 0;
  190. }
  191. int BDB_ByteSwap_UintCompare(DB*, const DBT* val1, const DBT* val2)
  192. {
  193.     unsigned int v1, v2;
  194.     v1 = (unsigned int) CByteSwap::GetInt4((unsigned char*)val1->data);
  195.     v2 = (unsigned int) CByteSwap::GetInt4((unsigned char*)val2->data);
  196.     return (v1 < v2) ? -1
  197.                      : ((v2 < v1) ? 1 : 0);
  198. }
  199. int BDB_ByteSwap_IntCompare(DB*, const DBT* val1, const DBT* val2)
  200. {
  201.     int v1, v2;
  202.     v1 = CByteSwap::GetInt4((unsigned char*)val1->data);
  203.     v2 = CByteSwap::GetInt4((unsigned char*)val2->data);
  204.     return (v1 < v2) ? -1
  205.                      : ((v2 < v1) ? 1 : 0);
  206. }
  207. int BDB_ByteSwap_Int2Compare(DB*, const DBT* val1, const DBT* val2)
  208. {
  209.     Int2 v1, v2;
  210.     v1 = CByteSwap::GetInt2((unsigned char*)val1->data);
  211.     v2 = CByteSwap::GetInt2((unsigned char*)val2->data);
  212.     return (v1 < v2) ? -1
  213.                      : ((v2 < v1) ? 1 : 0);
  214. }
  215. int BDB_ByteSwap_FloatCompare(DB*, const DBT* val1, const DBT* val2)
  216. {
  217.     float v1, v2;
  218.     v1 = CByteSwap::GetFloat((unsigned char*)val1->data);
  219.     v2 = CByteSwap::GetFloat((unsigned char*)val2->data);
  220.     return (v1 < v2) ? -1
  221.                      : ((v2 < v1) ? 1 : 0);
  222. }
  223. int BDB_ByteSwap_DoubleCompare(DB*, const DBT* val1, const DBT* val2)
  224. {
  225.     double v1, v2;
  226.     v1 = CByteSwap::GetDouble((unsigned char*)val1->data);
  227.     v2 = CByteSwap::GetDouble((unsigned char*)val2->data);
  228.     return (v1 < v2) ? -1
  229.                      : ((v2 < v1) ? 1 : 0);
  230. }
  231. } // extern "C"
  232. /////////////////////////////////////////////////////////////////////////////
  233. //  IBDB_Field::
  234. //
  235. IBDB_Field::~IBDB_Field() 
  236. {
  237. }
  238. /////////////////////////////////////////////////////////////////////////////
  239. //  CBDB_Field::
  240. //
  241. CBDB_Field::CBDB_Field(ELengthType length_type)
  242. : m_BufferManager(0),
  243.   m_Buffer(0),
  244.   m_BufferSize(0),
  245.   m_BufferIdx(0)
  246. {   
  247.     m_Flags.VariableLength = (length_type == eFixedLength) ? 0 : 1;
  248.     m_Flags.Attached = 0;
  249.     m_Flags.Nullable = 0;
  250. }
  251. BDB_CompareFunction 
  252. CBDB_Field::GetCompareFunction(bool /*byte_swapped*/) const
  253.     return BDB_Compare; 
  254. }
  255. /////////////////////////////////////////////////////////////////////////////
  256. //  CBDB_BufferManager::
  257. //
  258. CBDB_BufferManager::CBDB_BufferManager()
  259.   : m_Buffer(0),
  260.     m_BufferSize(0),
  261.     m_PackedSize(0),
  262.     m_DBT_Size(0),
  263.     m_Packable(false),
  264.     m_ByteSwapped(false),
  265.     m_Nullable(false),
  266.     m_NullSetSize(0),
  267.     m_CompareLimit(0),
  268.     m_LegacyString(false)
  269. {
  270. }
  271. CBDB_BufferManager::~CBDB_BufferManager()
  272. {
  273.     delete [] m_Buffer;
  274. }
  275. void CBDB_BufferManager::Bind(CBDB_Field* field, ENullable is_nullable)
  276. {
  277.     m_Fields.push_back(field);
  278.     m_Ptrs.push_back(0);
  279.     unsigned field_idx = (unsigned)(m_Fields.size() - 1);
  280.     field->SetBufferIdx(field_idx);
  281.     if ( !m_Packable ) {
  282.         // If we bind any var length field, then record becomes packable
  283.         m_Packable = field->IsVariableLength();
  284.     }
  285.     if (is_nullable == eNullable)
  286.         field->SetNullable();
  287. }
  288. int CBDB_BufferManager::GetFieldIndex(const string& name) const
  289. {
  290.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  291.         const CBDB_Field& field = *m_Fields[i];
  292.         const string& fname = field.GetName();
  293.         if (NStr::CompareNocase(name, fname) == 0) {
  294.             return i;
  295.         }
  296.     }
  297.     return -1;
  298. }
  299. size_t CBDB_BufferManager::ComputeBufferSize() const
  300. {
  301.     size_t buf_len = 0;
  302.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  303.         const CBDB_Field& field = *m_Fields[i];
  304.         buf_len += field.GetBufferSize();
  305.     }
  306.     return buf_len;
  307. }
  308. void CBDB_BufferManager::CheckNullConstraint() const
  309. {
  310.     if ( !IsNullable() )
  311.         return;
  312.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  313.         const CBDB_Field& fld = *m_Fields[i];
  314.         if (!fld.IsNullable()  &&  TestNullBit((unsigned)i)) {
  315.             string message("NULL field in database operation.");
  316.             const string& field_name = fld.GetName();
  317.             if ( !field_name.empty() ) {
  318.                 message.append("(Field:");
  319.                 message.append(field_name);
  320.                 message.append(")");
  321.             }
  322.             BDB_THROW(eNull, message);
  323.         }
  324.     }
  325. }
  326. void CBDB_BufferManager::Construct()
  327. {
  328.     _ASSERT(m_Fields.size());
  329.     // Buffer construction: fields size calculation.
  330.     m_BufferSize = ComputeBufferSize();
  331.     if ( IsNullable() ) {
  332.         m_NullSetSize = ComputeNullSetSize();
  333.         m_BufferSize += m_NullSetSize;
  334.     }
  335.     delete [] m_Buffer; m_Buffer = 0;
  336.     m_Buffer = new char[m_BufferSize];
  337.     ::memset(m_Buffer, 0, m_BufferSize);
  338.     // Record construction: set element offsets(pointers)
  339.     char*  buf_ptr = (char*) m_Buffer;
  340.     buf_ptr += m_NullSetSize;
  341.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  342.         CBDB_Field& df = *m_Fields[i];
  343.         m_Ptrs[i] = buf_ptr;
  344.         df.SetBufferManager(this);
  345.         df.SetBuffer(buf_ptr);
  346.         buf_ptr += df.GetBufferSize();
  347.     }
  348.     m_PackedSize = 0;  // not packed
  349. }
  350. BDB_CompareFunction 
  351. CBDB_BufferManager::GetCompareFunction() const
  352. {
  353.     if (m_Fields.size() > 1)
  354.         return BDB_Compare;
  355.     bool byte_swapped = IsByteSwapped();
  356.     return m_Fields[0]->GetCompareFunction(byte_swapped);
  357. }
  358. void CBDB_BufferManager::ArrangePtrsPacked()
  359. {
  360.     _ASSERT(m_Fields.size());
  361.     if ( !IsPackable() ) {
  362.         m_PackedSize = m_BufferSize;
  363.         return;
  364.     }
  365.     char* buf_ptr = m_Buffer;
  366.     buf_ptr += m_NullSetSize;
  367.     m_PackedSize = m_NullSetSize;
  368.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  369.         CBDB_Field& df = *m_Fields[i];
  370.         df.SetBuffer(buf_ptr);
  371.         size_t len = df.GetDataLength(buf_ptr);
  372.         buf_ptr += len;
  373.         m_PackedSize += len;
  374.     }
  375. }
  376. unsigned int CBDB_BufferManager::Pack()
  377. {
  378.     _ASSERT(m_Fields.size());
  379.     if (m_PackedSize != 0)
  380.         return (unsigned)m_PackedSize;
  381.     if ( !IsPackable() ) {
  382.         m_PackedSize = m_BufferSize;
  383.         return (unsigned)m_PackedSize;
  384.     }
  385.     char* new_ptr = m_Buffer;
  386.     new_ptr += m_NullSetSize;
  387.     m_PackedSize = m_NullSetSize;
  388.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  389.         CBDB_Field& df = *m_Fields[i];
  390.         size_t actual_len = df.GetLength();
  391.         void* old_ptr = m_Ptrs[i];
  392.         if (new_ptr != old_ptr) {
  393.             ::memmove(new_ptr, old_ptr, actual_len);
  394.             df.SetBuffer(new_ptr);
  395.         }
  396.         if ( m_NullSetSize ) {
  397.             if (df.IsVariableLength()  &&  TestNullBit((unsigned)i)) {
  398.                 actual_len = 1;
  399.                 *new_ptr = ''; // for string it will guarantee it is empty
  400.             }
  401.         }
  402.         new_ptr      += actual_len;
  403.         m_PackedSize += actual_len;
  404.     }
  405.     return (unsigned)m_PackedSize;
  406. }
  407. unsigned int CBDB_BufferManager::Unpack()
  408. {
  409.     _ASSERT(m_Fields.size());
  410.     if (m_PackedSize == 0)
  411.         return (unsigned)m_BufferSize;
  412.     if ( !IsPackable() ) {
  413.         m_PackedSize = 0;
  414.         return (unsigned)m_PackedSize;
  415.     }
  416.     _ASSERT(!m_Fields.empty());
  417.     for (size_t i = m_Fields.size() - 1;  true;  --i) {
  418.         CBDB_Field& df = *m_Fields[i];
  419.         size_t actual_len = df.GetLength();
  420.         void* new_ptr = m_Ptrs[i];
  421.         const void* old_ptr = df.GetBuffer();
  422.         if (new_ptr != old_ptr) {
  423.             ::memmove(new_ptr, old_ptr, actual_len);
  424.             df.SetBuffer(new_ptr);
  425.         }
  426.         m_PackedSize -= actual_len;
  427.         if (i == 0)
  428.             break;
  429.     }
  430.     m_PackedSize -= m_NullSetSize;
  431.     _ASSERT(m_PackedSize == 0);
  432.     return (unsigned)m_BufferSize;
  433. }
  434. void CBDB_BufferManager::PrepareDBT_ForWrite(DBT* dbt)
  435. {
  436.     Pack();
  437.     dbt->data = m_Buffer;
  438.     dbt->size = (unsigned)m_PackedSize;
  439. }
  440. void CBDB_BufferManager::PrepareDBT_ForRead(DBT* dbt)
  441. {
  442.     dbt->data = m_Buffer;
  443.     dbt->size = dbt->ulen = (unsigned)m_BufferSize;
  444.     dbt->flags = DB_DBT_USERMEM;
  445. }
  446. int CBDB_BufferManager::Compare(const CBDB_BufferManager& buf_mgr,
  447.                                 unsigned int              field_count)
  448.     const
  449. {
  450.     if ( !field_count ) {
  451.         field_count = FieldCount();
  452.     }
  453.     _ASSERT(field_count <= FieldCount());
  454.     for (unsigned int i = 0;  i < field_count;  ++i) {
  455.         const CBDB_Field& df1 = GetField(i);
  456.         const CBDB_Field& df2 = buf_mgr.GetField(i);
  457.         int ret = df1.CompareWith(df2);
  458.         if ( ret )
  459.             return ret;
  460.     }
  461.     return 0;
  462. }
  463. void CBDB_BufferManager::DuplicateStructureFrom(const CBDB_BufferManager& buf_mgr)
  464. {
  465.     _ASSERT(FieldCount() == 0);
  466.     for (unsigned int i = 0;  i < buf_mgr.FieldCount();  ++i) {
  467.         const CBDB_Field& src_fld = buf_mgr.GetField(i);
  468.         auto_ptr<CBDB_Field> dst_fld(src_fld.Construct(0));
  469.         dst_fld->SetName(src_fld.GetName().c_str());
  470.         Bind(dst_fld.get());
  471.         dst_fld.release();
  472.     }
  473.     m_LegacyString = buf_mgr.IsLegacyStrings();
  474. }
  475. /////////////////////////////////////////////////////////////////////////////
  476. //  CBDB_FieldLString::
  477. //
  478. CBDB_FieldLString::CBDB_FieldLString() 
  479.  : CBDB_FieldStringBase()
  480. {
  481.     SetBufferSize(256 + 4);
  482. }
  483. CBDB_Field* CBDB_FieldLString::Construct(size_t buf_size) const
  484. {
  485.     CBDB_FieldLString* fld = new CBDB_FieldLString();
  486.     fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
  487.     return fld;
  488. }
  489. const unsigned char* 
  490. CBDB_FieldLString::GetLString(const unsigned char* str,
  491.                               bool                 check_legacy,
  492.                               int*                 str_len) const
  493. {
  494.     size_t DBT_size = m_BufferManager->GetDBT_Size();
  495.     if (DBT_size > 0 && DBT_size <= 4) {  // looks like legacy C-string
  496.         _ASSERT(check_legacy);
  497.         *str_len = (int)::strlen((const char*)str);
  498.     } else {
  499.         str = s_GetLString(str, check_legacy, str_len);
  500.     }
  501.     return str;
  502. }
  503. /*
  504. CBDB_FieldLString::operator const char* () const
  505. {
  506.     const unsigned char* str = (const unsigned char*)GetBuffer();
  507.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  508.     int str_len;
  509.     size_t DBT_size = m_BufferManager->GetDBT_Size();
  510.     if (DBT_size <= 4) {  // looks like legacy C-string
  511.         _ASSERT(check_legacy);
  512.         str_len = ::strlen((const char*)str);
  513.     } else {
  514.         str = GetLString(str, check_legacy, &str_len);
  515.     }
  516.     return (const char*) str;
  517. }
  518. */
  519. const CBDB_FieldLString& 
  520. CBDB_FieldLString::operator=(const CBDB_FieldLString& str)
  521. {
  522.     void* buf = GetBuffer();
  523.     if (this == &str)
  524.         return *this;
  525.     size_t len = str.GetDataLength(buf);
  526.     if ( len > (GetBufferSize() - 4) ) {
  527.         // TODO: allow partial string assignment?
  528.         BDB_THROW(eOverflow, "String field overflow.");
  529.     }
  530.     Unpack();
  531.     ::memcpy(buf, str.GetBuffer(), len);
  532.     if ( str.IsNull() ) {
  533.         SetNull();
  534.     } else {
  535.         SetNotNull();
  536.     }
  537.     return *this;
  538. }
  539. void CBDB_FieldLString::Set(const char* str, EOverflowAction if_overflow)
  540. {
  541.     if ( !str )
  542.         str = kEmptyCStr;
  543.     unsigned int new_len = ::strlen(str) + 1;
  544.     // check overflow
  545.     if ( new_len > (GetBufferSize() - 4) ) {
  546.         if (if_overflow == eTruncateOnOverflow) {
  547.             new_len = GetBufferSize();
  548.         } else {
  549.             string message("String field overflow."); 
  550.             // TODO: add info what caused overflow, what length expected
  551.             BDB_THROW(eOverflow, message);
  552.         }
  553.     }
  554.     Unpack();
  555.     unsigned char* str_buf = (unsigned char*) GetBuffer();
  556.     int s_len = -new_len;  // always store it negative
  557.     str_buf[0] = (unsigned char) (s_len);
  558.     str_buf[1] = (unsigned char) (s_len >> 8);
  559.     str_buf[2] = (unsigned char) (s_len >> 16);
  560.     str_buf[3] = (unsigned char) (s_len >> 24);
  561.     str_buf += 4;
  562.     ::memcpy(str_buf, str, new_len);
  563.     SetNotNull();
  564. }
  565. void CBDB_FieldLString::SetString(const char* str)
  566. {
  567.     operator=(str);
  568. }
  569. int CBDB_FieldLString::Compare(const void* p1, 
  570.                                const void* p2, 
  571.                                bool /*byte_swapped*/) const
  572. {
  573.     _ASSERT(p1 && p2);
  574.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  575.     
  576.     const unsigned char* str1;
  577.     const unsigned char* str2;
  578.     int str_len1; 
  579.     int str_len2;
  580.     str1 = GetLString((const unsigned char*)p1, check_legacy, &str_len1);
  581.     str2 = GetLString((const unsigned char*)p2, check_legacy, &str_len2); 
  582.     int cmp_len = min(str_len1, str_len2);
  583.     int r = ::memcmp(str1, str2, cmp_len);
  584.     if (r == 0) {
  585.         return (str_len1 < str_len2) ? -1
  586.                                      : ((str_len2 < str_len1) ? 1 : 0);
  587.     }
  588.     return r;
  589. }
  590. void CBDB_FieldLString::SetMinVal()
  591. {
  592.     Set("", eTruncateOnOverflow);
  593. }
  594. void CBDB_FieldLString::SetMaxVal()
  595. {
  596.     void* buf = Unpack();
  597.     int buf_size = GetBufferSize();
  598.     ::memset(buf, 0x7F, buf_size); // 0xFF for international
  599.     ((char*) buf)[buf_size - 1] = '';
  600.     int s_len = -(buf_size - 4);  // always store it negative
  601.     unsigned char* str_buf = (unsigned char*) buf;
  602.     str_buf[0] = (unsigned char) (s_len);
  603.     str_buf[1] = (unsigned char) (s_len >> 8);
  604.     str_buf[2] = (unsigned char) (s_len >> 16);
  605.     str_buf[3] = (unsigned char) (s_len >> 24);
  606.     SetNotNull();
  607. }
  608. bool CBDB_FieldLString::IsEmpty() const
  609. {
  610.     const unsigned char* str = (const unsigned char*) GetBuffer();
  611.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  612.     int str_len;
  613.     str = GetLString(str, check_legacy, &str_len);
  614.     return (str_len == 0);
  615. }
  616. bool CBDB_FieldLString::IsBlank() const
  617. {
  618.     const unsigned char* str = (const unsigned char*) GetBuffer();
  619.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  620.     int str_len;
  621.     str = GetLString(str, check_legacy, &str_len);
  622.     for (int i = 0; i < str_len; ++i) {
  623.         if (!isspace(str[i]))
  624.             return false;
  625.     }
  626.     return true;
  627. }
  628. size_t CBDB_FieldLString::GetDataLength(const void* buf) const
  629. {
  630.     const unsigned char* str = (const unsigned char*) buf;
  631.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  632.     int str_len;
  633.     str = GetLString(str, check_legacy, &str_len);
  634.     if (str != (const unsigned char*) buf)
  635.         str_len += 4;
  636.     return str_len + 1;
  637. }
  638. const CBDB_FieldLString& CBDB_FieldLString::operator= (const char* str)
  639.     Set(str, eThrowOnOverflow); 
  640.     return *this;
  641. }
  642. const CBDB_FieldLString& CBDB_FieldLString::operator= (const string& str)
  643. {
  644.     SetStdString(str);
  645.     return *this;
  646. }
  647. string CBDB_FieldLString::Get() const
  648. {
  649.     const unsigned char* buf = (const unsigned char*) GetBuffer();
  650.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  651.     
  652.     const unsigned char* str;
  653.     int str_len; 
  654.     str = GetLString(buf, check_legacy, &str_len);
  655.     if (str_len == 0) {
  656.         return kEmptyStr;
  657.     } 
  658.     string ret((const char*) str, str_len);
  659.     return ret;
  660. }
  661. void CBDB_FieldLString::ToString(string& ostr) const
  662. {
  663.     const unsigned char* buf = (const unsigned char*) GetBuffer();
  664.     bool check_legacy = m_BufferManager->IsLegacyStrings();
  665.     
  666.     const unsigned char* str;
  667.     int str_len;
  668.     ostr.resize(0);
  669.     str = GetLString(buf, check_legacy, &str_len);
  670.     if (str_len == 0) {
  671.         return;
  672.     }
  673.     ostr.append((const char*) str, str_len);
  674. }
  675. void CBDB_FieldLString::SetStdString(const string& str)
  676. {
  677.     unsigned int str_len = str.length();
  678.     if (str_len == 0) {
  679.         Set("", eThrowOnOverflow);
  680.         return;
  681.     }
  682.     // check overflow
  683.     if (str_len > (GetBufferSize() - 4 - 1)) {
  684.         string message("String field overflow."); 
  685.         // TODO: add info what caused overflow, what length expected
  686.         BDB_THROW(eOverflow, message);
  687.     }
  688.     const char* str_data = str.data();
  689.     /* void* buf = */ Unpack();
  690.     unsigned char* str_buf = (unsigned char*) GetBuffer();
  691.     int s_len = -str_len;  // always store it negative
  692.     str_buf[0] = (unsigned char) (s_len);
  693.     str_buf[1] = (unsigned char) (s_len >> 8);
  694.     str_buf[2] = (unsigned char) (s_len >> 16);
  695.     str_buf[3] = (unsigned char) (s_len >> 24);
  696.     str_buf += 4;
  697.     ::memcpy(str_buf, str_data, str_len);
  698.     str_buf[str_len] = 0;
  699.     SetNotNull();
  700. }
  701. END_NCBI_SCOPE
  702. /*
  703.  * ===========================================================================
  704.  * $Log: bdb_types.cpp,v $
  705.  * Revision 1000.3  2004/06/01 18:37:36  gouriano
  706.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.23
  707.  *
  708.  * Revision 1.23  2004/05/17 20:55:11  gorelenk
  709.  * Added include of PCH ncbi_pch.hpp
  710.  *
  711.  * Revision 1.22  2004/05/06 15:42:19  rotmistr
  712.  * Changed Char type to UChar
  713.  *
  714.  * Revision 1.21  2004/05/05 19:18:21  rotmistr
  715.  * CBDB_FieldChar added
  716.  *
  717.  * Revision 1.20  2004/03/08 13:30:39  kuznets
  718.  * + ToString
  719.  *
  720.  * Revision 1.19  2004/02/17 19:05:21  kuznets
  721.  * GCC warnings fix
  722.  *
  723.  * Revision 1.18  2004/02/12 19:54:39  kuznets
  724.  * CBDB_BufferManager::GetFieldIndex()
  725.  *
  726.  * Revision 1.17  2004/02/04 17:03:39  kuznets
  727.  * Fixed bug in LString manipulation.
  728.  *
  729.  * Revision 1.16  2003/12/22 18:54:14  kuznets
  730.  * Implemeneted length prefixed string field (CBDB_FieldLString)
  731.  *
  732.  * Revision 1.15  2003/11/06 14:06:02  kuznets
  733.  * Removing auto_ptr from CBDB_BufferManager
  734.  *
  735.  * Revision 1.14  2003/10/16 19:25:38  kuznets
  736.  * Added field comparison limit to the fields manager
  737.  *
  738.  * Revision 1.13  2003/09/29 16:27:06  kuznets
  739.  * Cleaned up 64-bit compilation warnings
  740.  *
  741.  * Revision 1.12  2003/09/17 13:31:12  kuznets
  742.  * Implemented Int2Compare family of functions
  743.  *
  744.  * Revision 1.11  2003/09/11 16:34:35  kuznets
  745.  * Implemented byte-order independence.
  746.  *
  747.  * Revision 1.10  2003/07/25 15:47:15  kuznets
  748.  * Added support for double field type
  749.  *
  750.  * Revision 1.9  2003/07/23 20:21:43  kuznets
  751.  * Implemented new improved scheme for setting BerkeleyDB comparison function.
  752.  * When table has non-segmented key the simplest(and fastest) possible function
  753.  * is assigned (automatically without reloading CBDB_File::SetCmp function).
  754.  *
  755.  * Revision 1.8  2003/07/02 17:55:35  kuznets
  756.  * Implementation modifications to eliminated direct dependency from <db.h>
  757.  *
  758.  * Revision 1.7  2003/06/10 20:08:27  kuznets
  759.  * Fixed function names.
  760.  *
  761.  * Revision 1.6  2003/05/27 18:43:45  kuznets
  762.  * Fixed some compilation problems with GCC 2.95
  763.  *
  764.  * Revision 1.5  2003/05/02 14:12:11  kuznets
  765.  * Bug fix
  766.  *
  767.  * Revision 1.4  2003/04/29 19:07:22  kuznets
  768.  * Cosmetics..
  769.  *
  770.  * Revision 1.3  2003/04/29 19:04:47  kuznets
  771.  * Fixed a bug in buffers management
  772.  *
  773.  * Revision 1.2  2003/04/28 14:51:55  kuznets
  774.  * #include directives changed to conform the NCBI policy
  775.  *
  776.  * Revision 1.1  2003/04/24 16:34:30  kuznets
  777.  * Initial revision
  778.  *
  779.  * ===========================================================================
  780.  */