include/db/bdb/bdb_types.hpp

Go to the documentation of this file.
00001 #ifndef BDB_TYPES__HPP
00002 #define BDB_TYPES__HPP
00003 
00004 /* $Id: bdb_types.hpp 163327 2009-06-15 15:40:12Z ivanovp $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Author:  Anatoliy Kuznetsov
00030  *
00031  * File Description: Field types classes.
00032  *
00033  */
00034 
00035 #include <db/bdb/bdb_expt.hpp>
00036 #include <corelib/ncbi_limits.hpp>
00037 #include <corelib/ncbi_bswap.hpp>
00038 #include <corelib/ncbistr.hpp>
00039 #include <util/simple_buffer.hpp>
00040 
00041 #include <string>
00042 #include <vector>
00043 #include <memory>
00044 
00045 
00046 extern "C" {
00047     //
00048     // Forward structure declarations, so we can declare pointers and
00049     // applications can get type checking.
00050     // Taken from <db.h>
00051     struct __db_dbt; typedef struct __db_dbt DBT;
00052     struct __db;     typedef struct __db     DB;
00053     struct __dbc;    typedef struct __dbc    DBC;
00054     struct __db_env; typedef struct __db_env DB_ENV;
00055     struct __db_txn; typedef struct __db_txn DB_TXN;
00056 
00057     typedef int (*BDB_CompareFunction)(DB*, const DBT*, const DBT*);
00058     typedef unsigned int (*BDB_HashFunction)
00059                             (DB *, const void *bytes, unsigned length);
00060 }
00061 
00062 BEGIN_NCBI_SCOPE
00063 
00064 /** @addtogroup BDB_Types
00065  *
00066  * @{
00067  */
00068 
00069 
00070 extern "C" {
00071 
00072 
00073 /// Simple and fast comparison function for tables with
00074 /// non-segmented "unsigned int" keys
00075 NCBI_DEPRECATED
00076  int BDB_UintCompare(DB*, const DBT* val1, const DBT* val2);
00077  int BDB_Uint4Compare(DB*, const DBT* val1, const DBT* val2);
00078 
00079 /// Simple and fast comparison function for tables with
00080 /// non-segmented "int" keys
00081 NCBI_DEPRECATED
00082  int BDB_IntCompare(DB*, const DBT* val1, const DBT* val2);
00083  int BDB_Int4Compare(DB*, const DBT* val1, const DBT* val2);
00084 
00085 /// Simple and fast comparison function for tables with
00086 /// non-segmented "Int8" keys
00087  int BDB_Int8Compare(DB*, const DBT* val1, const DBT* val2);
00088 
00089 /// Simple and fast comparison function for tables with
00090 /// non-segmented "Uint8" keys
00091  int BDB_Uint8Compare(DB*, const DBT* val1, const DBT* val2);
00092 
00093 /// Simple and fast comparison function for tables with
00094 /// non-segmented "short int" keys
00095  int BDB_Int2Compare(DB*, const DBT* val1, const DBT* val2);
00096 
00097 /// Simple and fast comparison function for tables with
00098 /// non-segmented "unsigned short int" keys
00099  int BDB_Uint2Compare(DB*, const DBT* val1, const DBT* val2);
00100 
00101 /// Simple and fast comparison function for tables with
00102 /// non-segmented "char" keys
00103  int BDB_CharCompare(DB*, const DBT* val1, const DBT* val2);
00104 
00105 /// Simple and fast comparison function for tables with
00106 /// non-segmented "unsigned char" keys
00107  int BDB_UCharCompare(DB*, const DBT* val1, const DBT* val2);
00108 
00109 /// Simple and fast comparison function for tables with
00110 /// non-segmented "float" keys
00111  int BDB_FloatCompare(DB*, const DBT* val1, const DBT* val2);
00112 
00113 /// Simple and fast comparison function for tables with
00114 /// non-segmented "double" keys
00115  int BDB_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
00116 
00117 /// Simple and fast comparison function for tables with
00118 /// non-segmented "C string" keys
00119  int BDB_StringCompare(DB*, const DBT* val1, const DBT* val2);
00120 
00121 /// Simple and fast comparison function for tables with
00122 /// non-segmented length prefixed string keys
00123  int BDB_LStringCompare(DB*, const DBT* val1, const DBT* val2);
00124 
00125 /// Simple and fast comparison function for tables with
00126 /// non-segmented fixed length string keys
00127  int BDB_FixedByteStringCompare
00128                                     (DB*, const DBT* val1, const DBT* val2);
00129 
00130 
00131 /// Simple and fast comparison function for tables with
00132 /// non-segmented "case insensitive C string" keys
00133  int
00134 BDB_StringCaseCompare(DB*, const DBT* val1, const DBT* val2);
00135 
00136 /// General purpose DBD comparison function
00137 int  BDB_Compare(DB* db, const DBT* val1, const DBT* val2);
00138 
00139 
00140 
00141 /// Simple and fast comparison function for tables with
00142 /// non-segmented "unsigned int" keys.
00143 /// Used when the data file is in a different byte order architecture.
00144 NCBI_DEPRECATED
00145  int
00146 BDB_ByteSwap_UintCompare(DB*, const DBT* val1, const DBT* val2);
00147  int
00148 BDB_ByteSwap_Uint4Compare(DB*, const DBT* val1, const DBT* val2);
00149 
00150 /// Simple and fast comparison function for tables with
00151 /// non-segmented "Int8" keys
00152 /// Used when the data file is in a different byte order architecture.
00153  int
00154 BDB_ByteSwap_Int8Compare(DB*, const DBT* val1, const DBT* val2);
00155 
00156 /// Simple and fast comparison function for tables with
00157 /// non-segmented "Uint8" keys
00158 /// Used when the data file is in a different byte order architecture.
00159  int
00160 BDB_ByteSwap_Uint8Compare(DB*, const DBT* val1, const DBT* val2);
00161 
00162 /// Simple and fast comparison function for tables with
00163 /// non-segmented "int" keys
00164 /// Used when the data file is in a different byte order architecture.
00165 NCBI_DEPRECATED
00166  int
00167 BDB_ByteSwap_IntCompare(DB*, const DBT* val1, const DBT* val2);
00168  int
00169 BDB_ByteSwap_Int4Compare(DB*, const DBT* val1, const DBT* val2);
00170 
00171 /// Simple and fast comparison function for tables with
00172 /// non-segmented "short int" keys
00173 /// Used when the data file is in a different byte order architecture.
00174  int
00175 BDB_ByteSwap_Int2Compare(DB*, const DBT* val1, const DBT* val2);
00176 
00177 /// Simple and fast comparison function for tables with
00178 /// non-segmented "unsigned short int" keys
00179 /// Used when the data file is in a different byte order architecture.
00180  int
00181 BDB_ByteSwap_Uint2Compare(DB*, const DBT* val1, const DBT* val2);
00182 
00183 /// Simple and fast comparison function for tables with
00184 /// non-segmented "float" keys
00185 /// Used when the data file is in a different byte order architecture.
00186  int
00187 BDB_ByteSwap_FloatCompare(DB*, const DBT* val1, const DBT* val2);
00188 
00189 /// Simple and fast comparison function for tables with
00190 /// non-segmented "double" keys
00191 /// Used when the data file is in a different byte order architecture.
00192  int
00193 BDB_ByteSwap_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
00194 
00195 
00196 /// General purpose hash function
00197 unsigned int
00198  BDB_Hash(DB *, const void *bytes, unsigned length);
00199 
00200 /// Hash method for databases with a single (unique) UInt4 key
00201 unsigned int
00202  BDB_Uint4Hash(DB *, const void *bytes, unsigned length);
00203 
00204 
00205 }
00206 
00207 
00208 class CBDB_BufferManager;
00209 class CBDB_Field;
00210 class CBDB_File;
00211 class CBDB_FileCursor;
00212 class CBDB_FC_Condition;
00213 
00214 
00215 
00216 
00217 /// BDB Data Field interface definition.
00218 ///
00219 /// Every relational table in BDB library consists of fields, supporting
00220 /// basic IBDB_Field interface
00221 class  IBDB_Field
00222 {
00223 public:
00224     virtual ~IBDB_Field();
00225 
00226     /// Comparison function. p1 and p2 are void pointers on field buffers.
00227     /// Positive if p1>p2, zero if p1==p2, negative if p1<p2.
00228     /// NOTE:  both buffers can be unaligned.
00229     /// byte_swapped TRUE indicates that buffers values are in
00230     /// a different byte order architecture
00231     virtual int         Compare(const void* p1,
00232                                 const void* p2,
00233                                 bool byte_swapped) const = 0;
00234 
00235     /// Return current effective size of the buffer.
00236     virtual size_t      GetDataLength(const void* buf) const = 0;
00237 
00238     /// Set minimal possible value for the field type
00239     virtual void        SetMinVal() = 0;
00240 
00241     /// Set maximum possible value for the field type
00242     virtual void        SetMaxVal() = 0;
00243 };
00244 
00245 
00246 
00247 /// BDB Data Field conversion interface definition.
00248 /// All interface functions by default throw "bad conversion" exception.
00249 
00250 class  IBDB_FieldConvert
00251 {
00252 public:
00253     virtual ~IBDB_FieldConvert() {}
00254 
00255     virtual void SetInt(int)
00256         { BDB_THROW(eType, "Bad conversion"); }
00257     virtual void SetUint(unsigned)
00258         { BDB_THROW(eType, "Bad conversion"); }
00259     virtual int GetInt() const
00260         { BDB_THROW(eType, "Bad conversion"); }
00261     virtual unsigned GetUint() const
00262         { BDB_THROW(eType, "Bad conversion"); }
00263     virtual void SetString(const char*)
00264         { BDB_THROW(eType, "Bad conversion"); }
00265     virtual void SetStdString(const string&)
00266         { BDB_THROW(eType, "Bad conversion"); }
00267     virtual void SetFloat(float)
00268         { BDB_THROW(eType, "Bad conversion"); }
00269     virtual void SetDouble(double)
00270         { BDB_THROW(eType, "Bad conversion"); }
00271 
00272     virtual string GetString() const = 0;
00273 
00274     virtual void ToString(string& str) const = 0;
00275 };
00276 
00277 
00278 
00279 /// Interface definition class for field construction.
00280 /// Used for interfaces' "access rights management".
00281 
00282 class CBDB_FieldInterfaces : public  IBDB_Field,
00283                              public  IBDB_FieldConvert
00284 {
00285     friend class CBDB_FileCursor;
00286 };
00287 
00288 
00289 
00290 /// Base class for constructing BDB fields. Implements field buffer pointer.
00291 ///
00292 /// All DBD field types do not own their buffers.
00293 /// It works as a pointer on external memory kept by the record manager
00294 /// (CBDB_FieldBuf). Class cannot be used independently without record manager.
00295 
00296 class  CBDB_Field : public CBDB_FieldInterfaces
00297 {
00298 public:
00299     /// Length based classificator for fields (fixed-variable)
00300     enum ELengthType {
00301         eFixedLength,    //!< fixed-length (like int)
00302         eVariableLength  //!< variable-length (like string)
00303     };
00304     CBDB_Field(ELengthType length_type = eFixedLength);
00305     virtual ~CBDB_Field() {}
00306 
00307     /// Virtual constructor - class factory for BDB fields.
00308     /// Default (zero) value of 'buf-len' uses GetBufferSize().
00309     /// For fixed length fields this buf_size parameter has no effect
00310     virtual CBDB_Field* Construct(size_t buf_size = 0) const = 0;
00311 
00312     /// Return address to the type specific comparison function
00313     /// By default it's universal BDB_Compare
00314     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const;
00315 
00316     /// Return TRUE if field can be NULL
00317     bool IsNullable() const;
00318 
00319     /// Assign field value to NULL
00320     void SetNull();
00321 
00322     /// Return TRUE if field is NULL
00323     bool IsNull() const;
00324 
00325     /// Return symbolic name for the field
00326     const string& GetName() const;
00327 
00328     /// Get pointer to the data. NULL if not yet attached.
00329     const void* GetBuffer() const;
00330     /// Get pointer to the data. NULL if not yet attached.
00331     void*       GetBuffer();
00332 
00333     /// Return maximum possible buffer length
00334     size_t GetBufferSize() const;
00335 
00336     /// Get length of the actual data
00337     size_t GetLength() const;
00338 
00339 protected:
00340 
00341     /// Field comparison function
00342     int CompareWith(const CBDB_Field& field) const;
00343 
00344     /// Copies field value from another field.
00345     /// The field type MUST be the same, or an exception will be thrown.
00346     void CopyFrom(const CBDB_Field& src);
00347 
00348     // Buffer management functions:
00349 
00350     /// Return TRUE if it is a variable length variable (like string)
00351     bool IsVariableLength() const;
00352 
00353     /// Return TRUE if external buffer has already been attached
00354     bool IsBufferAttached() const;
00355 
00356     /// RTTI based check if fld is of the same type
00357     bool IsSameType(const CBDB_Field& field) const;
00358 
00359     /// Return TRUE if field belongs to a file with an alternative
00360     /// byte order
00361     bool IsByteSwapped() const;
00362 
00363 
00364     /// Mark field as "NULL" capable.
00365     void SetNullable();
00366 
00367     /// Set "is NULL" flag to FALSE
00368     void SetNotNull();
00369 
00370     /// Set symbolic name for the field
00371     void SetName(const char* name);
00372 
00373     /// Set field position in the buffer manager
00374     void SetBufferIdx(unsigned int idx);
00375 
00376 
00377 protected:
00378     /// Unpack the buffer which contains this field (using CBDB_BufferManager).
00379     /// Return new pointer to the field data -- located in the unpacked buffer.
00380     void*  Unpack();
00381     /// Set external buffer pointer and length.
00382     /// Zero 'buf_size' means GetBufferSize() is used to obtain the buf. size.
00383     void  SetBuffer(void* buf, size_t buf_size = 0);
00384     /// Set the buffer size.
00385     void  SetBufferSize(size_t size);
00386     /// Set data size, taking into account possible extra data for some fields
00387     void SetDataSize(size_t size);
00388     /// Hook for defining extra data length
00389     virtual size_t GetExtraDataLength();
00390     /// Set CBDB_BufferManager -- which works as a memory manager for BDB fields.
00391     void  SetBufferManager(CBDB_BufferManager* owner);
00392 
00393     /// Copy buffer value from the external source
00394     void CopyFrom(const void* src_buf);
00395 
00396 private:
00397     CBDB_Field& operator= (const CBDB_Field& data);
00398     CBDB_Field(const CBDB_Field& data);
00399 
00400 protected:
00401     CBDB_BufferManager*  m_BufferManager;
00402     struct {
00403         unsigned VariableLength : 1;
00404         unsigned Attached       : 1;
00405         unsigned Nullable       : 1;
00406     } m_Flags;
00407 private:
00408     void*      m_Buffer;       // Pointer to the field data (in buf. mgr.)
00409     size_t     m_BufferSize;   // Field data buffer capacity
00410     unsigned   m_BufferIdx;    // Fields' position in the managing buffer
00411     string     m_Name;         // Field's symbolic name
00412 
00413     // Friends
00414     friend class CBDB_BufferManager;
00415     friend class CBDB_File;
00416     friend class CBDB_BLobFile;
00417 };
00418 
00419 
00420 
00421 /// Template class for building simple scalar data fields.
00422 /// (int, float, double)
00423 
00424 template<typename T>
00425 class CBDB_FieldSimple : public CBDB_Field
00426 {
00427 public:
00428     typedef  T  TFieldType;
00429 public:
00430     CBDB_FieldSimple()
00431     : CBDB_Field(eFixedLength)
00432     {
00433         SetBufferSize(sizeof(T));
00434     }
00435 
00436     void SetField(const CBDB_FieldSimple& field)
00437     {
00438         if ( field.IsNull() ) {
00439             SetNull();
00440         } else {
00441             if (IsByteSwapped() != field.IsByteSwapped()) {
00442                 BDB_THROW(eInvalidValue, "Byte order incompatibility");
00443             }
00444 #ifdef HAVE_UNALIGNED_READS
00445             TFieldType* b = (TFieldType*) GetBuffer();
00446             TFieldType* f = (TFieldType*) field.GetBuffer();
00447             *b = *f;
00448 #else
00449             ::memcpy(GetBuffer(), field.GetBuffer(), sizeof(T));
00450 #endif
00451             SetNotNull();
00452         }
00453     }
00454 
00455     // IDBD_Field implementation
00456 
00457     virtual int Compare(const void* p1,
00458                         const void* p2,
00459                         bool/* byte_swapped*/) const
00460     {
00461         // Default implementation ignores byte swapping
00462         T v1, v2;
00463 
00464 #ifdef HAVE_UNALIGNED_READS
00465         v1 = *((TFieldType*)p1);
00466         v2 = *((TFieldType*)p2);
00467 #else
00468         ::memcpy(&v1, p1, sizeof(v1));
00469         ::memcpy(&v2, p2, sizeof(v2));
00470 #endif
00471         if (v1 < v2) return -1;
00472         if (v2 < v1) return 1;
00473         return 0;
00474     }
00475 
00476     virtual size_t GetDataLength(const void* /*buf*/) const
00477     {
00478         return sizeof(T);
00479     }
00480 };
00481 
00482 
00483 
00484 /// Template class for building simple scalar integer compatible data fields.
00485 /// (int, short, char)
00486 
00487 template<typename T>
00488 class CBDB_FieldSimpleInt : public CBDB_FieldSimple<T>
00489 {
00490 public:
00491     CBDB_FieldSimpleInt() : CBDB_FieldSimple<T>() {}
00492 
00493     void Set(T val)
00494     {
00495         if (this->IsByteSwapped()) {
00496 
00497             if (sizeof(T) == 2) {
00498                 CByteSwap::PutInt2((unsigned char*)this->GetBuffer(),
00499                                    (Int2) val);
00500             } else
00501             if (sizeof(T) == 4) {
00502                 CByteSwap::PutInt4((unsigned char*)this->GetBuffer(),
00503                                    (Int4) val);
00504             } else
00505             if (sizeof(T) == 8) {
00506                 CByteSwap::PutInt8((unsigned char*)this->GetBuffer(),
00507                                    (Int8) val);
00508             }
00509             else {
00510                 _ASSERT(0);
00511             }
00512 
00513         } else {
00514 #ifdef HAVE_UNALIGNED_READS
00515             typename CBDB_FieldSimple<T>::TFieldType* b =
00516                 (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
00517             *b = val;
00518 #else
00519             ::memcpy(this->GetBuffer(), &val, sizeof(T));
00520 #endif
00521         }
00522         this->SetNotNull();
00523     }
00524 
00525     virtual void SetInt    (int          val)  { Set((T) val); }
00526     virtual void SetUint   (unsigned int val)  { Set((T) val); }
00527     virtual void SetString (const char*  val)
00528     {
00529         long v = ::atol(val);
00530         Set((T) v);
00531     }
00532 
00533     virtual int GetInt() const
00534     {
00535         int value;
00536 #ifdef HAVE_UNALIGNED_READS
00537         typename CBDB_FieldSimple<T>::TFieldType* b =
00538             (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
00539         value = (int)*b;
00540 #else
00541         ::memcpy(&value, this->GetBuffer(), sizeof(T));
00542 #endif
00543         return value;
00544     }
00545 
00546     virtual unsigned GetUint() const
00547     {
00548         unsigned value;
00549 #ifdef HAVE_UNALIGNED_READS
00550         typename CBDB_FieldSimple<T>::TFieldType* b =
00551             (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
00552         value = (unsigned)*b;
00553 #else
00554         ::memcpy(&value, this->GetBuffer(), sizeof(T));
00555 #endif
00556         return value;
00557     }
00558 
00559     virtual void SetStdString(const string& str)
00560     {
00561         SetString(str.c_str());
00562     }
00563 
00564     virtual int Compare(const void* p1,
00565                         const void* p2,
00566                         bool byte_swapped) const
00567     {
00568         if (!byte_swapped)
00569             return CBDB_FieldSimple<T>::Compare(p1, p2, byte_swapped);
00570 
00571         T v1, v2;
00572         v1 = (T) CByteSwap::GetInt4((unsigned char*)p1);
00573         v2 = (T) CByteSwap::GetInt4((unsigned char*)p2);
00574         if (v1 < v2) return -1;
00575         if (v2 < v1) return 1;
00576         return 0;
00577     }
00578 
00579     virtual void SetMinVal()
00580     {
00581         Set(numeric_limits<T>::min());
00582     }
00583 
00584     virtual void SetMaxVal()
00585     {
00586         Set(numeric_limits<T>::max());
00587     }
00588 };
00589 
00590 
00591 
00592 /// Template class for building simple scalar floating point compatible fields.
00593 /// (float, double)
00594 ///
00595 
00596 template<typename T>
00597 class CBDB_FieldSimpleFloat : public CBDB_FieldSimple<T>
00598 {
00599 public:
00600     CBDB_FieldSimpleFloat() : CBDB_FieldSimple<T>() {}
00601 
00602     void Set(T val)
00603     {
00604         if (this->IsByteSwapped()) {
00605 
00606             if (sizeof(T) == 4) {
00607                 CByteSwap::PutFloat((unsigned char*)this->GetBuffer(),
00608                                     (float)val);
00609             } else
00610             if (sizeof(T) == 8) {
00611                 CByteSwap::PutDouble((unsigned char*)this->GetBuffer(), val);
00612             }
00613             else {
00614                 _ASSERT(0);
00615             }
00616         } else {
00617 #ifdef HAVE_UNALIGNED_READS
00618             typename CBDB_FieldSimple<T>::TFieldType* b =
00619                 (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
00620             *b = val;
00621 #else
00622             ::memcpy(this->GetBuffer(), &val, sizeof(T));
00623 #endif
00624         }
00625         this->SetNotNull();
00626     }
00627 
00628     virtual void SetInt    (int          val) { Set((T) val); }
00629     virtual void SetUint   (unsigned int val) { Set((T) val); }
00630     virtual void SetString (const char*  val)
00631     {
00632         double v = ::atof(val);
00633         Set((T) v);
00634     }
00635     virtual void SetStdString(const string& str)
00636     {
00637         SetString(str.c_str());
00638     }
00639 
00640     virtual void SetFloat (float  val) { Set((T) val); }
00641     virtual void SetDouble(double val) { Set((T) val); }
00642 
00643     virtual void SetMinVal()
00644     {
00645         Set(numeric_limits<T>::min());
00646     }
00647 
00648     virtual void SetMaxVal()
00649     {
00650         Set(numeric_limits<T>::max());
00651     }
00652 };
00653 
00654 
00655 ///  Int8 field type
00656 ///
00657 
00658 class  CBDB_FieldInt8 : public CBDB_FieldSimpleInt<Int8>
00659 {
00660 public:
00661     CBDB_FieldInt8& operator= (Int8 val)
00662     {
00663         Set(val);
00664         return *this;
00665     }
00666 
00667     CBDB_FieldInt8& operator= (const CBDB_FieldInt8& val)
00668     {
00669         Set(val);
00670         return *this;
00671     }
00672 
00673     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
00674     {
00675         return new CBDB_FieldInt8();
00676     }
00677 
00678     Int8 Get() const
00679     {
00680         Int8  v;
00681 
00682         _ASSERT(!IsNull());
00683 
00684         if (IsByteSwapped()) {
00685             v = CByteSwap::GetInt8((unsigned char*)GetBuffer());
00686         } else {
00687 #ifdef HAVE_UNALIGNED_READS
00688             TFieldType* b = (TFieldType*) this->GetBuffer();
00689             v = *b;
00690 #else
00691             ::memcpy(&v, GetBuffer(), sizeof(Int8));
00692 #endif
00693         }
00694         return v;
00695     }
00696 
00697     virtual string GetString() const
00698     {
00699         Int8  v = Get();
00700         return NStr::Int8ToString(v);
00701     }
00702 
00703     virtual void ToString(string& str) const
00704     {
00705         Int8 v = Get();
00706         NStr::Int8ToString(str, v);
00707     }
00708 
00709     operator Int8() const
00710     {
00711         return Get();
00712     }
00713 
00714     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
00715     {
00716         if (byte_swapped)
00717             return BDB_ByteSwap_Int8Compare;
00718         return BDB_Int8Compare;
00719     }
00720 
00721     virtual int Compare(const void* p1,
00722                         const void* p2,
00723                         bool byte_swapped) const
00724     {
00725         if (!byte_swapped)
00726             return CBDB_FieldSimpleInt<Int8>::Compare(p1, p2, byte_swapped);
00727 
00728         Int8 v1, v2;
00729         v1 = CByteSwap::GetInt8((unsigned char*)p1);
00730         v2 = CByteSwap::GetInt8((unsigned char*)p2);
00731         if (v1 < v2) return -1;
00732         if (v2 < v1) return 1;
00733         return 0;
00734     }
00735 
00736 };
00737 
00738 
00739 ///  Uint8 field type
00740 ///
00741 
00742 class  CBDB_FieldUint8 : public CBDB_FieldSimpleInt<Uint8>
00743 {
00744 public:
00745     CBDB_FieldUint8& operator= (Uint8 val)
00746     {
00747         Set(val);
00748         return *this;
00749     }
00750 
00751     CBDB_FieldUint8& operator= (const CBDB_FieldUint8& val)
00752     {
00753         Set(val);
00754         return *this;
00755     }
00756 
00757     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
00758     {
00759         return new CBDB_FieldUint8();
00760     }
00761 
00762     Uint8 Get() const
00763     {
00764         Uint8  v;
00765 
00766         _ASSERT(!IsNull());
00767 
00768         if (IsByteSwapped()) {
00769             v = CByteSwap::GetInt8((unsigned char*)GetBuffer());
00770         } else {
00771 #ifdef HAVE_UNALIGNED_READS
00772             TFieldType* b = (TFieldType*) GetBuffer();
00773             v = *b;
00774 #else
00775             ::memcpy(&v, GetBuffer(), sizeof(Uint8));
00776 #endif
00777         }
00778         return v;
00779     }
00780 
00781     virtual string GetString() const
00782     {
00783         Uint8  v = Get();
00784         return NStr::UInt8ToString(v);
00785     }
00786 
00787     virtual void ToString(string& str) const
00788     {
00789         Uint8 v = Get();
00790         NStr::UInt8ToString(str, v);
00791     }
00792 
00793     operator Uint8() const
00794     {
00795         return Get();
00796     }
00797 
00798     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
00799     {
00800         if (byte_swapped)
00801             return BDB_ByteSwap_Uint8Compare;
00802         return BDB_Uint8Compare;
00803     }
00804 
00805     virtual int Compare(const void* p1,
00806                         const void* p2,
00807                         bool byte_swapped) const
00808     {
00809         if (!byte_swapped)
00810             return CBDB_FieldSimpleInt<Uint8>::Compare(p1, p2, byte_swapped);
00811 
00812         Uint8 v1, v2;
00813         v1 = CByteSwap::GetInt8((unsigned char*)p1);
00814         v2 = CByteSwap::GetInt8((unsigned char*)p2);
00815         if (v1 < v2) return -1;
00816         if (v2 < v1) return 1;
00817         return 0;
00818     }
00819 
00820 };
00821 
00822 
00823 ///  Int4 field type
00824 ///
00825 
00826 class  CBDB_FieldInt4 : public CBDB_FieldSimpleInt<Int4>
00827 {
00828 public:
00829     CBDB_FieldInt4& operator= (Int4 val)
00830     {
00831         Set(val);
00832         return *this;
00833     }
00834 
00835     CBDB_FieldInt4& operator= (const CBDB_FieldInt4& val)
00836     {
00837         Set(val);
00838         return *this;
00839     }
00840 
00841     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
00842     {
00843         return new CBDB_FieldInt4();
00844     }
00845 
00846     Int4 Get() const
00847     {
00848         Int4  v;
00849 
00850         _ASSERT(!IsNull());
00851 
00852         if (IsByteSwapped()) {
00853             v = CByteSwap::GetInt4((unsigned char*)GetBuffer());
00854         } else {
00855 #ifdef HAVE_UNALIGNED_READS
00856             TFieldType* b = (TFieldType*)GetBuffer();
00857             v = *b;
00858 #else
00859             ::memcpy(&v, GetBuffer(), sizeof(Int4));
00860 #endif
00861         }
00862         return v;
00863     }
00864 
00865     virtual string GetString() const
00866     {
00867         Int4  v = Get();
00868         return NStr::IntToString(v);
00869     }
00870 
00871     virtual void ToString(string& str) const
00872     {
00873         Int4 v = Get();
00874         NStr::IntToString(str, v);
00875     }
00876 
00877     operator Int4() const
00878     {
00879         return Get();
00880     }
00881 
00882     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
00883     {
00884         if (byte_swapped)
00885             return BDB_ByteSwap_Int4Compare;
00886         return BDB_Int4Compare;
00887     }
00888 
00889     virtual int Compare(const void* p1,
00890                         const void* p2,
00891                         bool byte_swapped) const
00892     {
00893         if (!byte_swapped)
00894             return CBDB_FieldSimpleInt<Int4>::Compare(p1, p2, byte_swapped);
00895 
00896         Int4 v1, v2;
00897         v1 = CByteSwap::GetInt4((unsigned char*)p1);
00898         v2 = CByteSwap::GetInt4((unsigned char*)p2);
00899         if (v1 < v2) return -1;
00900         if (v2 < v1) return 1;
00901         return 0;
00902     }
00903 
00904 };
00905 
00906 
00907 ///  Int2 field type
00908 ///
00909 
00910 class  CBDB_FieldInt2 : public CBDB_FieldSimpleInt<Int2>
00911 {
00912 public:
00913     CBDB_FieldInt2& operator= (Int2 val)
00914     {
00915         Set(val);
00916         return *this;
00917     }
00918 
00919     CBDB_FieldInt2& operator= (const CBDB_FieldInt2& val)
00920     {
00921         Set(val);
00922         return *this;
00923     }
00924 
00925     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
00926     {
00927         return new CBDB_FieldInt2();
00928     }
00929 
00930     Int2 Get() const
00931     {
00932         Int2  v;
00933 
00934         _ASSERT(!IsNull());
00935 
00936         if (IsByteSwapped()) {
00937             v = CByteSwap::GetInt2((unsigned char*)GetBuffer());
00938         } else {
00939 #ifdef HAVE_UNALIGNED_READS
00940             TFieldType* b = (TFieldType*) GetBuffer();
00941             v = *b;
00942 #else
00943             ::memcpy(&v, GetBuffer(), sizeof(Int2));
00944 #endif
00945         }
00946         return v;
00947     }
00948 
00949     virtual string GetString() const
00950     {
00951         Int4  v = Get();
00952         return NStr::IntToString(v);
00953     }
00954 
00955     virtual void ToString(string& str) const
00956     {
00957         Int4 v = Get();
00958         NStr::IntToString(str, v);
00959     }
00960 
00961     operator Int2() const
00962     {
00963         return Get();
00964     }
00965 
00966     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
00967     {
00968         if (byte_swapped)
00969             return BDB_ByteSwap_Int2Compare;
00970         return BDB_Int2Compare;
00971     }
00972 
00973     virtual int Compare(const void* p1,
00974                         const void* p2,
00975                         bool byte_swapped) const
00976     {
00977         if (!byte_swapped)
00978             return CBDB_FieldSimpleInt<Int2>::Compare(p1, p2, byte_swapped);
00979 
00980         Int2 v1, v2;
00981         v1 = CByteSwap::GetInt2((unsigned char*)p1);
00982         v2 = CByteSwap::GetInt2((unsigned char*)p2);
00983         if (v1 < v2) return -1;
00984         if (v2 < v1) return 1;
00985         return 0;
00986     }
00987 
00988 };
00989 
00990 
00991 /// Uint2 field type
00992 ///
00993 
00994 class  CBDB_FieldUint2 : public CBDB_FieldSimpleInt<Uint2>
00995 {
00996 public:
00997     CBDB_FieldUint2& operator= (Uint2 val)
00998     {
00999         Set(val);
01000         return *this;
01001     }
01002 
01003     CBDB_FieldUint2& operator= (const CBDB_FieldUint2& val)
01004     {
01005         Set(val);
01006         return *this;
01007     }
01008 
01009     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
01010     {
01011         return new CBDB_FieldUint2();
01012     }
01013 
01014     Uint2 Get() const
01015     {
01016         Uint2  v;
01017 
01018         _ASSERT(!IsNull());
01019 
01020         if (IsByteSwapped()) {
01021             v = CByteSwap::GetInt2((unsigned char*)GetBuffer());
01022         } else {
01023 #ifdef HAVE_UNALIGNED_READS
01024             TFieldType* b = (TFieldType*) GetBuffer();
01025             v = *b;
01026 #else
01027             ::memcpy(&v, GetBuffer(), sizeof(Uint2));
01028 #endif
01029         }
01030         return v;
01031     }
01032 
01033     virtual string GetString() const
01034     {
01035         Int4  v = Get();
01036         return NStr::IntToString(v);
01037     }
01038 
01039     virtual void ToString(string& str) const
01040     {
01041         Int4 v = Get();
01042         NStr::IntToString(str, v);
01043     }
01044 
01045     operator Uint2() const
01046     {
01047         return Get();
01048     }
01049 
01050     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
01051     {
01052         if (byte_swapped)
01053             return BDB_ByteSwap_Uint2Compare;
01054         return BDB_Uint2Compare;
01055     }
01056 
01057     virtual int Compare(const void* p1,
01058                         const void* p2,
01059                         bool byte_swapped) const
01060     {
01061         if (!byte_swapped)
01062             return CBDB_FieldSimpleInt<Uint2>::Compare(p1, p2, byte_swapped);
01063 
01064         Uint2 v1, v2;
01065         v1 = CByteSwap::GetInt2((unsigned char*)p1);
01066         v2 = CByteSwap::GetInt2((unsigned char*)p2);
01067         if (v1 < v2) return -1;
01068         if (v2 < v1) return 1;
01069         return 0;
01070     }
01071 
01072 };
01073 
01074 /// Char field type
01075 ///
01076 
01077 class CBDB_FieldUChar : public CBDB_FieldSimpleInt<unsigned char>
01078 {
01079 public:
01080     CBDB_FieldUChar& operator = (unsigned char val)
01081     {
01082         Set(val);
01083         return *this;
01084     }
01085 
01086     CBDB_FieldUChar& operator = (const CBDB_FieldUChar& val)
01087     {
01088         Set(val);
01089         return *this;
01090     }
01091 
01092     virtual CBDB_Field * Construct(size_t) const
01093     {
01094         return new CBDB_FieldUChar();
01095     }
01096 
01097     unsigned char Get() const
01098     {
01099         _ASSERT(!IsNull());
01100 
01101         return *(const unsigned char*)GetBuffer();
01102     }
01103 
01104     operator char () const
01105     {
01106         return Get();
01107     }
01108 
01109     virtual string GetString() const
01110     {
01111         return string(1, Get());
01112     }
01113 
01114     virtual void ToString(string& s) const
01115     {
01116         s.assign(1, Get());
01117     }
01118 
01119     virtual BDB_CompareFunction GetCompareFunction(bool) const
01120     {
01121         return BDB_UCharCompare;
01122     }
01123 
01124     virtual int Compare(const void * p1,
01125                         const void * p2,
01126                         bool) const
01127     {
01128         const unsigned char& c1 = *(const unsigned char *)p1;
01129         const unsigned char& c2 = *(const unsigned char *)p2;
01130 
01131         return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
01132     }
01133 };
01134 
01135 class CBDB_FieldChar : public CBDB_FieldSimpleInt<char>
01136 {
01137 public:
01138     CBDB_FieldChar& operator = (char val)
01139     {
01140         Set(val);
01141         return *this;
01142     }
01143 
01144     CBDB_FieldChar& operator = (const CBDB_FieldChar& val)
01145     {
01146         Set(val);
01147         return *this;
01148     }
01149 
01150     virtual CBDB_Field * Construct(size_t) const
01151     {
01152         return new CBDB_FieldChar();
01153     }
01154 
01155     char Get() const
01156     {
01157         _ASSERT(!IsNull());
01158 
01159         return *(const char*)GetBuffer();
01160     }
01161 
01162     operator char () const
01163     {
01164         return Get();
01165     }
01166 
01167     virtual string GetString() const
01168     {
01169         return string(1, Get());
01170     }
01171 
01172     virtual void ToString(string& s) const
01173     {
01174         s.assign(1, Get());
01175     }
01176 
01177     virtual BDB_CompareFunction GetCompareFunction(bool) const
01178     {
01179         return BDB_CharCompare;
01180     }
01181 
01182     virtual int Compare(const void * p1,
01183                         const void * p2,
01184                         bool) const
01185     {
01186         const char& c1 = *(const char *)p1;
01187         const char& c2 = *(const char *)p2;
01188 
01189         return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
01190     }
01191 };
01192 
01193 /// Int1 field type
01194 ///
01195 
01196 class CBDB_FieldInt1 : public CBDB_FieldChar
01197 {
01198 public:
01199     CBDB_FieldInt1& operator=(Int1 val)
01200     {
01201         Set(val);
01202         return *this;
01203     }
01204 
01205     CBDB_FieldInt1& operator=(const CBDB_FieldChar& val)
01206     {
01207         Set(val);
01208         return *this;
01209     }
01210 
01211     virtual CBDB_Field * Construct(size_t) const
01212     {
01213         return new CBDB_FieldInt1();
01214     }
01215 
01216     virtual string GetString() const
01217     {
01218         return NStr::UIntToString(Get());
01219     }
01220 
01221     virtual void ToString(string& s) const
01222     {
01223         s = GetString();
01224     }
01225 };
01226 
01227 
01228 /// Uint1 field type
01229 ///
01230 
01231 class CBDB_FieldUint1 : public CBDB_FieldUChar
01232 {
01233 public:
01234     CBDB_FieldUint1& operator= (unsigned char val)
01235     {
01236         Set(val);
01237         return *this;
01238     }
01239 
01240     CBDB_FieldUint1& operator= (const CBDB_FieldUChar& val)
01241     {
01242         Set(val);
01243         return *this;
01244     }
01245 
01246     virtual CBDB_Field * Construct(size_t) const
01247     {
01248         return new CBDB_FieldUint1();
01249     }
01250 
01251     virtual string GetString() const
01252     {
01253         return NStr::UIntToString(Get());
01254     }
01255 
01256     virtual void ToString(string& s) const
01257     {
01258         s = GetString();
01259     }
01260 };
01261 
01262 
01263 ///  Uint4 field type
01264 ///
01265 
01266 class  CBDB_FieldUint4 : public CBDB_FieldSimpleInt<Uint4>
01267 {
01268 public:
01269     CBDB_FieldUint4& operator= (Uint4 val)
01270     {
01271         Set(val);
01272         return *this;
01273     }
01274 
01275     CBDB_FieldUint4& operator= (const CBDB_FieldUint4& val)
01276     {
01277         Set(val);
01278         return *this;
01279     }
01280 
01281     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
01282     {
01283         return new CBDB_FieldUint4();
01284     }
01285 
01286     Uint4 Get() const
01287     {
01288         Uint4  v;
01289 
01290         _ASSERT(!IsNull());
01291 
01292         if (IsByteSwapped()) {
01293             v = (Uint4)CByteSwap::GetInt4((unsigned char*)GetBuffer());
01294         } else {
01295 #ifdef HAVE_UNALIGNED_READS
01296             TFieldType* b = (TFieldType*) GetBuffer();
01297             v = *b;
01298 #else
01299             ::memcpy(&v, GetBuffer(), sizeof(Uint4));
01300 #endif
01301         }
01302         return v;
01303     }
01304 
01305     virtual string GetString() const
01306     {
01307         Uint4  v = Get();
01308         return NStr::UIntToString(v);
01309     }
01310 
01311     virtual void ToString(string& str) const
01312     {
01313         Uint4 v = Get();
01314         NStr::UIntToString(str, v);
01315     }
01316 
01317     operator Uint4() const
01318     {
01319         return Get();
01320     }
01321 
01322     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
01323     {
01324         if (byte_swapped)
01325             return BDB_ByteSwap_Uint4Compare;
01326         return BDB_Uint4Compare;
01327     }
01328 
01329     virtual int Compare(const void* p1,
01330                         const void* p2,
01331                         bool byte_swapped) const
01332     {
01333         if (!byte_swapped)
01334             return CBDB_FieldSimpleInt<Uint4>::Compare(p1, p2, byte_swapped);
01335 
01336         Uint4 v1, v2;
01337         v1 = (Uint4)CByteSwap::GetInt4((unsigned char*)p1);
01338         v2 = (Uint4)CByteSwap::GetInt4((unsigned char*)p2);
01339         if (v1 < v2) return -1;
01340         if (v2 < v1) return 1;
01341         return 0;
01342     }
01343 
01344 };
01345 
01346 
01347 
01348 ///  Float field type
01349 ///
01350 
01351 class  CBDB_FieldFloat : public CBDB_FieldSimpleFloat<float>
01352 {
01353 public:
01354     CBDB_FieldFloat& operator= (float val)
01355     {
01356         Set(val);
01357         return *this;
01358     }
01359 
01360     CBDB_FieldFloat& operator= (const CBDB_FieldFloat& val)
01361     {
01362         Set(val);
01363         return *this;
01364     }
01365 
01366     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
01367     {
01368         return new CBDB_FieldFloat();
01369     }
01370 
01371     float Get() const
01372     {
01373         float  v;
01374 
01375         _ASSERT(!IsNull());
01376 
01377         if (IsByteSwapped()) {
01378             v = CByteSwap::GetFloat((unsigned char*)GetBuffer());
01379         } else {
01380 #ifdef HAVE_UNALIGNED_READS
01381             TFieldType* b = (TFieldType*) this->GetBuffer();
01382             v = *b;
01383 #else
01384             ::memcpy(&v, GetBuffer(), sizeof(float));
01385 #endif
01386         }
01387         return v;
01388     }
01389 
01390     virtual string GetString() const
01391     {
01392         double v = Get();
01393         return NStr::DoubleToString(v);
01394     }
01395 
01396     virtual void ToString(string& str) const
01397     {
01398         double v = Get();
01399         NStr::DoubleToString(str, v);
01400     }
01401 
01402     operator float() const
01403     {
01404         return Get();
01405     }
01406 
01407     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
01408     {
01409         if (byte_swapped)
01410             return BDB_ByteSwap_FloatCompare;
01411 
01412         return BDB_FloatCompare;
01413     }
01414 
01415     virtual int Compare(const void* p1,
01416                         const void* p2,
01417                         bool byte_swapped) const
01418     {
01419         if (!byte_swapped)
01420             return CBDB_FieldSimpleFloat<float>::Compare(p1, p2, byte_swapped);
01421 
01422         float v1, v2;
01423         v1 = CByteSwap::GetFloat((unsigned char*)p1);
01424         v2 = CByteSwap::GetFloat((unsigned char*)p2);
01425         if (v1 < v2) return -1;
01426         if (v2 < v1) return 1;
01427         return 0;
01428     }
01429 };
01430 
01431 
01432 ///  Double precision floating point field type
01433 ///
01434 
01435 class  CBDB_FieldDouble : public CBDB_FieldSimpleFloat<double>
01436 {
01437 public:
01438     CBDB_FieldDouble& operator= (double val)
01439     {
01440         Set(val);
01441         return *this;
01442     }
01443 
01444     CBDB_FieldDouble& operator= (const CBDB_FieldDouble& val)
01445     {
01446         Set(val);
01447         return *this;
01448     }
01449 
01450     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
01451     {
01452         return new CBDB_FieldDouble();
01453     }
01454 
01455     double Get() const
01456     {
01457         double  v;
01458 
01459         _ASSERT(!IsNull());
01460 
01461         if (IsByteSwapped()) {
01462             v = CByteSwap::GetDouble((unsigned char*)GetBuffer());
01463         } else {
01464 #ifdef HAVE_UNALIGNED_READS
01465             TFieldType* b = (TFieldType*) GetBuffer();
01466             v = *b;
01467 #else
01468             ::memcpy(&v, GetBuffer(), sizeof(double));
01469 #endif
01470         }
01471         return v;
01472     }
01473 
01474     virtual string GetString() const
01475     {
01476         double v = Get();
01477         return NStr::DoubleToString(v);
01478     }
01479 
01480     virtual void ToString(string& str) const
01481     {
01482         double v = Get();
01483         NStr::DoubleToString(str, v);
01484     }
01485 
01486     operator double() const
01487     {
01488         return Get();
01489     }
01490 
01491     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
01492     {
01493         if (byte_swapped)
01494             return BDB_ByteSwap_DoubleCompare;
01495 
01496         return BDB_DoubleCompare;
01497     }
01498 
01499     virtual int Compare(const void* p1,
01500                         const void* p2,
01501                         bool byte_swapped) const
01502     {
01503         if (!byte_swapped)
01504             return CBDB_FieldSimpleFloat<double>::Compare(p1, p2, byte_swapped);
01505 
01506         double v1, v2;
01507         v1 = CByteSwap::GetDouble((unsigned char*)p1);
01508         v2 = CByteSwap::GetDouble((unsigned char*)p2);
01509         if (v1 < v2) return -1;
01510         if (v2 < v1) return 1;
01511         return 0;
01512     }
01513 
01514 };
01515 
01516 /// Fixed length bytestring. (Can hold 0 chars).
01517 ///
01518 class  CBDB_FieldFixedByteString : public CBDB_Field
01519 {
01520 public:
01521     CBDB_FieldFixedByteString();
01522 
01523     virtual CBDB_Field* Construct(size_t buf_size) const
01524     {
01525         CBDB_FieldFixedByteString* fld = new CBDB_FieldFixedByteString();
01526         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
01527         return fld;
01528     }
01529     operator const char* () const;
01530     CBDB_FieldFixedByteString& operator=
01531                     (const CBDB_FieldFixedByteString& str);
01532 
01533     void Set(const char* str);
01534     virtual void SetString (const char*  val) { Set(val); }
01535     string Get() const;
01536     virtual string GetString() const { return Get(); }
01537 
01538     bool IsEmpty() const { return false; }
01539     bool IsBlank() const { return false; }
01540 
01541 
01542     // IField
01543     virtual int         Compare(const void* p1,
01544                                 const void* p2,
01545                                 bool /* byte_swapped */) const;
01546     virtual size_t      GetDataLength(const void* buf) const;
01547     virtual void        SetMinVal();
01548     virtual void        SetMaxVal();
01549 
01550     virtual void SetStdString(const string& str)
01551     {
01552         _ASSERT(str.length() == GetBufferSize());
01553         SetString(str.c_str());
01554     }
01555     virtual void ToString(string& str) const
01556     {
01557         str.assign((const char*) GetBuffer(), GetBufferSize());
01558     }
01559 
01560     virtual BDB_CompareFunction GetCompareFunction(bool) const
01561     {
01562         return BDB_FixedByteStringCompare;
01563     }
01564 
01565 };
01566 
01567 
01568 ///
01569 ///  String field type
01570 ///
01571 class  CBDB_FieldStringBase : public CBDB_Field
01572 {
01573 public:
01574     enum EOverflowAction {
01575         eThrowOnOverflow,
01576         eTruncateOnOverflow,
01577         eTruncateOnOverflowLogError
01578     };
01579 
01580 protected:
01581     CBDB_FieldStringBase() : CBDB_Field(eVariableLength) {}
01582 };
01583 
01584 
01585 ///
01586 ///  String field type designed to work with C-strings (ASCIIZ)
01587 ///
01588 
01589 class  CBDB_FieldString : public CBDB_FieldStringBase
01590 {
01591 public:
01592     CBDB_FieldString();
01593 
01594     /// Class factory for string fields.
01595     /// Default (zero) value of 'buf_size' uses GetBufferSize().
01596     virtual CBDB_Field* Construct(size_t buf_size) const
01597     {
01598         CBDB_FieldString* fld = new CBDB_FieldString();
01599         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
01600         return fld;
01601     }
01602 
01603     operator const char* () const;
01604     CBDB_FieldString& operator= (const CBDB_FieldString& str);
01605     CBDB_FieldString& operator= (const char*             str);
01606     CBDB_FieldString& operator= (const string&           str);
01607 
01608     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
01609     string Get() const { return string((const char*)GetBuffer()); }
01610 
01611     virtual string GetString() const
01612     {
01613         return Get();
01614     }
01615 
01616     bool IsEmpty() const;
01617     bool IsBlank() const;
01618 
01619 
01620     // IField
01621     virtual int         Compare(const void* p1,
01622                                 const void* p2,
01623                                 bool /* byte_swapped */) const;
01624     virtual size_t      GetDataLength(const void* buf) const;
01625     virtual void        SetMinVal();
01626     virtual void        SetMaxVal();
01627 
01628     virtual void SetString(const char*);
01629     virtual void SetStdString(const string& str)
01630     {
01631         SetString(str.c_str());
01632     }
01633     virtual void ToString(string& str) const
01634     {
01635         str = (const char*) GetBuffer();
01636     }
01637 
01638     virtual BDB_CompareFunction GetCompareFunction(bool) const
01639     {
01640         return BDB_StringCompare;
01641     }
01642 };
01643 
01644 
01645 
01646 ///  Case-insensitive (but case preserving) string field type
01647 ///
01648 
01649 class  CBDB_FieldStringCase : public CBDB_FieldString
01650 {
01651 public:
01652     typedef CBDB_FieldString CParent;
01653 
01654     explicit CBDB_FieldStringCase() : CBDB_FieldString() {}
01655 
01656     virtual CBDB_Field* Construct(size_t buf_size) const
01657     {
01658         CBDB_FieldStringCase* fld = new CBDB_FieldStringCase();
01659         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
01660         return fld;
01661     }
01662 
01663     // Accessors
01664     operator const char* () const { return (const char*) GetBuffer(); }
01665 
01666     CBDB_FieldStringCase& operator= (const CBDB_FieldString& str)
01667     {
01668         Set(str);
01669         return *this;
01670     }
01671     CBDB_FieldStringCase& operator= (const CBDB_FieldStringCase& str)
01672     {
01673         Set(str);
01674         return *this;
01675     }
01676     CBDB_FieldStringCase& operator= (const char* str)
01677     {
01678         Set(str);
01679         return *this;
01680     }
01681     CBDB_FieldStringCase& operator= (const string& str)
01682     {
01683         Set(str.c_str());
01684         return *this;
01685     }
01686 
01687     virtual int Compare(const void* p1,
01688                         const void* p2,
01689                         bool/* byte_swapped */) const
01690     {
01691         _ASSERT(p1 && p2);
01692         return NStr::CompareNocase((const char*) p1, (const char*) p2);
01693     }
01694 
01695     virtual
01696     BDB_CompareFunction GetCompareFunction(bool /* byte_swapped */) const
01697     {
01698         return BDB_StringCaseCompare;
01699     }
01700 
01701 };
01702 
01703 
01704 ///
01705 ///  Length prefised string field type
01706 ///
01707 
01708 class  CBDB_FieldLString : public CBDB_FieldStringBase
01709 {
01710 public:
01711     CBDB_FieldLString();
01712 
01713     // Class factory for string fields.
01714     // Default (zero) value of 'buf_size' uses GetBufferSize().
01715     virtual CBDB_Field* Construct(size_t buf_size) const;
01716 
01717     operator string() const { return GetString(); }
01718     CBDB_FieldLString& operator= (const CBDB_FieldLString& str);
01719     CBDB_FieldLString& operator= (const char*             str);
01720     CBDB_FieldLString& operator= (const string&           str);
01721 
01722     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
01723     void Set(const char* str, size_t size,
01724              EOverflowAction if_overflow = eThrowOnOverflow);
01725     string Get() const;
01726 
01727     virtual string GetString() const
01728     {
01729         return Get();
01730     }
01731 
01732     bool IsEmpty() const;
01733     bool IsBlank() const;
01734 
01735 
01736     // IField
01737     virtual int         Compare(const void* p1,
01738                                 const void* p2,
01739                                 bool /* byte_swapped */) const;
01740     virtual size_t      GetDataLength(const void* buf) const;
01741     virtual void        SetMinVal();
01742     virtual void        SetMaxVal();
01743 
01744     virtual void SetString(const char*);
01745     virtual void SetStdString(const string& str);
01746 
01747     virtual BDB_CompareFunction GetCompareFunction(bool) const
01748     {
01749         return BDB_LStringCompare;
01750     }
01751     virtual void ToString(string& str) const;
01752 protected:
01753     const unsigned char* GetLString(const unsigned char* str,
01754                                     bool                 check_legacy,
01755                                     int*                 str_len) const;
01756     virtual size_t GetExtraDataLength();
01757 };
01758 
01759 
01760 
01761 
01762 /// BDB Data Field Buffer manager class.
01763 /// For internal use in BDB library.
01764 ///
01765 /// @internal
01766 
01767 class  CBDB_BufferManager
01768 {
01769 public:
01770     /// Return number of fields attached using function Bind
01771     unsigned int FieldCount() const;
01772 
01773     const CBDB_Field& GetField(unsigned int idx) const;
01774     CBDB_Field&       GetField(unsigned int idx);
01775 
01776     /// Find the field with the specified name. Name is case insensitive.
01777     /// @return -1 if field cannot be found
01778     int GetFieldIndex(const string& name) const;
01779 
01780     /// Return TRUE if buffer is in a non-native byte order
01781     bool IsByteSwapped() const { return m_ByteSwapped; }
01782 
01783     /// Sets maximum number of fields participating in comparison
01784     /// Should be less than total number of fields in the buffer
01785     void SetFieldCompareLimit(unsigned int n_fields);
01786 
01787     /// Get number of fields in comparison.
01788     /// 0 - means no forced limit
01789     unsigned int GetFieldCompareLimit() const;
01790 
01791     /// Return TRUE if buffer l-strings should check about legacy
01792     /// c-str compatibility
01793     bool IsLegacyStrings() const { return m_LegacyString; }
01794 
01795     /// Get DBT.size of the parent file (key or data area)
01796     /// (Set by CBDB_File after read)
01797     size_t GetDBT_Size() const { return m_DBT_Size; }
01798 
01799     ~CBDB_BufferManager();
01800 
01801     /// Check if any field is NULL
01802     bool HasNull() const;
01803 
01804     /// Copy all fields from another manager with the same(a must!) structure
01805     void CopyFrom(const CBDB_BufferManager& bman);
01806 
01807     /// Copy packed data (buffer) from an external source
01808     void CopyPackedFrom(void* data, size_t data_size);
01809 
01810 protected:
01811     CBDB_BufferManager();
01812 
01813     /// Create internal data buffer, assign places in this buffer to the fields
01814     void Construct();
01815 
01816     /// Set minimum possible value to buffer fields from 'idx_from' to 'idx_to'
01817     void SetMinVal(unsigned int idx_from, unsigned int idx_to);
01818 
01819     /// Set maximum possible value to buffer fields from 'idx_from' to 'idx_to'
01820     void SetMaxVal(unsigned int idx_from, unsigned int idx_to);
01821 
01822     /// Attach 'field' to the buffer.
01823     /// NOTE: buffer manager will not own the attached object, nor will it
01824     ///       keep ref counters or do any other automagic memory management,
01825     ///       unless field ownership is set to TRUE
01826     void Bind(CBDB_Field* field, ENullable is_nullable = eNotNullable);
01827 
01828     /// Copy all field values from the 'buf_mgr'.
01829     void CopyFieldsFrom(const CBDB_BufferManager& buf_mgr);
01830 
01831     /// Duplicate (dynamic allocation is used) all fields from 'buf_mgr' and
01832     /// bind them to the this buffer manager. Field values are not copied.
01833     /// NOTE: CBDB_BufferManager does not own or deallocate fields,
01834     ///       caller is responsible for deallocation,
01835     ///       unless field ownership is set to TRUE
01836     void DuplicateStructureFrom(const CBDB_BufferManager& buf_mgr);
01837 
01838     /// Compare fields of this buffer with those of 'buf_mgr' using
01839     /// CBDB_Field::CompareWith().
01840     /// Optional 'n_fields' parameter used when we want to compare only
01841     /// several first fields instead of all.
01842     int Compare(const CBDB_BufferManager& buf_mgr,
01843                 unsigned int              n_fields = 0) const;
01844 
01845     /// Return TRUE if any field bound to this buffer manager has variable
01846     /// length (i.e. packable)
01847     bool IsPackable() const;
01848 
01849     /// Check if all NOT NULLABLE fields were assigned.
01850     /// Throw an exception if not.
01851     void CheckNullConstraint() const;
01852 
01853     void ArrangePtrsUnpacked();
01854     void ArrangePtrsPacked();
01855     void Clear();
01856     unsigned Pack();
01857     unsigned Unpack();
01858 
01859     /// Pack the buffer and initialize DBT structure for write operation
01860     void PrepareDBT_ForWrite(DBT* dbt);
01861 
01862     /// Initialize DBT structure for read operation.
01863     void PrepareDBT_ForRead(DBT* dbt);
01864 
01865     /// Calculate buffer size
01866     size_t ComputeBufferSize() const;
01867 
01868     /// Return TRUE if buffer can carry NULL fields
01869     bool IsNullable() const;
01870 
01871     /// Set byte swapping flag for the buffer
01872     void SetByteSwapped(bool byte_swapped) { m_ByteSwapped = byte_swapped; }
01873 
01874     /// Mark buffer as "NULL fields ready".
01875     /// NOTE: Should be called before buffer construction.
01876     void SetNullable();
01877 
01878     void SetNull(unsigned int field_idx, bool value);
01879     bool IsNull (unsigned int field_idx) const;
01880 
01881     size_t ComputeNullSetSize() const;
01882     bool   TestNullBit(unsigned int idx) const;
01883     void   SetNullBit (unsigned int idx, bool value);
01884     void   SetAllNull();
01885 
01886     /// Return buffer compare function
01887     BDB_CompareFunction GetCompareFunction() const;
01888 
01889     /// Return buffer hash function
01890     BDB_HashFunction GetHashFunction() const;
01891 
01892     /// Set C-str detection
01893     void SetLegacyStringsCheck(bool value) { m_LegacyString = value; }
01894 
01895     void SetDBT_Size(size_t size) { m_DBT_Size = size; }
01896 
01897     /// Fields deletion is managed by the class when own_fields is TRUE
01898     void SetFieldOwnership(bool own_fields) { m_OwnFields = own_fields; }
01899 
01900     /// Return fields ownership flag
01901     bool IsOwnFields() const { return m_OwnFields; }
01902 
01903     /// Disable-enable packing
01904     void SetPackable(bool packable) { m_Packable = packable; }
01905 
01906 private:
01907     void x_ComputePackOpt();
01908 private:
01909     CBDB_BufferManager(const CBDB_BufferManager&);
01910     CBDB_BufferManager& operator= (const CBDB_BufferManager&);
01911 
01912 private:
01913     typedef vector<CBDB_Field*>  TFieldVector;
01914 
01915 private:
01916     TFieldVector            m_Fields;
01917     /// Array of pointers to the fields' data
01918     vector<void*>           m_Ptrs;
01919     char*                   m_Buffer;
01920     size_t                  m_BufferSize;
01921     size_t                  m_PackedSize;
01922     size_t                  m_DBT_Size;
01923     bool                    m_Packable;
01924     /// TRUE if buffer is in a non-native arch.
01925     bool                    m_ByteSwapped;
01926 
01927     /// TRUE if buffer can carry NULL fields
01928     bool                    m_Nullable;
01929     /// size of the 'is NULL' bitset in bytes
01930     size_t                  m_NullSetSize;
01931 
01932     /// Number of fields in key comparison
01933     unsigned int            m_CompareLimit;
01934 
01935     /// Flag to check for legacy string compatibility
01936     bool                    m_LegacyString;
01937 
01938     /// Field ownership flag
01939     bool                    m_OwnFields;
01940 
01941 
01942     // pack optimization fields
01943 
01944     /// Pack optimization flag (turns TRUE on first Pack call)
01945     bool                    m_PackOptComputed;
01946     /// Index of first variable length field
01947     unsigned int            m_FirstVarFieldIdx;
01948     /// Buffer offset of first variable length field
01949     unsigned int            m_FirstVarFieldIdxOffs;
01950 
01951 private:
01952     friend class CBDB_Field;
01953     friend class CBDB_BLobFile;
01954     friend class CBDB_File;
01955     friend class CBDB_FileCursor;
01956     friend class CBDB_FC_Condition;
01957 };
01958 
01959 /// Class factory for BDB field types
01960 class  CBDB_FieldFactory
01961 {
01962 public:
01963     enum EType
01964     {
01965         eUnknown,
01966 
01967         eString,
01968         eLString,
01969         eInt8,
01970         eInt4,
01971         eUint4,
01972         eInt2,
01973         eUint1,
01974         eFloat,
01975         eDouble,
01976         eUChar,
01977         eBlob
01978     };
01979 
01980 public:
01981     CBDB_FieldFactory();
01982 
01983     /// Return type enumerator by string type (case insensitive)
01984     EType GetType(const string& type) const;
01985 
01986 
01987     CBDB_Field* Create(EType type) const;
01988 
01989     /// Create field type by string. Caller is responsible for deletion.
01990     ///
01991     /// @param type
01992     ///    string type ("string", "int4", "double"). Case insensitive.
01993 
01994     CBDB_Field* Create(const string& type) const;
01995 };
01996 
01997 
01998 /////////////////////////////////////////////////////////////////////////////
01999 ///
02000 /// Type trait classes for finding the correct BDB field type automagically
02001 ///
02002 
02003 ///
02004 /// SBDB_TypeTraits defines via template parameters a policy for mapping a
02005 /// built-in type to a BDB field type.
02006 ///
02007 template <class Type>
02008 struct SBDB_TypeTraits
02009 {
02010     typedef Type TType;
02011     typedef void* TFieldType;
02012 };
02013 
02014 
02015 ///
02016 /// 8-bit signed and unsigned integral types
02017 ///
02018 template<>
02019 struct SBDB_TypeTraits<Int1>
02020 {
02021     typedef Int4 TType;
02022     typedef CBDB_FieldInt1 TFieldType;
02023 };
02024 
02025 template<>
02026 struct SBDB_TypeTraits<Uint1>
02027 {
02028     typedef Uint4 TType;
02029     typedef CBDB_FieldUint1 TFieldType;
02030 };
02031 
02032 
02033 ///
02034 /// 16-bit signed and unsigned integral types
02035 ///
02036 template<>
02037 struct SBDB_TypeTraits<Int2>
02038 {
02039     typedef Int4 TType;
02040     typedef CBDB_FieldInt2 TFieldType;
02041 };
02042 
02043 template<>
02044 struct SBDB_TypeTraits<Uint2>
02045 {
02046     typedef Uint4 TType;
02047     typedef CBDB_FieldUint2 TFieldType;
02048 };
02049 
02050 
02051 ///
02052 /// 32-bit signed and unsigned integral types
02053 ///
02054 template<>
02055 struct SBDB_TypeTraits<Int4>
02056 {
02057     typedef Int4 TType;
02058     typedef CBDB_FieldInt4 TFieldType;
02059 };
02060 
02061 template<>
02062 struct SBDB_TypeTraits<Uint4>
02063 {
02064     typedef Uint4 TType;
02065     typedef CBDB_FieldUint4 TFieldType;
02066 };
02067 
02068 
02069 ///
02070 /// 64-bit signed and unsigned integral types
02071 ///
02072 template<>
02073 struct SBDB_TypeTraits<Int8>
02074 {
02075     typedef Int8 TType;
02076     typedef CBDB_FieldInt8 TFieldType;
02077 };
02078 
02079 template<>
02080 struct SBDB_TypeTraits<Uint8>
02081 {
02082     typedef Uint8 TType;
02083     typedef CBDB_FieldUint8 TFieldType;
02084 };
02085 
02086 
02087 ///
02088 /// string types
02089 ///
02090 template<>
02091 struct SBDB_TypeTraits<string>
02092 {
02093     typedef string TType;
02094     typedef CBDB_FieldString TFieldType;
02095 };
02096 
02097 
02098 ///
02099 /// 32- and 64- bit floating point types
02100 ///
02101 template<>
02102 struct SBDB_TypeTraits<float>
02103 {
02104     typedef float TType;
02105     typedef CBDB_FieldFloat TFieldType;
02106 };
02107 
02108 template<>
02109 struct SBDB_TypeTraits<double>
02110 {
02111     typedef double TType;
02112     typedef CBDB_FieldDouble TFieldType;
02113 };
02114 
02115 
02116 /* @} */
02117 
02118 /////////////////////////////////////////////////////////////////////////////
02119 //  IMPLEMENTATION of INLINE functions
02120 /////////////////////////////////////////////////////////////////////////////
02121 
02122 
02123 /////////////////////////////////////////////////////////////////////////////
02124 //  CBDB_Field::
02125 //
02126 
02127 
02128 inline bool CBDB_Field::IsVariableLength() const
02129 {
02130     return m_Flags.VariableLength == 1;
02131 }
02132 
02133 
02134 inline size_t CBDB_Field::GetBufferSize() const
02135 {
02136     return m_BufferSize;
02137 }
02138 
02139 
02140 inline bool CBDB_Field::IsBufferAttached() const
02141 {
02142     return m_Flags.Attached == 1;
02143 }
02144 
02145 
02146 inline bool CBDB_Field::IsNullable() const
02147 {
02148     return m_Flags.Nullable == 1;
02149 }
02150 
02151 
02152 inline void CBDB_Field::SetNullable()
02153 {
02154     m_Flags.Nullable = 1;
02155 }
02156 
02157 
02158 inline void CBDB_Field::SetNotNull()
02159 {
02160     m_BufferManager->SetNull(m_BufferIdx, false);
02161 }
02162 
02163 
02164 inline void CBDB_Field::SetNull()
02165 {
02166     _ASSERT(m_BufferManager->IsNullable());
02167     m_BufferManager->SetNull(m_BufferIdx, true);
02168 }
02169 
02170 
02171 inline bool CBDB_Field::IsNull() const
02172 {
02173     return m_BufferManager->IsNull(m_BufferIdx);
02174 }
02175 
02176 
02177 inline void* CBDB_Field::Unpack()
02178 {
02179     _ASSERT(m_BufferManager);
02180     m_BufferManager->Unpack();
02181     return GetBuffer();
02182 }
02183 
02184 
02185 inline void CBDB_Field::SetBuffer(void* buf, size_t buf_size)
02186 {
02187     m_Buffer = buf;
02188     if ( buf_size )
02189         m_BufferSize = buf_size;
02190     m_Flags.Attached = 1;
02191 }
02192 
02193 
02194 inline void CBDB_Field::SetBufferSize(size_t buf_size)
02195 {
02196     _ASSERT(buf_size != 0);
02197     m_BufferSize = buf_size;
02198 }
02199 
02200 
02201 inline void CBDB_Field::SetDataSize(size_t size)
02202 {
02203     m_BufferSize = size + GetExtraDataLength();
02204 }
02205 
02206 
02207 inline void CBDB_Field::SetBufferIdx(unsigned int idx)
02208 {
02209     m_BufferIdx = idx;
02210 }
02211 
02212 
02213 inline const void* CBDB_Field::GetBuffer() const
02214 {
02215     return m_Buffer;
02216 }
02217 
02218 
02219 inline void* CBDB_Field::GetBuffer()
02220 {
02221     return m_Buffer;
02222 }
02223 
02224 
02225 inline void CBDB_Field::SetBufferManager(CBDB_BufferManager* owner)
02226 {
02227     _ASSERT(owner);
02228     m_BufferManager = owner;
02229 }
02230 
02231 
02232 inline size_t CBDB_Field::GetLength() const
02233 {
02234     return GetDataLength(m_Buffer);
02235 }
02236 
02237 
02238 inline int CBDB_Field::CompareWith(const CBDB_Field& field) const
02239 {
02240     bool byte_swapped = m_BufferManager->IsByteSwapped();
02241     return Compare(GetBuffer(), field.GetBuffer(), byte_swapped);
02242 }
02243 
02244 
02245 inline bool CBDB_Field::IsSameType(const CBDB_Field& field) const
02246 {
02247     try {
02248         const type_info& t1 = typeid(*this);
02249         const type_info& t2 = typeid(field);
02250         return (t1 == t2) != 0;
02251     } catch (...) {
02252     }
02253     return false;
02254 }
02255 
02256 
02257 
02258 inline void CBDB_Field::CopyFrom(const CBDB_Field& src)
02259 {
02260     if (this == &src)
02261         return;
02262 
02263     if ( !IsSameType(src) ) {
02264         BDB_THROW(eType, "Wrong field type");
02265     }
02266 
02267     CopyFrom(src.GetBuffer());
02268 }
02269 
02270 
02271 inline void CBDB_Field::CopyFrom(const void* src_buf)
02272 {
02273     _ASSERT(src_buf);
02274 
02275     void* dst_ptr = Unpack();
02276     _ASSERT(dst_ptr);
02277 
02278     size_t max_len  = GetBufferSize();
02279     size_t copy_len = GetDataLength(src_buf);
02280 
02281     if (copy_len > max_len) {
02282         BDB_THROW(eOverflow, "Cannot copy. Data length exceeds max value");
02283     }
02284     ::memcpy(dst_ptr, src_buf, copy_len);
02285     SetNotNull();
02286 }
02287 
02288 
02289 inline const string& CBDB_Field::GetName() const
02290 {
02291     return m_Name;
02292 }
02293 
02294 
02295 inline void CBDB_Field::SetName(const char* name)
02296 {
02297     _ASSERT(name);
02298     m_Name = name;
02299 }
02300 
02301 inline bool CBDB_Field::IsByteSwapped() const
02302 {
02303     return m_BufferManager->IsByteSwapped();
02304 }
02305 
02306 /////////////////////////////////////////////////////////////////////////////
02307 //  CBDB_FieldString::
02308 //
02309 
02310 inline CBDB_FieldFixedByteString::operator const char* () const
02311 {
02312     const char* str = (const char*) GetBuffer();
02313     _ASSERT(str);
02314     return str;
02315 }
02316 
02317 
02318 inline
02319 void CBDB_FieldFixedByteString::Set(const char* str)
02320 {
02321     ::memcpy((char*)GetBuffer(), str, GetBufferSize());
02322 }
02323 
02324 inline
02325 string CBDB_FieldFixedByteString::Get() const
02326 {
02327     _ASSERT(!IsNull());
02328 
02329     const char* buf = (const char*) GetBuffer();
02330     return string(buf, GetBufferSize());
02331 }
02332 
02333 inline
02334 int CBDB_FieldFixedByteString::Compare(const void* p1,
02335                                        const void* p2,
02336                                        bool /*byte_swapped*/) const
02337 {
02338     return ::memcmp(p1, p2, GetBufferSize());
02339 }
02340 
02341 inline
02342 size_t CBDB_FieldFixedByteString::GetDataLength(const void* buf) const
02343 {
02344     return GetBufferSize();
02345 }
02346 
02347 inline
02348 void CBDB_FieldFixedByteString::SetMinVal()
02349 {
02350     void* buf = Unpack();
02351     ::memset(buf, 0, GetBufferSize());
02352 }
02353 
02354 inline
02355 void CBDB_FieldFixedByteString::SetMaxVal()
02356 {
02357     void* buf = Unpack();
02358     ::memset(buf, 0xFF, GetBufferSize());
02359 }
02360 
02361 /////////////////////////////////////////////////////////////////////////////
02362 //  CBDB_FieldString::
02363 //
02364 
02365 inline CBDB_FieldString::CBDB_FieldString()
02366     : CBDB_FieldStringBase()
02367 {
02368     SetBufferSize(256);
02369 }
02370 
02371 
02372 inline CBDB_FieldString::operator const char* () const
02373 {
02374     const char* str = (const char*) GetBuffer();
02375     _ASSERT(str);
02376     return str;
02377 }
02378 
02379 
02380 inline
02381 CBDB_FieldString&
02382 CBDB_FieldString::operator= (const CBDB_FieldString& str)
02383 {
02384     if (this == &str)
02385         return *this;
02386 
02387     size_t len = str.GetLength();
02388     if (len > GetBufferSize()) {
02389         // TODO: allow partial string assignment?
02390         BDB_THROW(eOverflow, "String field overflow.");
02391     }
02392     Unpack();
02393     ::strcpy((char*)GetBuffer(), (const char*) str);
02394 
02395     if ( str.IsNull() ) {
02396         SetNull();
02397     } else {
02398         SetNotNull();
02399     }
02400 
02401     return *this;
02402 }
02403 
02404 
02405 inline
02406 void CBDB_FieldString::Set(const char* str, EOverflowAction if_overflow)
02407 {
02408     if ( !str )
02409         str = kEmptyCStr;
02410 
02411     size_t new_len = ::strlen(str) + 1;
02412 
02413     // check overflow
02414     if (new_len > GetBufferSize()) {
02415         switch (if_overflow) {
02416         case eTruncateOnOverflowLogError:
02417             LOG_POST(Warning << "Value truncated for field '"
02418                     << GetName() << "'");
02419             /* FALLTHROUGH */
02420         case eTruncateOnOverflow:
02421             new_len = GetBufferSize();
02422             break;
02423         case eThrowOnOverflow:
02424             string msg("String field '");
02425             msg += GetName();
02426             msg += "' overflow: max size = ";
02427             msg += NStr::IntToString(GetBufferSize());
02428             msg += ", assignee size = ";
02429             msg += NStr::IntToString(new_len);
02430             BDB_THROW(eOverflow, msg);
02431             break;
02432         }
02433     }
02434     Unpack();
02435     ::memcpy(GetBuffer(), str, new_len);
02436     SetNotNull();
02437 }
02438 
02439 inline
02440 void CBDB_FieldString::SetString(const char* str)
02441 {
02442     operator=(str);
02443 }
02444 
02445 inline int CBDB_FieldString::Compare(const void* p1,
02446                                      const void* p2,
02447                                      bool /*byte_swapped*/) const
02448 {
02449     _ASSERT(p1 && p2);
02450     return ::strcmp((const char*) p1, (const char*) p2);
02451 }
02452 
02453 
02454 inline void CBDB_FieldString::SetMinVal()
02455 {
02456     ((char*) Unpack())[0] = '\0';
02457 }
02458 
02459 
02460 inline void CBDB_FieldString::SetMaxVal()
02461 {
02462     void* buf = Unpack();
02463     // TODO:  find out whether xFF or 0x7F should be used, and how
02464     //        (because of possible 'signed char' comparison in strcmp()).
02465     ::memset(buf, 0x7F, GetBufferSize()); // 0xFF for international
02466     ((char*) buf)[GetBufferSize() - 1] = '\0';
02467 
02468     SetNotNull();
02469 }
02470 
02471 
02472 inline bool CBDB_FieldString::IsEmpty() const
02473 {
02474     const char* str = (const char*) GetBuffer();
02475     _ASSERT(str);
02476     return !*str;
02477 }
02478 
02479 
02480 inline bool CBDB_FieldString::IsBlank() const
02481 {
02482     const char* str = (const char*) GetBuffer();
02483     _ASSERT(str);
02484     for (;  *str;  ++str) {
02485         if ( !isspace((unsigned char)(*str)) )
02486             return false;
02487     }
02488     return true;
02489 }
02490 
02491 
02492 inline size_t CBDB_FieldString::GetDataLength(const void* buf) const
02493 {
02494     _ASSERT(buf);
02495     return ::strlen((const char*) buf) + 1;
02496 }
02497 
02498 
02499 inline CBDB_FieldString& CBDB_FieldString::operator= (const char* str)
02500 {
02501     Set(str, eThrowOnOverflow);
02502     return *this;
02503 }
02504 
02505 inline CBDB_FieldString& CBDB_FieldString::operator= (const string& str)
02506 {
02507     return this->operator=(str.c_str());
02508 }
02509 
02510 
02511 
02512 /////////////////////////////////////////////////////////////////////////////
02513 //  CBDB_BufferManager::
02514 //
02515 
02516 
02517 inline const CBDB_Field& CBDB_BufferManager::GetField(unsigned int n) const
02518 {
02519     return *m_Fields[n];
02520 }
02521 
02522 
02523 inline CBDB_Field& CBDB_BufferManager::GetField(unsigned int n)
02524 {
02525     return *m_Fields[n];
02526 }
02527 
02528 
02529 inline unsigned int CBDB_BufferManager::FieldCount() const
02530 {
02531     return (unsigned int)m_Fields.size();
02532 }
02533 
02534 
02535 inline bool CBDB_BufferManager::IsPackable() const
02536 {
02537     return m_Packable;
02538 }
02539 
02540 
02541 inline bool CBDB_BufferManager::IsNullable() const
02542 {
02543     return m_Nullable;
02544 }
02545 
02546 
02547 inline void CBDB_BufferManager::SetNullable()
02548 {
02549     _ASSERT(m_Buffer == 0);
02550     m_Nullable = true;
02551 }
02552 
02553 
02554 inline size_t CBDB_BufferManager::ComputeNullSetSize() const
02555 {
02556     if ( !IsNullable() )
02557         return 0;
02558 
02559     return (FieldCount() + 7) / 8;
02560 }
02561 
02562 
02563 inline bool CBDB_BufferManager::TestNullBit(unsigned int n) const
02564 {
02565     _ASSERT(IsNullable());
02566 
02567     const unsigned char* buf  = (unsigned char*) m_Buffer;
02568     unsigned char        mask = (unsigned char) (1 << (n & 7));
02569     const unsigned char* offs = buf + (n >> 3);
02570 
02571     return ((*offs) & mask) != 0;
02572 }
02573 
02574 
02575 inline void CBDB_BufferManager::SetNullBit(unsigned int n, bool value)
02576 {
02577     _ASSERT(IsNullable());
02578 
02579     unsigned char* buf  = (unsigned char*) m_Buffer;
02580     unsigned char  mask = (unsigned char) (1 << (n & 7));
02581     unsigned char* offs = buf + (n >> 3);
02582 
02583     (void) (value ? (*offs |= mask) : (*offs &= ~mask));
02584 }
02585 
02586 
02587 inline void CBDB_BufferManager::SetNull(unsigned int field_idx, bool value)
02588 {
02589     if ( !IsNullable() )
02590         return;
02591     _ASSERT(field_idx < m_Fields.size());
02592     SetNullBit(field_idx, value);
02593 }
02594 
02595 
02596 inline void CBDB_BufferManager::SetAllNull()
02597 {
02598     if ( !IsNullable() )
02599         return;
02600     unsigned char* buf = (unsigned char*) m_Buffer;
02601     for (size_t i = 0;  i < m_NullSetSize;  ++i) {
02602         *buf++ = (unsigned char) 0xFF;
02603     }
02604 }
02605 
02606 
02607 inline bool CBDB_BufferManager::HasNull() const
02608 {
02609     if (IsNullable()) {
02610         for (size_t i = 0;  i < m_NullSetSize;  ++i) {
02611             if (m_Buffer[i])
02612                 return true;
02613         }
02614     }
02615     return false;
02616 }
02617 
02618 
02619 inline bool CBDB_BufferManager::IsNull(unsigned field_idx) const
02620 {
02621     if ( !IsNullable() )
02622         return false;
02623 
02624     _ASSERT(field_idx < m_Fields.size());
02625 
02626     return TestNullBit(field_idx);
02627 }
02628 
02629 
02630 inline void CBDB_BufferManager::ArrangePtrsUnpacked()
02631 {
02632     if ( !m_PackedSize )
02633         return;
02634 
02635     if ( !IsPackable() ) {
02636         m_PackedSize = 0;
02637         return;
02638     }
02639 
02640     for (size_t i = 0;  i < m_Fields.size();  ++i) {
02641         CBDB_Field& df = GetField((unsigned)i);
02642         df.SetBuffer(m_Ptrs[i]);
02643     }
02644 
02645     m_PackedSize = 0;  // not packed
02646 }
02647 
02648 
02649 inline void CBDB_BufferManager::Clear()
02650 {
02651     ::memset(m_Buffer, 0, m_BufferSize);
02652     ArrangePtrsUnpacked();
02653 }
02654 
02655 
02656 inline
02657 void CBDB_BufferManager::CopyFieldsFrom(const CBDB_BufferManager& buf_mgr)
02658 {
02659     unsigned int field_count = min(FieldCount(), buf_mgr.FieldCount());
02660 
02661     for (unsigned int i = 0;  i < field_count;  ++i) {
02662         CBDB_Field* fld = m_Fields[i];
02663         fld->CopyFrom(buf_mgr.GetField(i));
02664     }
02665 }
02666 
02667 
02668 inline
02669 void CBDB_BufferManager::SetMinVal(unsigned int idx_from, unsigned int idx_to)
02670 {
02671     _ASSERT(idx_to <= FieldCount());
02672 
02673     for ( ;  idx_from < idx_to;  ++idx_from) {
02674         CBDB_Field& fld = GetField(idx_from);
02675         fld.SetMinVal();
02676     }
02677 }
02678 
02679 
02680 inline
02681 void CBDB_BufferManager::SetMaxVal(unsigned int idx_from, unsigned int idx_to)
02682 {
02683     _ASSERT(idx_to <= FieldCount());
02684 
02685     for ( ;  idx_from < idx_to;  ++idx_from) {
02686         CBDB_Field& fld = GetField(idx_from);
02687         fld.SetMaxVal();
02688     }
02689 }
02690 
02691 inline
02692 void CBDB_BufferManager::SetFieldCompareLimit(unsigned int n_fields)
02693 {
02694     m_CompareLimit = n_fields;
02695 }
02696 
02697 inline
02698 unsigned int CBDB_BufferManager::GetFieldCompareLimit() const
02699 {
02700     return m_CompareLimit;
02701 }
02702 
02703 // Delete all field objects bound to field buffer.
02704 // Should be used with extreme caution. After calling this buf object should
02705 // never be used again. All fields bound to the buffer must be dynamically
02706 // allocated.
02707 inline
02708 void DeleteFields(CBDB_BufferManager& buf)
02709 {
02710     for (unsigned int i = 0;  i < buf.FieldCount();  ++i) {
02711         CBDB_Field* fld = &buf.GetField(i);
02712         delete fld;
02713     }
02714 }
02715 
02716 
02717 END_NCBI_SCOPE
02718 
02719 
02720 
02721 #endif  /* BDB_TYPES__HPP */
02722 
02723 

Generated on Wed Dec 9 03:00:37 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:17:27 2009 by modify_doxy.py rev. 173732