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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bdb_types.hpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 18:37:08  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef BDB_TYPES__HPP
  10. #define BDB_TYPES__HPP
  11. /* $Id: bdb_types.hpp,v 1000.4 2004/06/01 18:37:08 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Anatoliy Kuznetsov
  37.  *   
  38.  * File Description: Field types classes.
  39.  *
  40.  */
  41. #include <bdb/bdb_expt.hpp>
  42. #include <corelib/ncbi_limits.hpp>
  43. #include <corelib/ncbi_bswap.hpp>
  44. #include <corelib/ncbistr.hpp>
  45. #include <string>
  46. #include <vector>
  47. #include <memory>
  48. extern "C" {
  49.     //
  50.     // Forward structure declarations, so we can declare pointers and
  51.     // applications can get type checking.
  52.     // Taken from <db.h> 
  53.     struct __db_dbt; typedef struct __db_dbt DBT;
  54.     struct __db;     typedef struct __db     DB;
  55.     struct __dbc;    typedef struct __dbc    DBC;
  56.     struct __db_env; typedef struct __db_env DB_ENV;
  57.     struct __db_txn; typedef struct __db_txn DB_TXN;
  58.     typedef int (*BDB_CompareFunction)(DB*, const DBT*, const DBT*);
  59. }
  60. BEGIN_NCBI_SCOPE
  61. /** @addtogroup BDB_Types
  62.  *
  63.  * @{
  64.  */
  65. extern "C" {
  66. /// Simple and fast comparison function for tables with 
  67. /// non-segmented "unsigned int" keys
  68. int BDB_UintCompare(DB*, const DBT* val1, const DBT* val2);
  69. /// Simple and fast comparison function for tables with 
  70. /// non-segmented "int" keys
  71. int BDB_IntCompare(DB*, const DBT* val1, const DBT* val2);
  72. /// Simple and fast comparison function for tables with 
  73. /// non-segmented "short int" keys
  74. int BDB_Int2Compare(DB*, const DBT* val1, const DBT* val2);
  75. /// Simple and fast comparison function for tables with 
  76. /// non-segmented "unsigned char" keys
  77. int BDB_UCharCompare(DB*, const DBT* val1, const DBT* val2);
  78. /// Simple and fast comparison function for tables with 
  79. /// non-segmented "float" keys
  80. int BDB_FloatCompare(DB*, const DBT* val1, const DBT* val2);
  81. /// Simple and fast comparison function for tables with 
  82. /// non-segmented "double" keys
  83. int BDB_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
  84. /// Simple and fast comparison function for tables with 
  85. /// non-segmented "C string" keys
  86. int BDB_StringCompare(DB*, const DBT* val1, const DBT* val2);
  87. /// Simple and fast comparison function for tables with 
  88. /// non-segmented length prefixed string keys
  89. int BDB_LStringCompare(DB*, const DBT* val1, const DBT* val2);
  90. /// Simple and fast comparison function for tables with 
  91. /// non-segmented "case insensitive C string" keys
  92. int BDB_StringCaseCompare(DB*, const DBT* val1, const DBT* val2);
  93. /// General purpose DBD comparison function
  94. int BDB_Compare(DB* db, const DBT* val1, const DBT* val2);
  95. /// Simple and fast comparison function for tables with 
  96. /// non-segmented "unsigned int" keys.
  97. /// Used when the data file is in a different byte order architecture.
  98. int BDB_ByteSwap_UintCompare(DB*, const DBT* val1, const DBT* val2);
  99. /// Simple and fast comparison function for tables with 
  100. /// non-segmented "int" keys
  101. /// Used when the data file is in a different byte order architecture.
  102. int BDB_ByteSwap_IntCompare(DB*, const DBT* val1, const DBT* val2);
  103. /// Simple and fast comparison function for tables with 
  104. /// non-segmented "short int" keys
  105. /// Used when the data file is in a different byte order architecture.
  106. int BDB_ByteSwap_Int2Compare(DB*, const DBT* val1, const DBT* val2);
  107. /// Simple and fast comparison function for tables with 
  108. /// non-segmented "float" keys
  109. /// Used when the data file is in a different byte order architecture.
  110. int BDB_ByteSwap_FloatCompare(DB*, const DBT* val1, const DBT* val2);
  111. /// Simple and fast comparison function for tables with 
  112. /// non-segmented "double" keys
  113. /// Used when the data file is in a different byte order architecture.
  114. int BDB_ByteSwap_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
  115. }
  116. class CBDB_BufferManager;
  117. class CBDB_Field;
  118. class CBDB_File;
  119. class CBDB_FileCursor;
  120. class CBDB_FC_Condition;
  121. /// BDB Data Field interface definition.
  122. ///
  123. /// Every relational table in BDB library consists of fields, supporting
  124. /// basic IBDB_Field interface
  125. class NCBI_BDB_EXPORT IBDB_Field
  126. {
  127. public:
  128.     virtual ~IBDB_Field();
  129.     /// Comparison function. p1 and p2 are void pointers on field buffers.
  130.     /// Positive if p1>p2, zero if p1==p2, negative if p1<p2.
  131.     /// NOTE:  both buffers can be unaligned. 
  132.     /// byte_swapped TRUE indicates that buffers values are in 
  133.     /// a different byte order architecture
  134.     virtual int         Compare(const void* p1, 
  135.                                 const void* p2,
  136.                                 bool byte_swapped) const = 0;
  137.     /// Return current effective size of the buffer.
  138.     virtual size_t      GetDataLength(const void* buf) const = 0;
  139.     /// Set minimal possible value for the field type
  140. virtual void        SetMinVal() = 0;
  141.     /// Set maximum possible value for the field type
  142. virtual void        SetMaxVal() = 0;
  143. };
  144. /// BDB Data Field conversion interface definition.
  145. /// All interface functions by default throw "bad conversion" exception.
  146. class NCBI_BDB_EXPORT IBDB_FieldConvert
  147. {
  148. public:
  149.     virtual ~IBDB_FieldConvert() {}
  150.     virtual void SetInt(int)
  151.         { BDB_THROW(eType, "Bad conversion"); }
  152.     virtual void SetUint(unsigned)  // ???
  153.         { BDB_THROW(eType, "Bad conversion"); }
  154.     virtual void SetString(const char*)
  155.         { BDB_THROW(eType, "Bad conversion"); }
  156.     virtual void SetStdString(const string&)
  157.         { BDB_THROW(eType, "Bad conversion"); }
  158.     virtual void SetFloat(float)
  159.         { BDB_THROW(eType, "Bad conversion"); }
  160.     virtual void SetDouble(double)
  161.         { BDB_THROW(eType, "Bad conversion"); }
  162.     virtual string GetString() const = 0;
  163.     virtual void ToString(string& str) const = 0;
  164. };
  165. /// Interface definition class for field construction.
  166. /// Used for interfaces' "access rights management".
  167. class CBDB_FieldInterfaces : public  IBDB_Field,
  168.                              public  IBDB_FieldConvert
  169. {
  170.     friend class CBDB_FileCursor;
  171. };
  172. /// Base class for constructing BDB fields. Implements field buffer pointer.
  173. ///
  174. /// All DBD field types do not own their buffers. 
  175. /// It works as a pointer on external memory kept by the record manager
  176. /// (CBDB_FieldBuf). Class cannot be used independently without record manager.
  177. class NCBI_BDB_EXPORT CBDB_Field : public CBDB_FieldInterfaces
  178. {
  179. public:
  180.     /// Length based classificator for fields (fixed-variable)
  181.     enum ELengthType {
  182.         eFixedLength,    //!< fixed-length (like int)
  183.         eVariableLength  //!< variable-length (like string)
  184.     };
  185.     CBDB_Field(ELengthType length_type = eFixedLength);
  186.     virtual ~CBDB_Field() {}
  187.     
  188.     /// Virtual constructor - class factory for BDB fields.
  189.     /// Default (zero) value of 'buf-len' uses GetBufferSize().
  190.     /// For fixed length fields this buf_size parameter has no effect
  191.     virtual CBDB_Field* Construct(size_t buf_size = 0) const = 0;
  192.     /// Return address to the type specific comparison function
  193.     /// By default it's universal BDB_Compare
  194.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const;
  195.     /// Return TRUE if field can be NULL
  196.     bool IsNullable() const;
  197.     /// Assign field value to NULL
  198.     void SetNull();
  199.     /// Return TRUE if field is NULL
  200.     bool IsNull() const;
  201.     /// Return symbolic name for the field
  202.     const string& GetName() const;
  203.     /// Get pointer to the data. NULL if not yet attached.
  204.     const void* GetBuffer() const;
  205.     /// Get pointer to the data. NULL if not yet attached.
  206.     void*       GetBuffer();
  207.     /// Return maximum possible buffer length
  208.     size_t GetBufferSize() const;
  209.     /// Get length of the actual data
  210.     size_t GetLength() const;
  211. protected:
  212.     /// Field comparison function
  213.     int CompareWith(const CBDB_Field& field) const;
  214.     /// Copies field value from another field.
  215.     /// The field type MUST be the same, or an exception will be thrown.
  216.     void CopyFrom(const CBDB_Field& src);
  217.     // Buffer management functions:
  218.     /// Return TRUE if it is a variable length variable (like string)
  219.     bool IsVariableLength() const;
  220.     /// Return TRUE if external buffer has already been attached
  221.     bool IsBufferAttached() const;
  222.     /// RTTI based check if fld is of the same type
  223.     bool IsSameType(const CBDB_Field& field) const;
  224.     /// Return TRUE if field belongs to a file with an alternative
  225.     /// byte order
  226.     bool IsByteSwapped() const;
  227.     /// Mark field as "NULL" capable.
  228.     void SetNullable();
  229.     /// Set "is NULL" flag to FALSE
  230.     void SetNotNull();
  231.     /// Set symbolic name for the field
  232.     void SetName(const char* name);
  233.     /// Set field position in the buffer manager
  234.     void SetBufferIdx(unsigned int idx);
  235. protected:
  236.     /// Unpack the buffer which contains this field (using CBDB_BufferManager).
  237.     /// Return new pointer to the field data -- located in the unpacked buffer.
  238.     void*  Unpack();
  239.     /// Set external buffer pointer and length. 
  240.     /// Zero 'buf_size' means GetBufferSize() is used to obtain the buf. size.
  241.     void  SetBuffer(void* buf, size_t buf_size = 0);
  242.     /// Set the buffer size.
  243.     void  SetBufferSize(size_t size);
  244.     /// Set CBDB_BufferManager -- which works as a memory manager for BDB fields.
  245.     void  SetBufferManager(CBDB_BufferManager* owner);
  246.     /// Copy buffer value from the external source
  247.     void CopyFrom(const void* src_buf);
  248. private:
  249.     CBDB_Field& operator= (const CBDB_Field& data);
  250.     CBDB_Field(const CBDB_Field& data);
  251. protected:
  252.     CBDB_BufferManager*  m_BufferManager;
  253.     struct {
  254.         unsigned VariableLength : 1;
  255.         unsigned Attached       : 1;
  256.         unsigned Nullable       : 1;
  257.     } m_Flags;
  258. private:
  259.     void*      m_Buffer;       // Pointer to the field data (in buf. mgr.)
  260.     size_t     m_BufferSize;   // Field data buffer capacity
  261.     unsigned   m_BufferIdx;    // Fields' position in the managing buffer
  262.     string     m_Name;         // Field's symbolic name
  263.     // Friends
  264.     friend class CBDB_BufferManager;
  265.     friend class CBDB_File;
  266.     friend class CBDB_BLobFile;
  267. };
  268. /// Template class for building simple scalar data fields. 
  269. /// (int, float, double)
  270. template<typename T>
  271. class CBDB_FieldSimple : public CBDB_Field
  272. {
  273. public:
  274.     CBDB_FieldSimple()
  275.     : CBDB_Field(eFixedLength)
  276.     {
  277.         SetBufferSize(sizeof(T));
  278.     }
  279.     void SetField(const CBDB_FieldSimple& field)
  280.     {
  281.         if ( field.IsNull() ) {
  282.             SetNull();
  283.         } else {
  284.             if (IsByteSwapped() != field.IsByteSwapped()) {
  285.                 BDB_THROW(eInvalidValue, "Byte order incompatibility");
  286.             }
  287.             ::memcpy(GetBuffer(), field.GetBuffer(), sizeof(T));
  288.             SetNotNull();
  289.         }
  290.     }
  291.     // IDBD_Field implementation
  292.     virtual int Compare(const void* p1, 
  293.                         const void* p2, 
  294.                         bool/* byte_swapped*/) const
  295.     {
  296.         // Default implementation ignores byte swapping
  297.         T v1, v2;
  298.         ::memcpy(&v1, p1, sizeof(v1));
  299.         ::memcpy(&v2, p2, sizeof(v2));
  300.         if (v1 < v2) return -1;
  301.         if (v2 < v1) return 1;
  302.         return 0;
  303.     }
  304.     virtual size_t GetDataLength(const void* /*buf*/) const
  305.     {
  306.         return sizeof(T);
  307.     }
  308. };
  309. /// Template class for building simple scalar integer compatible data fields.
  310. /// (int, short, char)
  311. template<typename T>
  312. class CBDB_FieldSimpleInt : public CBDB_FieldSimple<T>
  313. {
  314. public:
  315.     CBDB_FieldSimpleInt() : CBDB_FieldSimple<T>() {}
  316.     void Set(T val)
  317.     {
  318.         if (this->IsByteSwapped()) {
  319.             if (sizeof(T) == 2) {
  320.                 CByteSwap::PutInt2((unsigned char*)this->GetBuffer(),
  321.                                    (Int2) val);
  322.             } else
  323.             if (sizeof(T) == 4) {
  324.                 CByteSwap::PutInt4((unsigned char*)this->GetBuffer(),
  325.                                    (Int4) val);
  326.             } else
  327.             if (sizeof(T) == 8) {
  328.                 CByteSwap::PutInt8((unsigned char*)this->GetBuffer(),
  329.                                    (Int8) val);
  330.             }
  331.             else {
  332.                 _ASSERT(0);
  333.             }
  334.         } else {
  335.             ::memcpy(this->GetBuffer(), &val, sizeof(T));
  336.         }
  337.         this->SetNotNull();
  338.     }
  339.     virtual void SetInt    (int          val)  { Set((T) val); }
  340.     virtual void SetUint   (unsigned int val)  { Set((T) val); }
  341.     virtual void SetString (const char*  val)
  342.     {
  343.         long v = ::atol(val);
  344.         Set((T) v);
  345.     }
  346.     virtual void SetStdString(const string& str) 
  347.     {
  348.         SetString(str.c_str());
  349.     }
  350.     virtual int Compare(const void* p1, 
  351.                         const void* p2,
  352.                         bool byte_swapped) const
  353.     {
  354.         if (!byte_swapped)
  355.             return CBDB_FieldSimple<T>::Compare(p1, p2, byte_swapped);
  356.         T v1, v2;
  357.         v1 = (T) CByteSwap::GetInt4((unsigned char*)p1);
  358.         v2 = (T) CByteSwap::GetInt4((unsigned char*)p2);
  359.         if (v1 < v2) return -1;
  360.         if (v2 < v1) return 1;
  361.         return 0;
  362.     }
  363.     
  364. virtual void SetMinVal()
  365.     {
  366.         Set(numeric_limits<T>::min());
  367.     }
  368. virtual void SetMaxVal()
  369.     {
  370.         Set(numeric_limits<T>::max());
  371.     }
  372. };
  373. /// Template class for building simple scalar floating point compatible fields.
  374. /// (float, double)
  375. ///
  376. template<typename T>
  377. class CBDB_FieldSimpleFloat : public CBDB_FieldSimple<T>
  378. {
  379. public:
  380.     CBDB_FieldSimpleFloat() : CBDB_FieldSimple<T>() {}
  381.     void Set(T val)
  382.     {
  383.         if (this->IsByteSwapped()) {
  384.             if (sizeof(T) == 4) {
  385.                 CByteSwap::PutFloat((unsigned char*)this->GetBuffer(), val);
  386.             } else
  387.             if (sizeof(T) == 8) {
  388.                 CByteSwap::PutDouble((unsigned char*)this->GetBuffer(), val);
  389.             }
  390.             else {
  391.                 _ASSERT(0);
  392.             }
  393.         } else {
  394.             ::memcpy(this->GetBuffer(), &val, sizeof(T));
  395.         }
  396.         this->SetNotNull();
  397.     }
  398.     virtual void SetInt    (int          val) { Set((T) val); }
  399.     virtual void SetUint   (unsigned int val) { Set((T) val); }
  400.     virtual void SetString (const char*  val)
  401.     {
  402.         double v = ::atof(val);
  403.         Set((T) v);
  404.     }
  405.     virtual void SetStdString(const string& str)
  406.     {
  407.         SetString(str.c_str());
  408.     }
  409.     virtual void SetFloat (float  val) { Set((T) val); }
  410.     virtual void SetDouble(double val) { Set((T) val); }
  411. virtual void SetMinVal()
  412.     {
  413.         Set(numeric_limits<T>::min());
  414.     }
  415. virtual void SetMaxVal()
  416.     {
  417.         Set(numeric_limits<T>::max());
  418.     }
  419. };
  420. ///  Int4 field type
  421. ///
  422. class NCBI_BDB_EXPORT CBDB_FieldInt4 : public CBDB_FieldSimpleInt<Int4>
  423. {
  424. public:
  425.     const CBDB_FieldInt4& operator= (Int4 val)
  426.     {
  427.         Set(val);
  428.         return *this;
  429.     }
  430.     const CBDB_FieldInt4& operator= (const CBDB_FieldInt4& val)
  431.     {
  432.         Set(val);
  433.         return *this;
  434.     }
  435.     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
  436.     {
  437.         return new CBDB_FieldInt4();
  438.     }
  439.     Int4 Get() const
  440.     {
  441.         Int4  v;
  442.         if (IsByteSwapped()) {
  443.             v = CByteSwap::GetInt4((unsigned char*)GetBuffer());
  444.         } else {
  445.             ::memcpy(&v, GetBuffer(), sizeof(Int4));
  446.         }
  447.         return v;
  448.     }
  449.     virtual string GetString() const
  450.     {
  451.         Int4  v = Get();
  452.         return NStr::IntToString(v);
  453.     }
  454.     virtual void ToString(string& str) const
  455.     {
  456.         Int4 v = Get();
  457.         NStr::IntToString(str, v);
  458.     }
  459.     operator Int4() const 
  460.     { 
  461.         return Get(); 
  462.     }
  463.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
  464.     {
  465.         if (byte_swapped)
  466.             return BDB_ByteSwap_IntCompare;
  467.         return BDB_IntCompare;
  468.     } 
  469.     virtual int Compare(const void* p1, 
  470.                         const void* p2,
  471.                         bool byte_swapped) const
  472.     {
  473.         if (!byte_swapped)
  474.             return CBDB_FieldSimpleInt<Int4>::Compare(p1, p2, byte_swapped);
  475.         Int4 v1, v2;
  476.         v1 = CByteSwap::GetInt4((unsigned char*)p1);
  477.         v2 = CByteSwap::GetInt4((unsigned char*)p2);
  478.         if (v1 < v2) return -1;
  479.         if (v2 < v1) return 1;
  480.         return 0;
  481.     }
  482. };
  483. ///  Int2 field type
  484. ///
  485. class NCBI_BDB_EXPORT CBDB_FieldInt2 : public CBDB_FieldSimpleInt<Int2>
  486. {
  487. public:
  488.     const CBDB_FieldInt2& operator= (Int2 val)
  489.     {
  490.         Set(val);
  491.         return *this;
  492.     }
  493.     const CBDB_FieldInt2& operator= (const CBDB_FieldInt2& val)
  494.     {
  495.         Set(val);
  496.         return *this;
  497.     }
  498.     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
  499.     {
  500.         return new CBDB_FieldInt2();
  501.     }
  502.     Int2 Get() const
  503.     {
  504.         Int2  v;
  505.         if (IsByteSwapped()) {
  506.             v = CByteSwap::GetInt2((unsigned char*)GetBuffer());
  507.         } else {
  508.             ::memcpy(&v, GetBuffer(), sizeof(Int2));
  509.         }
  510.         return v;
  511.     }
  512.     virtual string GetString() const
  513.     {
  514.         Int4  v = Get();
  515.         return NStr::IntToString(v);
  516.     }
  517.     virtual void ToString(string& str) const
  518.     {
  519.         Int4 v = Get();
  520.         NStr::IntToString(str, v);
  521.     }
  522.     operator Int2() const 
  523.     { 
  524.         return Get(); 
  525.     }
  526.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
  527.     {
  528.         if (byte_swapped)
  529.             return BDB_ByteSwap_Int2Compare;
  530.         return BDB_Int2Compare;
  531.     } 
  532.     virtual int Compare(const void* p1, 
  533.                         const void* p2,
  534.                         bool byte_swapped) const
  535.     {
  536.         if (!byte_swapped)
  537.             return CBDB_FieldSimpleInt<Int2>::Compare(p1, p2, byte_swapped);
  538.         Int2 v1, v2;
  539.         v1 = CByteSwap::GetInt2((unsigned char*)p1);
  540.         v2 = CByteSwap::GetInt2((unsigned char*)p2);
  541.         if (v1 < v2) return -1;
  542.         if (v2 < v1) return 1;
  543.         return 0;
  544.     }
  545. };
  546. /// Char field type
  547. ///
  548. class CBDB_FieldUChar:public CBDB_FieldSimpleInt<unsigned char>
  549. {
  550. public:
  551.     const CBDB_FieldUChar& operator = (unsigned char val) 
  552.     { 
  553.         Set(val); 
  554.         return *this; 
  555.     }
  556.     const CBDB_FieldUChar& operator = (const CBDB_FieldUChar& val) 
  557.     { 
  558.         Set(val); 
  559.         return *this; 
  560.     }
  561.     virtual CBDB_Field * Construct(size_t) const
  562.     { 
  563.         return new CBDB_FieldUChar(); 
  564.     }
  565.     
  566.     unsigned char Get() const  
  567.     { 
  568.         return *(const unsigned char*)GetBuffer(); 
  569.     }
  570.     operator char () const  
  571.     { 
  572.         return Get(); 
  573.     }
  574.     virtual string GetString() const  
  575.     { 
  576.         return string(1, Get()); 
  577.     }
  578.     virtual void ToString(string& s) const 
  579.     { 
  580.         s.assign(1, Get()); 
  581.     }
  582.     virtual BDB_CompareFunction GetCompareFunction(bool) const 
  583.     { 
  584.         return BDB_UCharCompare; 
  585.     }
  586.     
  587.     virtual int Compare(const void * p1, 
  588.                         const void * p2, 
  589.                         bool) const 
  590.     { 
  591.         const unsigned char& c1 = *(const unsigned char *)p1;
  592.         const unsigned char& c2 = *(const unsigned char *)p2;
  593.         
  594.         return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
  595.     }
  596. };
  597. ///  Uint4 field type
  598. ///
  599. class NCBI_BDB_EXPORT CBDB_FieldUint4 : public CBDB_FieldSimpleInt<Uint4>
  600. {
  601. public:
  602.     const CBDB_FieldUint4& operator= (Uint4 val)
  603.     {
  604.         Set(val);
  605.         return *this;
  606.     }
  607.     const CBDB_FieldUint4& operator= (const CBDB_FieldUint4& val)
  608.     {
  609.         Set(val);
  610.         return *this;
  611.     }
  612.     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
  613.     {
  614.         return new CBDB_FieldUint4();
  615.     }
  616.     Uint4 Get() const
  617.     {
  618.         Uint4  v;
  619.         if (IsByteSwapped()) {
  620.             v = (Uint4)CByteSwap::GetInt4((unsigned char*)GetBuffer());
  621.         } else {
  622.             ::memcpy(&v, GetBuffer(), sizeof(Uint4));
  623.         }
  624.         return v;
  625.     }
  626.     virtual string GetString() const
  627.     {
  628.         Uint4  v = Get();
  629.         return NStr::UIntToString(v);
  630.     }
  631.     virtual void ToString(string& str) const
  632.     {
  633.         Uint4 v = Get();
  634.         NStr::UIntToString(str, v);
  635.     }
  636.     operator Uint4() const
  637.     { 
  638.         return Get(); 
  639.     }
  640.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
  641.     {
  642.         if (byte_swapped)
  643.             return BDB_ByteSwap_UintCompare;
  644.         return BDB_UintCompare;
  645.     } 
  646.     virtual int Compare(const void* p1, 
  647.                         const void* p2,
  648.                         bool byte_swapped) const
  649.     {
  650.         if (!byte_swapped)
  651.             return CBDB_FieldSimpleInt<Uint4>::Compare(p1, p2, byte_swapped);
  652.         Uint4 v1, v2;
  653.         v1 = (Uint4)CByteSwap::GetInt4((unsigned char*)p1);
  654.         v2 = (Uint4)CByteSwap::GetInt4((unsigned char*)p2);
  655.         if (v1 < v2) return -1;
  656.         if (v2 < v1) return 1;
  657.         return 0;
  658.     }
  659. };
  660. ///  Float field type
  661. ///
  662. class NCBI_BDB_EXPORT CBDB_FieldFloat : public CBDB_FieldSimpleFloat<float>
  663. {
  664. public:
  665.     const CBDB_FieldFloat& operator= (float val)
  666.     {
  667.         Set(val);
  668.         return *this;
  669.     }
  670.     const CBDB_FieldFloat& operator= (const CBDB_FieldFloat& val)
  671.     {
  672.         Set(val);
  673.         return *this;
  674.     }
  675.     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
  676.     {
  677.         return new CBDB_FieldFloat();
  678.     }
  679.     float Get() const
  680.     {
  681.         float  v;
  682.         if (IsByteSwapped()) {
  683.             v = CByteSwap::GetFloat((unsigned char*)GetBuffer());
  684.         } else {
  685.             ::memcpy(&v, GetBuffer(), sizeof(float));
  686.         }
  687.         return v;
  688.     }
  689.     virtual string GetString() const
  690.     {
  691.         double v = Get();
  692.         return NStr::DoubleToString(v);
  693.     }
  694.     virtual void ToString(string& str) const
  695.     {
  696.         double v = Get();
  697.         NStr::DoubleToString(str, v);
  698.     }
  699.     operator float() const 
  700.     { 
  701.         return Get(); 
  702.     }
  703.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
  704.     {
  705.         if (byte_swapped)
  706.             return BDB_ByteSwap_FloatCompare;
  707.         return BDB_FloatCompare;
  708.     } 
  709.     virtual int Compare(const void* p1, 
  710.                         const void* p2,
  711.                         bool byte_swapped) const
  712.     {
  713.         if (!byte_swapped)
  714.             return CBDB_FieldSimpleFloat<float>::Compare(p1, p2, byte_swapped);
  715.         float v1, v2;
  716.         v1 = CByteSwap::GetFloat((unsigned char*)p1);
  717.         v2 = CByteSwap::GetFloat((unsigned char*)p2);
  718.         if (v1 < v2) return -1;
  719.         if (v2 < v1) return 1;
  720.         return 0;
  721.     }
  722. };
  723. ///  Double precision floating point field type
  724. ///
  725. class NCBI_BDB_EXPORT CBDB_FieldDouble : public CBDB_FieldSimpleFloat<double>
  726. {
  727. public:
  728.     const CBDB_FieldDouble& operator= (double val)
  729.     {
  730.         Set(val);
  731.         return *this;
  732.     }
  733.     const CBDB_FieldDouble& operator= (const CBDB_FieldDouble& val)
  734.     {
  735.         Set(val);
  736.         return *this;
  737.     }
  738.     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
  739.     {
  740.         return new CBDB_FieldDouble();
  741.     }
  742.     double Get() const
  743.     {
  744.         double  v;
  745.         if (IsByteSwapped()) {
  746.             v = CByteSwap::GetDouble((unsigned char*)GetBuffer());
  747.         } else {
  748.             ::memcpy(&v, GetBuffer(), sizeof(double));
  749.         }
  750.         return v;
  751.     }
  752.     virtual string GetString() const
  753.     {
  754.         double v = Get();
  755.         return NStr::DoubleToString(v);
  756.     }
  757.     virtual void ToString(string& str) const
  758.     {
  759.         double v = Get();
  760.         NStr::DoubleToString(str, v);
  761.     }
  762.     operator double() const 
  763.     { 
  764.         return Get(); 
  765.     }
  766.     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
  767.     {
  768.         if (byte_swapped)
  769.             return BDB_ByteSwap_DoubleCompare;
  770.         return BDB_DoubleCompare;
  771.     }
  772.     virtual int Compare(const void* p1,
  773.                         const void* p2,
  774.                         bool byte_swapped) const
  775.     {
  776.         if (!byte_swapped)
  777.             return CBDB_FieldSimpleFloat<double>::Compare(p1, p2, byte_swapped);
  778.         double v1, v2;
  779.         v1 = CByteSwap::GetDouble((unsigned char*)p1);
  780.         v2 = CByteSwap::GetDouble((unsigned char*)p2);
  781.         if (v1 < v2) return -1;
  782.         if (v2 < v1) return 1;
  783.         return 0;
  784.     }
  785. };
  786. ///
  787. ///  String field type
  788. ///
  789. class NCBI_BDB_EXPORT CBDB_FieldStringBase : public CBDB_Field
  790. {
  791. public:
  792.     // if mute == true function do not report overflow condition, but just
  793.     // truncates the string value
  794.     enum EOverflowAction {
  795.         eThrowOnOverflow,
  796.         eTruncateOnOverflow
  797.     };
  798.     
  799. protected:
  800.     CBDB_FieldStringBase() : CBDB_Field(eVariableLength) {}
  801. };
  802. ///
  803. ///  String field type designed to work with C-strings (ASCIIZ)
  804. ///
  805. class NCBI_BDB_EXPORT CBDB_FieldString : public CBDB_FieldStringBase
  806. {
  807. public:
  808.     CBDB_FieldString();
  809.     // Class factory for string fields.
  810.     // Default (zero) value of 'buf_size' uses GetBufferSize().
  811.     virtual CBDB_Field* Construct(size_t buf_size) const
  812.     {
  813.         CBDB_FieldString* fld = new CBDB_FieldString();
  814.         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
  815.         return fld;
  816.     }
  817.     operator const char* () const;
  818.     const CBDB_FieldString& operator= (const CBDB_FieldString& str);
  819.     const CBDB_FieldString& operator= (const char*             str);
  820.     const CBDB_FieldString& operator= (const string&           str);
  821.     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
  822.     string Get() const { return string((const char*)GetBuffer()); }
  823.     virtual string GetString() const
  824.     {
  825.         return Get();
  826.     }
  827.     bool IsEmpty() const;
  828.     bool IsBlank() const;
  829.     // IField
  830.     virtual int         Compare(const void* p1, 
  831.                                 const void* p2, 
  832.                                 bool /* byte_swapped */) const;
  833.     virtual size_t      GetDataLength(const void* buf) const;
  834.     virtual void        SetMinVal();
  835.     virtual void        SetMaxVal();
  836.     virtual void SetString(const char*);
  837.     virtual void SetStdString(const string& str)
  838.     {
  839.         SetString(str.c_str());
  840.     }
  841.     virtual void ToString(string& str) const
  842.     {
  843.         str = (const char*) GetBuffer();
  844.     }
  845.     virtual BDB_CompareFunction GetCompareFunction(bool) const
  846.     {
  847.         return BDB_StringCompare;
  848.     } 
  849. };
  850. ///  Case-insensitive (but case preserving) string field type 
  851. ///
  852. class NCBI_BDB_EXPORT CBDB_FieldStringCase : public CBDB_FieldString
  853. {
  854. public:
  855.     typedef CBDB_FieldString CParent;
  856.     explicit CBDB_FieldStringCase() : CBDB_FieldString() {}
  857.     // Accessors
  858.     operator const char* () const { return (const char*) GetBuffer(); }
  859.     const CBDB_FieldStringCase& operator= (const CBDB_FieldString& str)
  860.     {
  861.         Set(str);
  862.         return *this;
  863.     }
  864.     const CBDB_FieldStringCase& operator= (const CBDB_FieldStringCase& str)
  865.     {
  866.         Set(str);
  867.         return *this;
  868.     }
  869.     const CBDB_FieldStringCase& operator= (const char* str) 
  870.     { 
  871.         Set(str);
  872.         return *this;
  873.     }
  874.     const CBDB_FieldStringCase& operator= (const string& str) 
  875.     { 
  876.         Set(str.c_str());
  877.         return *this;
  878.     }
  879.     virtual int Compare(const void* p1, 
  880.                         const void* p2, 
  881.                         bool/* byte_swapped */) const
  882.     {
  883.         _ASSERT(p1 && p2);
  884.         return NStr::strcasecmp((const char*) p1, (const char*) p2);
  885.     }
  886.     virtual 
  887.     BDB_CompareFunction GetCompareFunction(bool /* byte_swapped */) const
  888.     {
  889.         return BDB_StringCaseCompare;
  890.     } 
  891. };
  892. ///
  893. ///  Length prefised string field type
  894. ///
  895. class NCBI_BDB_EXPORT CBDB_FieldLString : public CBDB_FieldStringBase
  896. {
  897. public:
  898.     CBDB_FieldLString();
  899.     // Class factory for string fields.
  900.     // Default (zero) value of 'buf_size' uses GetBufferSize().
  901.     virtual CBDB_Field* Construct(size_t buf_size) const;
  902. //    operator const char* () const;
  903.     operator string() const { return GetString(); }
  904.     const CBDB_FieldLString& operator= (const CBDB_FieldLString& str);
  905.     const CBDB_FieldLString& operator= (const char*             str);
  906.     const CBDB_FieldLString& operator= (const string&           str);
  907.     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
  908.     string Get() const;
  909.     virtual string GetString() const
  910.     {
  911.         return Get();
  912.     }
  913.     bool IsEmpty() const;
  914.     bool IsBlank() const;
  915.     // IField
  916.     virtual int         Compare(const void* p1, 
  917.                                 const void* p2, 
  918.                                 bool /* byte_swapped */) const;
  919.     virtual size_t      GetDataLength(const void* buf) const;
  920.     virtual void        SetMinVal();
  921.     virtual void        SetMaxVal();
  922.     virtual void SetString(const char*);
  923.     virtual void SetStdString(const string& str);
  924.     virtual BDB_CompareFunction GetCompareFunction(bool) const
  925.     {
  926.         return BDB_LStringCompare;
  927.     }
  928.     virtual void ToString(string& str) const;
  929. protected:
  930.     const unsigned char* GetLString(const unsigned char* str, 
  931.                                     bool                 check_legacy, 
  932.                                     int*                 str_len) const;
  933. };
  934. /// BDB Data Field Buffer manager class. 
  935. /// For internal use in BDB library.
  936. ///
  937. /// @internal
  938. class NCBI_BDB_EXPORT CBDB_BufferManager
  939. {
  940. public:
  941.     /// Return number of fields attached using function Bind
  942.     unsigned int FieldCount() const;
  943.     const CBDB_Field& GetField(unsigned int idx) const;
  944.     CBDB_Field&       GetField(unsigned int idx);
  945.     /// Find the field with the specified name. Name is case insensitive.
  946.     /// @return -1 if field cannot be found
  947.     int GetFieldIndex(const string& name) const;
  948.     /// Return TRUE if buffer is in a non-native byte order
  949.     bool IsByteSwapped() const { return m_ByteSwapped; }
  950.     /// Sets maximum number of fields participating in comparison
  951.     /// Should be less than total number of fields in the buffer
  952.     void SetFieldCompareLimit(unsigned int n_fields);
  953.     /// Get number of fields in comparison.
  954.     /// 0 - means no forced limit
  955.     unsigned int GetFieldCompareLimit() const;
  956.     /// Return TRUE if buffer l-strings should check about legacy
  957.     /// c-str compatibility
  958.     bool IsLegacyStrings() const { return m_LegacyString; }
  959.     /// Get DBT.size of the parent file (key or data area)
  960.     /// (Set by CBDB_File after read)
  961.     size_t GetDBT_Size() const { return m_DBT_Size; }
  962.     ~CBDB_BufferManager();
  963. protected:
  964.     CBDB_BufferManager();
  965.     /// Create internal data buffer, assign places in this buffer to the fields
  966.     void Construct();
  967.     /// Set minimum possible value to buffer fields from 'idx_from' to 'idx_to'
  968.     void SetMinVal(unsigned int idx_from, unsigned int idx_to);
  969.     /// Set maximum possible value to buffer fields from 'idx_from' to 'idx_to'
  970.     void SetMaxVal(unsigned int idx_from, unsigned int idx_to);
  971.     /// Attach 'field' to the buffer.
  972.     /// NOTE: buffer manager will not own the attached object, nor will it
  973.     ///       keep ref counters or do any other automagic memory management.
  974.     void Bind(CBDB_Field* field, ENullable is_nullable = eNotNullable);
  975.     /// Duplicate (dynamic allocation is used) all fields from 'buf_mgr' and
  976.     /// bind them to the this buffer manager. Field values are not copied.
  977.     /// NOTE: CBDB_BufferManager does not own or deallocate fields, 
  978.     ///       caller is responsible for deallocation.
  979.     void CopyFieldsFrom(const CBDB_BufferManager& buf_mgr);
  980.     /// Copy all field values from the 'buf_mgr'.
  981.     void DuplicateStructureFrom(const CBDB_BufferManager& buf_mgr);
  982.     /// Compare fields of this buffer with those of 'buf_mgr' using
  983.     /// CBDB_Field::CompareWith().
  984.     /// Optional 'n_fields' parameter used when we want to compare only
  985.     /// several first fields instead of all.
  986.     int Compare(const CBDB_BufferManager& buf_mgr,
  987.                 unsigned int              n_fields = 0) const;
  988.     /// Return TRUE if any field bound to this buffer manager has variable
  989.     /// length (i.e. packable)
  990.     bool IsPackable() const;
  991.     /// Check if all NOT NULLABLE fields were assigned.
  992.     /// Throw an exception if not.
  993.     void CheckNullConstraint() const;
  994.     void ArrangePtrsUnpacked();
  995.     void ArrangePtrsPacked();
  996.     void Clear();
  997.     unsigned Pack();
  998.     unsigned Unpack();
  999.     /// Pack the buffer and initialize DBT structure for write operation
  1000.     void PrepareDBT_ForWrite(DBT* dbt);
  1001.     /// Initialize DBT structure for read operation.
  1002.     void PrepareDBT_ForRead(DBT* dbt);
  1003.     /// Calculate buffer size
  1004.     size_t ComputeBufferSize() const;
  1005.     /// Return TRUE if buffer can carry NULL fields
  1006.     bool IsNullable() const;
  1007.     /// Set byte swapping flag for the buffer
  1008.     void SetByteSwapped(bool byte_swapped) { m_ByteSwapped = byte_swapped; }
  1009.     /// Mark buffer as "NULL fields ready".
  1010.     /// NOTE: Should be called before buffer construction.
  1011.     void SetNullable();
  1012.     void SetNull(unsigned int field_idx, bool value);
  1013.     bool IsNull (unsigned int field_idx) const;
  1014.     size_t ComputeNullSetSize() const;
  1015.     bool   TestNullBit(unsigned int idx) const;
  1016.     void   SetNullBit (unsigned int idx, bool value);
  1017.     void   SetAllNull();
  1018.     /// Return buffer compare function
  1019.     BDB_CompareFunction GetCompareFunction() const;
  1020.     /// Set C-str detection
  1021.     void SetLegacyStringsCheck(bool value) { m_LegacyString = value; }
  1022.     void SetDBT_Size(size_t size) { m_DBT_Size = size; }
  1023. private:
  1024.     CBDB_BufferManager(const CBDB_BufferManager&);
  1025.     CBDB_BufferManager& operator= (const CBDB_BufferManager&);
  1026. private:
  1027.     vector<CBDB_Field*>     m_Fields;
  1028.     /// Array of pointers to the fields' data
  1029.     vector<void*>           m_Ptrs;        
  1030.     char*                   m_Buffer;
  1031.     size_t                  m_BufferSize;
  1032.     size_t                  m_PackedSize;
  1033.     size_t                  m_DBT_Size;
  1034.     bool                    m_Packable;
  1035.     /// TRUE if buffer is in a non-native arch.
  1036.     bool                    m_ByteSwapped; 
  1037.     /// TRUE if buffer can carry NULL fields
  1038.     bool                    m_Nullable;    
  1039.     /// size of the 'is NULL' bitset in bytes
  1040.     size_t                  m_NullSetSize; 
  1041.     /// Number of fields in key comparison
  1042.     unsigned int            m_CompareLimit;
  1043.     /// Flag to check for legacy string compatibility
  1044.     bool                    m_LegacyString;
  1045. private:
  1046.     friend class CBDB_Field;
  1047.     friend class CBDB_BLobFile;
  1048.     friend class CBDB_File;
  1049.     friend class CBDB_FileCursor;
  1050.     friend class CBDB_FC_Condition;
  1051. };
  1052. /* @} */
  1053. /////////////////////////////////////////////////////////////////////////////
  1054. //  IMPLEMENTATION of INLINE functions
  1055. /////////////////////////////////////////////////////////////////////////////
  1056. /////////////////////////////////////////////////////////////////////////////
  1057. //  CBDB_Field::
  1058. //
  1059. inline bool CBDB_Field::IsVariableLength() const
  1060. {
  1061.     return m_Flags.VariableLength == 1;
  1062. }
  1063. inline size_t CBDB_Field::GetBufferSize() const
  1064. {
  1065.     return m_BufferSize;
  1066. }
  1067. inline bool CBDB_Field::IsBufferAttached() const
  1068. {
  1069.     return m_Flags.Attached == 1;
  1070. }
  1071. inline bool CBDB_Field::IsNullable() const
  1072. {
  1073.     return m_Flags.Nullable == 1;
  1074. }
  1075. inline void CBDB_Field::SetNullable()
  1076. {
  1077.     m_Flags.Nullable = 1;
  1078. }
  1079. inline void CBDB_Field::SetNotNull()
  1080. {
  1081.     m_BufferManager->SetNull(m_BufferIdx, false);
  1082. }
  1083. inline void CBDB_Field::SetNull()
  1084. {
  1085.     _ASSERT(m_BufferManager->IsNullable());
  1086.     m_BufferManager->SetNull(m_BufferIdx, true);
  1087. }
  1088. inline bool CBDB_Field::IsNull() const
  1089. {
  1090.     return m_BufferManager->IsNull(m_BufferIdx);
  1091. }
  1092. inline void* CBDB_Field::Unpack()
  1093. {
  1094.     _ASSERT(m_BufferManager);
  1095.     m_BufferManager->Unpack();
  1096.     return GetBuffer();
  1097. }
  1098. inline void CBDB_Field::SetBuffer(void* buf, size_t buf_size)
  1099. {
  1100.     m_Buffer = buf; 
  1101.     if ( buf_size )
  1102.         m_BufferSize = buf_size;
  1103.     m_Flags.Attached = 1;
  1104. }
  1105. inline void CBDB_Field::SetBufferSize(size_t buf_size)
  1106. {
  1107.     _ASSERT(buf_size != 0);
  1108.     m_BufferSize = buf_size;
  1109. }
  1110. inline void CBDB_Field::SetBufferIdx(unsigned int idx)
  1111. {
  1112.     m_BufferIdx = idx;
  1113. }
  1114. inline const void* CBDB_Field::GetBuffer() const
  1115. {
  1116.     return m_Buffer;
  1117. }
  1118. inline void* CBDB_Field::GetBuffer() 
  1119. {
  1120.     return m_Buffer;
  1121. }
  1122. inline void CBDB_Field::SetBufferManager(CBDB_BufferManager* owner)
  1123. {
  1124.     _ASSERT(owner);
  1125.     m_BufferManager = owner;
  1126. }
  1127. inline size_t CBDB_Field::GetLength() const
  1128. {
  1129.     return GetDataLength(m_Buffer);
  1130. }
  1131. inline int CBDB_Field::CompareWith(const CBDB_Field& field) const
  1132. {
  1133.     bool byte_swapped = m_BufferManager->IsByteSwapped();
  1134.     return Compare(GetBuffer(), field.GetBuffer(), byte_swapped);
  1135. }
  1136. inline bool CBDB_Field::IsSameType(const CBDB_Field& field) const
  1137. {
  1138.     try {
  1139.         const type_info& t1 = typeid(*this);
  1140.         const type_info& t2 = typeid(field);
  1141.         return (t1 == t2) != 0;
  1142.     } catch (...) {
  1143.     }
  1144.     return false;
  1145. }
  1146. inline void CBDB_Field::CopyFrom(const CBDB_Field& src)
  1147. {
  1148.     if (this == &src)
  1149.         return;
  1150.     if ( !IsSameType(src) ) {
  1151.         BDB_THROW(eType, "Wrong field type");
  1152.     }
  1153.     CopyFrom(src.GetBuffer());
  1154. }
  1155. inline void CBDB_Field::CopyFrom(const void* src_buf)
  1156. {
  1157.     _ASSERT(src_buf);
  1158.     void* dst_ptr = Unpack();
  1159.     _ASSERT(dst_ptr);
  1160.     size_t max_len  = GetBufferSize();
  1161.     size_t copy_len = GetDataLength(src_buf);
  1162.     if (copy_len > max_len) {
  1163.         BDB_THROW(eOverflow, "Cannot copy. Data length exceeds max value");
  1164.     }
  1165.     ::memcpy(dst_ptr, src_buf, copy_len);
  1166. }
  1167. inline const string& CBDB_Field::GetName() const
  1168. {
  1169.     return m_Name;
  1170. }
  1171. inline void CBDB_Field::SetName(const char* name)
  1172. {
  1173.     _ASSERT(name);
  1174.     m_Name = name;
  1175. }
  1176. inline bool CBDB_Field::IsByteSwapped() const 
  1177.     return m_BufferManager->IsByteSwapped(); 
  1178. }
  1179. /////////////////////////////////////////////////////////////////////////////
  1180. //  CBDB_FieldString::
  1181. //
  1182. inline CBDB_FieldString::CBDB_FieldString()
  1183.     : CBDB_FieldStringBase()
  1184. {
  1185.     SetBufferSize(256);
  1186. }
  1187. inline CBDB_FieldString::operator const char* () const
  1188. {
  1189.     const char* str = (const char*) GetBuffer();
  1190.     _ASSERT(str);
  1191.     return str;
  1192. }
  1193. inline 
  1194. const CBDB_FieldString&
  1195. CBDB_FieldString::operator= (const CBDB_FieldString& str)
  1196. {
  1197.     if (this == &str)
  1198.         return *this;
  1199.     size_t len = str.GetLength();
  1200.     if (len > GetBufferSize()) {
  1201.         // TODO: allow partial string assignment?
  1202.         BDB_THROW(eOverflow, "String field overflow.");
  1203.     }
  1204.     Unpack();
  1205.     ::strcpy((char*)GetBuffer(), (const char*) str);
  1206.     if ( str.IsNull() ) {
  1207.         SetNull();
  1208.     } else {
  1209.         SetNotNull();
  1210.     }
  1211.     return *this;
  1212. }
  1213. inline
  1214. void CBDB_FieldString::Set(const char* str, EOverflowAction if_overflow)
  1215. {
  1216.     if ( !str )
  1217.         str = kEmptyCStr;
  1218.     size_t new_len = ::strlen(str) + 1;
  1219.     // check overflow
  1220.     if (new_len > GetBufferSize()) {
  1221.         if (if_overflow == eTruncateOnOverflow) {
  1222.             new_len = GetBufferSize();
  1223.         } else {
  1224.             string message("String field overflow."); 
  1225.             // TODO: add info what caused overflow, what length expected
  1226.             BDB_THROW(eOverflow, message);
  1227.         }
  1228.     }
  1229.     Unpack();
  1230.     ::memcpy(GetBuffer(), str, new_len);
  1231.     SetNotNull();
  1232. }
  1233. inline
  1234. void CBDB_FieldString::SetString(const char* str)
  1235. {
  1236.     operator=(str);
  1237. }
  1238. inline int CBDB_FieldString::Compare(const void* p1, 
  1239.                                      const void* p2, 
  1240.                                      bool /*byte_swapped*/) const
  1241. {
  1242.     _ASSERT(p1 && p2);
  1243.     return ::strcmp((const char*) p1, (const char*) p2);
  1244. }
  1245. inline void CBDB_FieldString::SetMinVal()
  1246. {
  1247.     ((char*) Unpack())[0] = '';
  1248. }
  1249. inline void CBDB_FieldString::SetMaxVal()
  1250. {
  1251.     void* buf = Unpack();
  1252.     // TODO:  find out whether xFF or 0x7F should be used, and how
  1253.     //        (because of possible 'signed char' comparison in strcmp()).
  1254.     ::memset(buf, 0x7F, GetBufferSize()); // 0xFF for international
  1255.     ((char*) buf)[GetBufferSize() - 1] = '';
  1256.     SetNotNull();
  1257. }
  1258. inline bool CBDB_FieldString::IsEmpty() const
  1259. {
  1260.     const char* str = (const char*) GetBuffer();
  1261.     _ASSERT(str);
  1262.     return !*str;
  1263. }
  1264. inline bool CBDB_FieldString::IsBlank() const
  1265. {
  1266.     const char* str = (const char*) GetBuffer();
  1267.     _ASSERT(str);
  1268.     for (;  *str;  ++str) {
  1269.         if ( !isspace(*str) )
  1270.             return false;
  1271.     }
  1272.     return true;
  1273. }
  1274. inline size_t CBDB_FieldString::GetDataLength(const void* buf) const
  1275. {
  1276.     _ASSERT(buf);
  1277.     return ::strlen((const char*) buf) + 1;
  1278. }
  1279. inline const CBDB_FieldString& CBDB_FieldString::operator= (const char* str)
  1280.     Set(str, eThrowOnOverflow); 
  1281.     return *this;
  1282. }
  1283. inline const CBDB_FieldString& CBDB_FieldString::operator= (const string& str)
  1284. {
  1285.     return this->operator=(str.c_str());
  1286. }
  1287. /////////////////////////////////////////////////////////////////////////////
  1288. //  CBDB_BufferManager::
  1289. //
  1290. inline const CBDB_Field& CBDB_BufferManager::GetField(unsigned int n) const
  1291. {
  1292.     return *m_Fields[n];
  1293. }
  1294. inline CBDB_Field& CBDB_BufferManager::GetField(unsigned int n)
  1295. {
  1296.     return *m_Fields[n];
  1297. }
  1298. inline unsigned int CBDB_BufferManager::FieldCount() const
  1299. {
  1300.     return (unsigned int)m_Fields.size();
  1301. }
  1302. inline bool CBDB_BufferManager::IsPackable() const
  1303. {
  1304.     return m_Packable;
  1305. }
  1306. inline bool CBDB_BufferManager::IsNullable() const
  1307. {
  1308.     return m_Nullable;
  1309. }
  1310. inline void CBDB_BufferManager::SetNullable()
  1311. {
  1312.     _ASSERT(m_Buffer == 0);
  1313.     m_Nullable = true;
  1314. }
  1315. inline size_t CBDB_BufferManager::ComputeNullSetSize() const
  1316. {
  1317.     if ( !IsNullable() )
  1318.         return 0;
  1319.     return (FieldCount() + 7) / 8;
  1320. }
  1321. inline bool CBDB_BufferManager::TestNullBit(unsigned int n) const
  1322. {
  1323.     _ASSERT(IsNullable());
  1324.     const unsigned char* buf  = (unsigned char*) m_Buffer;
  1325.     unsigned char        mask = (unsigned char) (1 << (n & 7));
  1326.     const unsigned char* offs = buf + (n >> 3);
  1327.     return ((*offs) & mask) != 0;
  1328. }
  1329. inline void CBDB_BufferManager::SetNullBit(unsigned int n, bool value)
  1330. {
  1331.     _ASSERT(IsNullable());
  1332.     unsigned char* buf  = (unsigned char*) m_Buffer;
  1333.     unsigned char  mask = (unsigned char) (1 << (n & 7));
  1334.     unsigned char* offs = buf + (n >> 3);
  1335.     (void) (value ? (*offs |= mask) : (*offs &= ~mask));
  1336. }
  1337. inline void CBDB_BufferManager::SetNull(unsigned int field_idx, bool value)
  1338. {
  1339.     if ( !IsNullable() )
  1340.         return;
  1341.     _ASSERT(field_idx < m_Fields.size());
  1342.     SetNullBit(field_idx, value);
  1343. }
  1344. inline void CBDB_BufferManager::SetAllNull()
  1345. {
  1346.     _ASSERT(IsNullable());
  1347.     unsigned char* buf = (unsigned char*) m_Buffer;
  1348.     for (size_t i = 0;  i < m_NullSetSize;  ++i) {
  1349.         *buf++ = (unsigned char) 0xFF;
  1350.     }
  1351. }
  1352. inline bool CBDB_BufferManager::IsNull(unsigned field_idx) const
  1353. {
  1354.     if ( !IsNullable() )
  1355.         return false;
  1356.     _ASSERT(field_idx < m_Fields.size());
  1357.     return TestNullBit(field_idx);
  1358. }
  1359. inline void CBDB_BufferManager::ArrangePtrsUnpacked()
  1360. {
  1361.     if ( !m_PackedSize )
  1362.         return;
  1363.     if ( !IsPackable() ) {
  1364.         m_PackedSize = 0;
  1365.         return;
  1366.     }
  1367.     for (size_t i = 0;  i < m_Fields.size();  ++i) {
  1368.         CBDB_Field& df = GetField((unsigned)i);
  1369.         df.SetBuffer(m_Ptrs[i]);
  1370.     }
  1371.     m_PackedSize = 0;  // not packed
  1372. }
  1373. inline void CBDB_BufferManager::Clear()
  1374. {
  1375.     ::memset(m_Buffer, 0, m_BufferSize);
  1376. ArrangePtrsUnpacked();
  1377. }
  1378. inline
  1379. void CBDB_BufferManager::CopyFieldsFrom(const CBDB_BufferManager& buf_mgr)
  1380. {
  1381.     unsigned int field_count = min(FieldCount(), buf_mgr.FieldCount());
  1382.     for (unsigned int i = 0;  i < field_count;  ++i) {
  1383.         CBDB_Field* fld = m_Fields[i];
  1384.         fld->CopyFrom(buf_mgr.GetField(i));
  1385.     }
  1386. }
  1387. inline
  1388. void CBDB_BufferManager::SetMinVal(unsigned int idx_from, unsigned int idx_to)
  1389. {
  1390.     _ASSERT(idx_to <= FieldCount());
  1391.     for ( ;  idx_from < idx_to;  ++idx_from) {
  1392.         CBDB_Field& fld = GetField(idx_from);
  1393.         fld.SetMinVal();
  1394.     }
  1395. }
  1396. inline
  1397. void CBDB_BufferManager::SetMaxVal(unsigned int idx_from, unsigned int idx_to)
  1398. {
  1399.     _ASSERT(idx_to <= FieldCount());
  1400.     for ( ;  idx_from < idx_to;  ++idx_from) {
  1401.         CBDB_Field& fld = GetField(idx_from);
  1402.         fld.SetMaxVal();
  1403.     }
  1404. }
  1405. inline 
  1406. void CBDB_BufferManager::SetFieldCompareLimit(unsigned int n_fields) 
  1407.     m_CompareLimit = n_fields; 
  1408. }
  1409. inline
  1410. unsigned int CBDB_BufferManager::GetFieldCompareLimit() const 
  1411.     return m_CompareLimit; 
  1412. }
  1413. // Delete all field objects bound to field buffer. 
  1414. // Should be used with extreme caution. After calling this buf object should
  1415. // never be used again. All fields bound to the buffer must be dynamically
  1416. // allocated.
  1417. inline 
  1418. void DeleteFields(CBDB_BufferManager& buf)
  1419. {
  1420.     for (unsigned int i = 0;  i < buf.FieldCount();  ++i) {
  1421.         CBDB_Field* fld = &buf.GetField(i);
  1422.         delete fld;
  1423.     }
  1424. }
  1425. END_NCBI_SCOPE
  1426. /*
  1427.  * ===========================================================================
  1428.  * $Log: bdb_types.hpp,v $
  1429.  * Revision 1000.4  2004/06/01 18:37:08  gouriano
  1430.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  1431.  *
  1432.  * Revision 1.36  2004/05/06 15:42:58  rotmistr
  1433.  * Changed Char type to UChar
  1434.  *
  1435.  * Revision 1.35  2004/05/05 19:18:21  rotmistr
  1436.  * CBDB_FieldChar added
  1437.  *
  1438.  * Revision 1.34  2004/04/26 16:43:59  ucko
  1439.  * Qualify inherited dependent names with this-> where needed by GCC 3.4.
  1440.  *
  1441.  * Revision 1.33  2004/03/08 13:30:14  kuznets
  1442.  * + ToString method
  1443.  *
  1444.  * Revision 1.32  2004/02/12 19:54:00  kuznets
  1445.  * + CBDB_BufferManager::GetFieldIndex()
  1446.  *
  1447.  * Revision 1.31  2004/02/04 17:02:34  kuznets
  1448.  * Commented operator char* for LString type to avoid ambuiguity
  1449.  *
  1450.  * Revision 1.30  2004/02/04 15:08:12  kuznets
  1451.  * + CBDB_FieldLString::operator string() const
  1452.  *
  1453.  * Revision 1.29  2003/12/23 22:31:31  ucko
  1454.  * Fix typo that could lead to stack overruns.
  1455.  *
  1456.  * Revision 1.28  2003/12/22 18:52:43  kuznets
  1457.  * Implemeneted length prefixed string field (CBDB_FieldLString)
  1458.  *
  1459.  * Revision 1.27  2003/12/10 19:13:37  kuznets
  1460.  * Added support of berkeley db transactions
  1461.  *
  1462.  * Revision 1.26  2003/11/06 14:05:08  kuznets
  1463.  * Dismissed auto_ptr from CBDB_BufferManager because of the delete / delete []
  1464.  * mismatch. Gives errors in some memory profilers (valgrind).
  1465.  *
  1466.  * Revision 1.25  2003/10/28 14:19:19  kuznets
  1467.  * Calling DoubleToString without precision (%g format) for float and double
  1468.  * BDB fields (more accurate results for scientific data)
  1469.  *
  1470.  * Revision 1.24  2003/10/27 14:19:12  kuznets
  1471.  * + methods to convert BDB types to string
  1472.  *
  1473.  * Revision 1.23  2003/10/16 19:25:25  kuznets
  1474.  * Added field comparison limit to the fields manager
  1475.  *
  1476.  * Revision 1.22  2003/09/29 16:25:14  kuznets
  1477.  * Cleaned up warnings for 64-bit mode
  1478.  *
  1479.  * Revision 1.21  2003/09/26 20:45:57  kuznets
  1480.  * Comments cleaned up
  1481.  *
  1482.  * Revision 1.20  2003/09/17 13:30:28  kuznets
  1483.  * Put comparison functions into ncbi namespace.
  1484.  *
  1485.  * Revision 1.19  2003/09/16 15:14:48  kuznets
  1486.  * Added Int2 (short int) field type
  1487.  *
  1488.  * Revision 1.18  2003/09/15 15:49:25  kuznets
  1489.  * Fixed some compilation warnings(SunCC)
  1490.  *
  1491.  * Revision 1.17  2003/09/11 16:34:13  kuznets
  1492.  * Implemented byte-order independence.
  1493.  *
  1494.  * Revision 1.16  2003/08/26 18:50:26  kuznets
  1495.  * Added forward declararion of DB_ENV structure
  1496.  *
  1497.  * Revision 1.15  2003/07/31 16:39:32  dicuccio
  1498.  * Minor corrections: remove EXPORT specifier from pure inline classes; added
  1499.  * virtual dtor to abstract classes
  1500.  *
  1501.  * Revision 1.14  2003/07/25 15:46:47  kuznets
  1502.  * Added support for double field type
  1503.  *
  1504.  * Revision 1.13  2003/07/23 20:21:27  kuznets
  1505.  * Implemented new improved scheme for setting BerkeleyDB comparison function.
  1506.  * When table has non-segmented key the simplest(and fastest) possible function
  1507.  * is assigned (automatically without reloading CBDB_File::SetCmp function).
  1508.  *
  1509.  * Revision 1.12  2003/07/22 16:05:20  kuznets
  1510.  * Resolved operators ambiguity (GCC-MSVC conflict of interests)
  1511.  *
  1512.  * Revision 1.11  2003/07/22 15:48:34  kuznets
  1513.  * Fixed minor compilation issue with GCC
  1514.  *
  1515.  * Revision 1.10  2003/07/16 13:32:04  kuznets
  1516.  * Implemented CBDB_FieldString::SetString (part of IBDB_FieldConvert interface)
  1517.  *
  1518.  * Revision 1.9  2003/07/02 17:53:59  kuznets
  1519.  * Eliminated direct dependency from <db.h>
  1520.  *
  1521.  * Revision 1.8  2003/06/27 18:57:16  dicuccio
  1522.  * Uninlined strerror() adaptor.  Changed to use #include<> instead of #include ""
  1523.  *
  1524.  * Revision 1.7  2003/06/10 20:07:27  kuznets
  1525.  * Fixed header files not to repeat information from the README file
  1526.  *
  1527.  * Revision 1.6  2003/06/03 18:50:09  kuznets
  1528.  * Added dll export/import specifications
  1529.  *
  1530.  * Revision 1.5  2003/05/27 16:13:21  kuznets
  1531.  * Destructors of key classes declared virtual to make GCC happy
  1532.  *
  1533.  * Revision 1.4  2003/05/22 19:31:51  kuznets
  1534.  * +CBDB_FieldString::operator= (const string& str)
  1535.  *
  1536.  * Revision 1.3  2003/05/05 20:14:41  kuznets
  1537.  * Added CBDB_BLobFile, CBDB_File changed to support more flexible data record
  1538.  * management.
  1539.  *
  1540.  * Revision 1.2  2003/04/29 16:48:31  kuznets
  1541.  * Fixed minor warnings in Sun Workshop compiler
  1542.  *
  1543.  * Revision 1.1  2003/04/24 16:31:16  kuznets
  1544.  * Initial revision
  1545.  *
  1546.  * ===========================================================================
  1547.  */
  1548. #endif  /* BDB_TYPES__HPP */