1 #ifndef BDB_TYPES__HPP
2 #define BDB_TYPES__HPP
3 
4 /* $Id: bdb_types.hpp 617975 2020-10-08 18:28:17Z grichenk $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author:  Anatoliy Kuznetsov
30  *
31  * File Description: Field types classes.
32  *
33  */
34 
35 #include <db/bdb/bdb_expt.hpp>
36 #include <corelib/ncbi_limits.hpp>
37 #include <corelib/ncbi_bswap.hpp>
38 #include <corelib/ncbistr.hpp>
39 #include <util/simple_buffer.hpp>
40 
41 #include <string>
42 #include <vector>
43 #include <memory>
44 
45 
46 extern "C" {
47     //
48     // Forward structure declarations, so we can declare pointers and
49     // applications can get type checking.
50     // Taken from <db.h>
51     struct __db_dbt; typedef struct __db_dbt DBT;
52     struct __db;     typedef struct __db     DB;
53     struct __dbc;    typedef struct __dbc    DBC;
54     struct __db_env; typedef struct __db_env DB_ENV;
55     struct __db_txn; typedef struct __db_txn DB_TXN;
56 
57     typedef int (*BDB_CompareFunction)(DB*, const DBT*, const DBT*);
58     typedef unsigned int (*BDB_HashFunction)
59                             (DB *, const void *bytes, unsigned length);
60 }
61 
62 BEGIN_NCBI_SCOPE
63 
64 /** @addtogroup BDB_Types
65  *
66  * @{
67  */
68 
69 
70 extern "C" {
71 
72 
73 /// Simple and fast comparison function for tables with
74 /// non-segmented "unsigned int" keys
75 NCBI_DEPRECATED
76 NCBI_BDB_EXPORT int BDB_UintCompare(DB*, const DBT* val1, const DBT* val2);
77 NCBI_BDB_EXPORT int BDB_Uint4Compare(DB*, const DBT* val1, const DBT* val2);
78 
79 /// Simple and fast comparison function for tables with
80 /// non-segmented "int" keys
81 NCBI_DEPRECATED
82 NCBI_BDB_EXPORT int BDB_IntCompare(DB*, const DBT* val1, const DBT* val2);
83 NCBI_BDB_EXPORT int BDB_Int4Compare(DB*, const DBT* val1, const DBT* val2);
84 
85 /// Simple and fast comparison function for tables with
86 /// non-segmented "Int8" keys
87 NCBI_BDB_EXPORT int BDB_Int8Compare(DB*, const DBT* val1, const DBT* val2);
88 
89 /// Simple and fast comparison function for tables with
90 /// non-segmented "Uint8" keys
91 NCBI_BDB_EXPORT int BDB_Uint8Compare(DB*, const DBT* val1, const DBT* val2);
92 
93 /// Simple and fast comparison function for tables with
94 /// non-segmented "short int" keys
95 NCBI_BDB_EXPORT int BDB_Int2Compare(DB*, const DBT* val1, const DBT* val2);
96 
97 /// Simple and fast comparison function for tables with
98 /// non-segmented "unsigned short int" keys
99 NCBI_BDB_EXPORT int BDB_Uint2Compare(DB*, const DBT* val1, const DBT* val2);
100 
101 /// Simple and fast comparison function for tables with
102 /// non-segmented "char" keys
103 NCBI_BDB_EXPORT int BDB_CharCompare(DB*, const DBT* val1, const DBT* val2);
104 
105 /// Simple and fast comparison function for tables with
106 /// non-segmented "unsigned char" keys
107 NCBI_BDB_EXPORT int BDB_UCharCompare(DB*, const DBT* val1, const DBT* val2);
108 
109 /// Simple and fast comparison function for tables with
110 /// non-segmented "float" keys
111 NCBI_BDB_EXPORT int BDB_FloatCompare(DB*, const DBT* val1, const DBT* val2);
112 
113 /// Simple and fast comparison function for tables with
114 /// non-segmented "double" keys
115 NCBI_BDB_EXPORT int BDB_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
116 
117 /// Simple and fast comparison function for tables with
118 /// non-segmented "C string" keys
119 NCBI_BDB_EXPORT int BDB_StringCompare(DB*, const DBT* val1, const DBT* val2);
120 
121 /// Simple and fast comparison function for tables with
122 /// non-segmented length prefixed string keys
123 NCBI_BDB_EXPORT int BDB_LStringCompare(DB*, const DBT* val1, const DBT* val2);
124 
125 /// Simple and fast comparison function for tables with
126 /// non-segmented fixed length string keys
127 NCBI_BDB_EXPORT int BDB_FixedByteStringCompare
128                                     (DB*, const DBT* val1, const DBT* val2);
129 
130 
131 /// Simple and fast comparison function for tables with
132 /// non-segmented "case insensitive C string" keys
133 NCBI_BDB_EXPORT int
134 BDB_StringCaseCompare(DB*, const DBT* val1, const DBT* val2);
135 
136 /// General purpose DBD comparison function
137 int NCBI_BDB_EXPORT BDB_Compare(DB* db, const DBT* val1, const DBT* val2);
138 
139 
140 
141 /// Simple and fast comparison function for tables with
142 /// non-segmented "unsigned int" keys.
143 /// Used when the data file is in a different byte order architecture.
144 NCBI_DEPRECATED
145 NCBI_BDB_EXPORT int
146 BDB_ByteSwap_UintCompare(DB*, const DBT* val1, const DBT* val2);
147 NCBI_BDB_EXPORT int
148 BDB_ByteSwap_Uint4Compare(DB*, const DBT* val1, const DBT* val2);
149 
150 /// Simple and fast comparison function for tables with
151 /// non-segmented "Int8" keys
152 /// Used when the data file is in a different byte order architecture.
153 NCBI_BDB_EXPORT int
154 BDB_ByteSwap_Int8Compare(DB*, const DBT* val1, const DBT* val2);
155 
156 /// Simple and fast comparison function for tables with
157 /// non-segmented "Uint8" keys
158 /// Used when the data file is in a different byte order architecture.
159 NCBI_BDB_EXPORT int
160 BDB_ByteSwap_Uint8Compare(DB*, const DBT* val1, const DBT* val2);
161 
162 /// Simple and fast comparison function for tables with
163 /// non-segmented "int" keys
164 /// Used when the data file is in a different byte order architecture.
165 NCBI_DEPRECATED
166 NCBI_BDB_EXPORT int
167 BDB_ByteSwap_IntCompare(DB*, const DBT* val1, const DBT* val2);
168 NCBI_BDB_EXPORT int
169 BDB_ByteSwap_Int4Compare(DB*, const DBT* val1, const DBT* val2);
170 
171 /// Simple and fast comparison function for tables with
172 /// non-segmented "short int" keys
173 /// Used when the data file is in a different byte order architecture.
174 NCBI_BDB_EXPORT int
175 BDB_ByteSwap_Int2Compare(DB*, const DBT* val1, const DBT* val2);
176 
177 /// Simple and fast comparison function for tables with
178 /// non-segmented "unsigned short int" keys
179 /// Used when the data file is in a different byte order architecture.
180 NCBI_BDB_EXPORT int
181 BDB_ByteSwap_Uint2Compare(DB*, const DBT* val1, const DBT* val2);
182 
183 /// Simple and fast comparison function for tables with
184 /// non-segmented "float" keys
185 /// Used when the data file is in a different byte order architecture.
186 NCBI_BDB_EXPORT int
187 BDB_ByteSwap_FloatCompare(DB*, const DBT* val1, const DBT* val2);
188 
189 /// Simple and fast comparison function for tables with
190 /// non-segmented "double" keys
191 /// Used when the data file is in a different byte order architecture.
192 NCBI_BDB_EXPORT int
193 BDB_ByteSwap_DoubleCompare(DB*, const DBT* val1, const DBT* val2);
194 
195 
196 /// General purpose hash function
197 unsigned int
198 NCBI_BDB_EXPORT BDB_Hash(DB *, const void *bytes, unsigned length);
199 
200 /// Hash method for databases with a single (unique) UInt4 key
201 unsigned int
202 NCBI_BDB_EXPORT BDB_Uint4Hash(DB *, const void *bytes, unsigned length);
203 
204 
205 }
206 
207 
208 class CBDB_BufferManager;
209 class CBDB_Field;
210 class CBDB_File;
211 class CBDB_FileCursor;
212 class CBDB_FC_Condition;
213 
214 
215 
216 
217 /// BDB Data Field interface definition.
218 ///
219 /// Every relational table in BDB library consists of fields, supporting
220 /// basic IBDB_Field interface
221 class NCBI_BDB_EXPORT IBDB_Field
222 {
223 public:
224     virtual ~IBDB_Field();
225 
226     /// Comparison function. p1 and p2 are void pointers on field buffers.
227     /// Positive if p1>p2, zero if p1==p2, negative if p1<p2.
228     /// NOTE:  both buffers can be unaligned.
229     /// byte_swapped TRUE indicates that buffers values are in
230     /// a different byte order architecture
231     virtual int         Compare(const void* p1,
232                                 const void* p2,
233                                 bool byte_swapped) const = 0;
234 
235     /// Return current effective size of the buffer.
236     virtual size_t      GetDataLength(const void* buf) const = 0;
237 
238     /// Set minimal possible value for the field type
239     virtual void        SetMinVal() = 0;
240 
241     /// Set maximum possible value for the field type
242     virtual void        SetMaxVal() = 0;
243 };
244 
245 
246 
247 /// BDB Data Field conversion interface definition.
248 /// All interface functions by default throw "bad conversion" exception.
249 
250 class NCBI_BDB_EXPORT IBDB_FieldConvert
251 {
252 public:
~IBDB_FieldConvert()253     virtual ~IBDB_FieldConvert() {}
254 
SetInt(int)255     virtual void SetInt(int)
256         { BDB_THROW(eType, "Bad conversion"); }
SetUint(unsigned)257     virtual void SetUint(unsigned)
258         { BDB_THROW(eType, "Bad conversion"); }
GetInt() const259     virtual int GetInt() const
260         { BDB_THROW(eType, "Bad conversion"); }
GetUint() const261     virtual unsigned GetUint() const
262         { BDB_THROW(eType, "Bad conversion"); }
SetString(const char *)263     virtual void SetString(const char*)
264         { BDB_THROW(eType, "Bad conversion"); }
SetStdString(const string &)265     virtual void SetStdString(const string&)
266         { BDB_THROW(eType, "Bad conversion"); }
SetFloat(float)267     virtual void SetFloat(float)
268         { BDB_THROW(eType, "Bad conversion"); }
SetDouble(double)269     virtual void SetDouble(double)
270         { BDB_THROW(eType, "Bad conversion"); }
271 
272     virtual string GetString() const = 0;
273 
274     virtual void ToString(string& str) const = 0;
275 };
276 
277 
278 
279 /// Interface definition class for field construction.
280 /// Used for interfaces' "access rights management".
281 
282 class CBDB_FieldInterfaces : public  IBDB_Field,
283                              public  IBDB_FieldConvert
284 {
285     friend class CBDB_FileCursor;
286 };
287 
288 
289 
290 /// Base class for constructing BDB fields. Implements field buffer pointer.
291 ///
292 /// All DBD field types do not own their buffers.
293 /// It works as a pointer on external memory kept by the record manager
294 /// (CBDB_FieldBuf). Class cannot be used independently without record manager.
295 
296 class NCBI_BDB_EXPORT CBDB_Field : public CBDB_FieldInterfaces
297 {
298 public:
299     /// Length based classificator for fields (fixed-variable)
300     enum ELengthType {
301         eFixedLength,    //!< fixed-length (like int)
302         eVariableLength  //!< variable-length (like string)
303     };
304     CBDB_Field(ELengthType length_type = eFixedLength);
~CBDB_Field()305     virtual ~CBDB_Field() {}
306 
307     /// Virtual constructor - class factory for BDB fields.
308     /// Default (zero) value of 'buf-len' uses GetBufferSize().
309     /// For fixed length fields this buf_size parameter has no effect
310     virtual CBDB_Field* Construct(size_t buf_size = 0) const = 0;
311 
312     /// Return address to the type specific comparison function
313     /// By default it's universal BDB_Compare
314     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const;
315 
316     /// Return TRUE if field can be NULL
317     bool IsNullable() const;
318 
319     /// Assign field value to NULL
320     void SetNull();
321 
322     /// Return TRUE if field is NULL
323     bool IsNull() const;
324 
325     /// Return symbolic name for the field
326     const string& GetName() const;
327 
328     /// Get pointer to the data. NULL if not yet attached.
329     const void* GetBuffer() const;
330     /// Get pointer to the data. NULL if not yet attached.
331     void*       GetBuffer();
332 
333     /// Return maximum possible buffer length
334     size_t GetBufferSize() const;
335 
336     /// Get length of the actual data
337     size_t GetLength() const;
338 
339 protected:
340 
341     /// Field comparison function
342     int CompareWith(const CBDB_Field& field) const;
343 
344     /// Copies field value from another field.
345     /// The field type MUST be the same, or an exception will be thrown.
346     void CopyFrom(const CBDB_Field& src);
347 
348     // Buffer management functions:
349 
350     /// Return TRUE if it is a variable length variable (like string)
351     bool IsVariableLength() const;
352 
353     /// Return TRUE if external buffer has already been attached
354     bool IsBufferAttached() const;
355 
356     /// RTTI based check if fld is of the same type
357     bool IsSameType(const CBDB_Field& field) const;
358 
359     /// Return TRUE if field belongs to a file with an alternative
360     /// byte order
361     bool IsByteSwapped() const;
362 
363 
364     /// Mark field as "NULL" capable.
365     void SetNullable();
366 
367     /// Set "is NULL" flag to FALSE
368     void SetNotNull();
369 
370     /// Set symbolic name for the field
371     void SetName(const char* name);
372 
373     /// Set field position in the buffer manager
374     void SetBufferIdx(unsigned int idx);
375 
376 
377 protected:
378     /// Unpack the buffer which contains this field (using CBDB_BufferManager).
379     /// Return new pointer to the field data -- located in the unpacked buffer.
380     void*  Unpack();
381     /// Set external buffer pointer and length.
382     /// Zero 'buf_size' means GetBufferSize() is used to obtain the buf. size.
383     void  SetBuffer(void* buf, size_t buf_size = 0);
384     /// Set the buffer size.
385     void  SetBufferSize(size_t size);
386     /// Set data size, taking into account possible extra data for some fields
387     void SetDataSize(size_t size);
388     /// Hook for defining extra data length
389     virtual size_t GetExtraDataLength();
390     /// Set CBDB_BufferManager -- which works as a memory manager for BDB fields.
391     void  SetBufferManager(CBDB_BufferManager* owner);
392 
393     /// Copy buffer value from the external source
394     void CopyFrom(const void* src_buf);
395 
396 private:
397     CBDB_Field& operator= (const CBDB_Field& data);
398     CBDB_Field(const CBDB_Field& data);
399 
400 protected:
401     CBDB_BufferManager*  m_BufferManager;
402     struct {
403         unsigned VariableLength : 1;
404         unsigned Attached       : 1;
405         unsigned Nullable       : 1;
406     } m_Flags;
407 private:
408     void*      m_Buffer;       // Pointer to the field data (in buf. mgr.)
409     size_t     m_BufferSize;   // Field data buffer capacity
410     unsigned   m_BufferIdx;    // Fields' position in the managing buffer
411     string     m_Name;         // Field's symbolic name
412 
413     // Friends
414     friend class CBDB_BufferManager;
415     friend class CBDB_File;
416     friend class CBDB_BLobFile;
417 };
418 
419 
420 
421 /// Template class for building simple scalar data fields.
422 /// (int, float, double)
423 
424 template<typename T>
425 class CBDB_FieldSimple : public CBDB_Field
426 {
427 public:
428     typedef  T  TFieldType;
429 public:
CBDB_FieldSimple()430     CBDB_FieldSimple()
431     : CBDB_Field(eFixedLength)
432     {
433         SetBufferSize(sizeof(T));
434     }
435 
SetField(const CBDB_FieldSimple & field)436     void SetField(const CBDB_FieldSimple& field)
437     {
438         if ( field.IsNull() ) {
439             SetNull();
440         } else {
441             if (IsByteSwapped() != field.IsByteSwapped()) {
442                 BDB_THROW(eInvalidValue, "Byte order incompatibility");
443             }
444 #ifdef HAVE_UNALIGNED_READS
445             TFieldType* b = (TFieldType*) GetBuffer();
446             TFieldType* f = (TFieldType*) field.GetBuffer();
447             *b = *f;
448 #else
449             ::memcpy(GetBuffer(), field.GetBuffer(), sizeof(T));
450 #endif
451             SetNotNull();
452         }
453     }
454 
455     // IDBD_Field implementation
456 
Compare(const void * p1,const void * p2,bool) const457     virtual int Compare(const void* p1,
458                         const void* p2,
459                         bool/* byte_swapped*/) const
460     {
461         // Default implementation ignores byte swapping
462         T v1, v2;
463 
464 #ifdef HAVE_UNALIGNED_READS
465         v1 = *((TFieldType*)p1);
466         v2 = *((TFieldType*)p2);
467 #else
468         ::memcpy(&v1, p1, sizeof(v1));
469         ::memcpy(&v2, p2, sizeof(v2));
470 #endif
471         if (v1 < v2) return -1;
472         if (v2 < v1) return 1;
473         return 0;
474     }
475 
GetDataLength(const void *) const476     virtual size_t GetDataLength(const void* /*buf*/) const
477     {
478         return sizeof(T);
479     }
480 };
481 
482 
483 
484 /// Template class for building simple scalar integer compatible data fields.
485 /// (int, short, char)
486 
487 template<typename T>
488 class CBDB_FieldSimpleInt : public CBDB_FieldSimple<T>
489 {
490 public:
CBDB_FieldSimpleInt()491     CBDB_FieldSimpleInt() : CBDB_FieldSimple<T>() {}
492 
Set(T val)493     void Set(T val)
494     {
495         if (this->IsByteSwapped()) {
496 
497             if (sizeof(T) == 2) {
498                 CByteSwap::PutInt2((unsigned char*)this->GetBuffer(),
499                                    (Int2) val);
500             } else
501             if (sizeof(T) == 4) {
502                 CByteSwap::PutInt4((unsigned char*)this->GetBuffer(),
503                                    (Int4) val);
504             } else
505             if (sizeof(T) == 8) {
506                 CByteSwap::PutInt8((unsigned char*)this->GetBuffer(),
507                                    (Int8) val);
508             }
509             else {
510                 _ASSERT(0);
511             }
512 
513         } else {
514 #ifdef HAVE_UNALIGNED_READS
515             typename CBDB_FieldSimple<T>::TFieldType* b =
516                 (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
517             *b = val;
518 #else
519             ::memcpy(this->GetBuffer(), &val, sizeof(T));
520 #endif
521         }
522         this->SetNotNull();
523     }
524 
SetInt(int val)525     virtual void SetInt    (int          val)  { Set((T) val); }
SetUint(unsigned int val)526     virtual void SetUint   (unsigned int val)  { Set((T) val); }
SetString(const char * val)527     virtual void SetString (const char*  val)
528     {
529         long v = ::atol(val);
530         Set((T) v);
531     }
532 
GetInt() const533     virtual int GetInt() const
534     {
535         int value;
536 #ifdef HAVE_UNALIGNED_READS
537         typename CBDB_FieldSimple<T>::TFieldType* b =
538             (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
539         value = (int)*b;
540 #else
541         ::memcpy(&value, this->GetBuffer(), sizeof(T));
542 #endif
543         return value;
544     }
545 
GetUint() const546     virtual unsigned GetUint() const
547     {
548         unsigned value;
549 #ifdef HAVE_UNALIGNED_READS
550         typename CBDB_FieldSimple<T>::TFieldType* b =
551             (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
552         value = (unsigned)*b;
553 #else
554         ::memcpy(&value, this->GetBuffer(), sizeof(T));
555 #endif
556         return value;
557     }
558 
SetStdString(const string & str)559     virtual void SetStdString(const string& str)
560     {
561         SetString(str.c_str());
562     }
563 
Compare(const void * p1,const void * p2,bool byte_swapped) const564     virtual int Compare(const void* p1,
565                         const void* p2,
566                         bool byte_swapped) const
567     {
568         if (!byte_swapped)
569             return CBDB_FieldSimple<T>::Compare(p1, p2, byte_swapped);
570 
571         T v1, v2;
572         v1 = (T) CByteSwap::GetInt4((unsigned char*)p1);
573         v2 = (T) CByteSwap::GetInt4((unsigned char*)p2);
574         if (v1 < v2) return -1;
575         if (v2 < v1) return 1;
576         return 0;
577     }
578 
SetMinVal()579     virtual void SetMinVal()
580     {
581         Set(numeric_limits<T>::min());
582     }
583 
SetMaxVal()584     virtual void SetMaxVal()
585     {
586         Set(numeric_limits<T>::max());
587     }
588 };
589 
590 
591 
592 /// Template class for building simple scalar floating point compatible fields.
593 /// (float, double)
594 ///
595 
596 template<typename T>
597 class CBDB_FieldSimpleFloat : public CBDB_FieldSimple<T>
598 {
599 public:
CBDB_FieldSimpleFloat()600     CBDB_FieldSimpleFloat() : CBDB_FieldSimple<T>() {}
601 
Set(T val)602     void Set(T val)
603     {
604         if (this->IsByteSwapped()) {
605 
606             if (sizeof(T) == 4) {
607                 CByteSwap::PutFloat((unsigned char*)this->GetBuffer(),
608                                     (float)val);
609             } else
610             if (sizeof(T) == 8) {
611                 CByteSwap::PutDouble((unsigned char*)this->GetBuffer(), val);
612             }
613             else {
614                 _ASSERT(0);
615             }
616         } else {
617 #ifdef HAVE_UNALIGNED_READS
618             typename CBDB_FieldSimple<T>::TFieldType* b =
619                 (typename CBDB_FieldSimple<T>::TFieldType*) this->GetBuffer();
620             *b = val;
621 #else
622             ::memcpy(this->GetBuffer(), &val, sizeof(T));
623 #endif
624         }
625         this->SetNotNull();
626     }
627 
SetInt(int val)628     virtual void SetInt    (int          val) { Set((T) val); }
SetUint(unsigned int val)629     virtual void SetUint   (unsigned int val) { Set((T) val); }
SetString(const char * val)630     virtual void SetString (const char*  val)
631     {
632         double v = ::atof(val);
633         Set((T) v);
634     }
SetStdString(const string & str)635     virtual void SetStdString(const string& str)
636     {
637         SetString(str.c_str());
638     }
639 
SetFloat(float val)640     virtual void SetFloat (float  val) { Set((T) val); }
SetDouble(double val)641     virtual void SetDouble(double val) { Set((T) val); }
642 
SetMinVal()643     virtual void SetMinVal()
644     {
645         Set(numeric_limits<T>::min());
646     }
647 
SetMaxVal()648     virtual void SetMaxVal()
649     {
650         Set(numeric_limits<T>::max());
651     }
652 };
653 
654 
655 ///  Int8 field type
656 ///
657 
658 class NCBI_BDB_EXPORT CBDB_FieldInt8 : public CBDB_FieldSimpleInt<Int8>
659 {
660 public:
operator =(Int8 val)661     CBDB_FieldInt8& operator= (Int8 val)
662     {
663         Set(val);
664         return *this;
665     }
666 
operator =(const CBDB_FieldInt8 & val)667     CBDB_FieldInt8& operator= (const CBDB_FieldInt8& val)
668     {
669         Set(val);
670         return *this;
671     }
672 
Construct(size_t) const673     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
674     {
675         return new CBDB_FieldInt8();
676     }
677 
Get() const678     Int8 Get() const
679     {
680         Int8  v;
681 
682         _ASSERT(!IsNull());
683 
684         if (IsByteSwapped()) {
685             v = CByteSwap::GetInt8((unsigned char*)GetBuffer());
686         } else {
687 #ifdef HAVE_UNALIGNED_READS
688             TFieldType* b = (TFieldType*) this->GetBuffer();
689             v = *b;
690 #else
691             ::memcpy(&v, GetBuffer(), sizeof(Int8));
692 #endif
693         }
694         return v;
695     }
696 
GetString() const697     virtual string GetString() const
698     {
699         Int8  v = Get();
700         return NStr::Int8ToString(v);
701     }
702 
ToString(string & str) const703     virtual void ToString(string& str) const
704     {
705         Int8 v = Get();
706         NStr::Int8ToString(str, v);
707     }
708 
operator Int8() const709     operator Int8() const
710     {
711         return Get();
712     }
713 
GetCompareFunction(bool byte_swapped) const714     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
715     {
716         if (byte_swapped)
717             return BDB_ByteSwap_Int8Compare;
718         return BDB_Int8Compare;
719     }
720 
Compare(const void * p1,const void * p2,bool byte_swapped) const721     virtual int Compare(const void* p1,
722                         const void* p2,
723                         bool byte_swapped) const
724     {
725         if (!byte_swapped)
726             return CBDB_FieldSimpleInt<Int8>::Compare(p1, p2, byte_swapped);
727 
728         Int8 v1, v2;
729         v1 = CByteSwap::GetInt8((unsigned char*)p1);
730         v2 = CByteSwap::GetInt8((unsigned char*)p2);
731         if (v1 < v2) return -1;
732         if (v2 < v1) return 1;
733         return 0;
734     }
735 
736 };
737 
738 
739 ///  Uint8 field type
740 ///
741 
742 class NCBI_BDB_EXPORT CBDB_FieldUint8 : public CBDB_FieldSimpleInt<Uint8>
743 {
744 public:
operator =(Uint8 val)745     CBDB_FieldUint8& operator= (Uint8 val)
746     {
747         Set(val);
748         return *this;
749     }
750 
operator =(const CBDB_FieldUint8 & val)751     CBDB_FieldUint8& operator= (const CBDB_FieldUint8& val)
752     {
753         Set(val);
754         return *this;
755     }
756 
Construct(size_t) const757     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
758     {
759         return new CBDB_FieldUint8();
760     }
761 
Get() const762     Uint8 Get() const
763     {
764         Uint8  v;
765 
766         _ASSERT(!IsNull());
767 
768         if (IsByteSwapped()) {
769             v = CByteSwap::GetInt8((unsigned char*)GetBuffer());
770         } else {
771 #ifdef HAVE_UNALIGNED_READS
772             TFieldType* b = (TFieldType*) GetBuffer();
773             v = *b;
774 #else
775             ::memcpy(&v, GetBuffer(), sizeof(Uint8));
776 #endif
777         }
778         return v;
779     }
780 
GetString() const781     virtual string GetString() const
782     {
783         Uint8  v = Get();
784         return NStr::UInt8ToString(v);
785     }
786 
ToString(string & str) const787     virtual void ToString(string& str) const
788     {
789         Uint8 v = Get();
790         NStr::UInt8ToString(str, v);
791     }
792 
operator Uint8() const793     operator Uint8() const
794     {
795         return Get();
796     }
797 
GetCompareFunction(bool byte_swapped) const798     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
799     {
800         if (byte_swapped)
801             return BDB_ByteSwap_Uint8Compare;
802         return BDB_Uint8Compare;
803     }
804 
Compare(const void * p1,const void * p2,bool byte_swapped) const805     virtual int Compare(const void* p1,
806                         const void* p2,
807                         bool byte_swapped) const
808     {
809         if (!byte_swapped)
810             return CBDB_FieldSimpleInt<Uint8>::Compare(p1, p2, byte_swapped);
811 
812         Uint8 v1, v2;
813         v1 = CByteSwap::GetInt8((unsigned char*)p1);
814         v2 = CByteSwap::GetInt8((unsigned char*)p2);
815         if (v1 < v2) return -1;
816         if (v2 < v1) return 1;
817         return 0;
818     }
819 
820 };
821 
822 
823 ///  Int4 field type
824 ///
825 
826 class NCBI_BDB_EXPORT CBDB_FieldInt4 : public CBDB_FieldSimpleInt<Int4>
827 {
828 public:
operator =(Int4 val)829     CBDB_FieldInt4& operator= (Int4 val)
830     {
831         Set(val);
832         return *this;
833     }
834 
operator =(const CBDB_FieldInt4 & val)835     CBDB_FieldInt4& operator= (const CBDB_FieldInt4& val)
836     {
837         Set(val);
838         return *this;
839     }
840 
Construct(size_t) const841     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
842     {
843         return new CBDB_FieldInt4();
844     }
845 
Get() const846     Int4 Get() const
847     {
848         Int4  v;
849 
850         _ASSERT(!IsNull());
851 
852         if (IsByteSwapped()) {
853             v = CByteSwap::GetInt4((unsigned char*)GetBuffer());
854         } else {
855 #ifdef HAVE_UNALIGNED_READS
856             TFieldType* b = (TFieldType*)GetBuffer();
857             v = *b;
858 #else
859             ::memcpy(&v, GetBuffer(), sizeof(Int4));
860 #endif
861         }
862         return v;
863     }
864 
GetString() const865     virtual string GetString() const
866     {
867         Int4  v = Get();
868         return NStr::IntToString(v);
869     }
870 
ToString(string & str) const871     virtual void ToString(string& str) const
872     {
873         Int4 v = Get();
874         NStr::IntToString(str, v);
875     }
876 
operator Int4() const877     operator Int4() const
878     {
879         return Get();
880     }
881 
GetCompareFunction(bool byte_swapped) const882     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
883     {
884         if (byte_swapped)
885             return BDB_ByteSwap_Int4Compare;
886         return BDB_Int4Compare;
887     }
888 
Compare(const void * p1,const void * p2,bool byte_swapped) const889     virtual int Compare(const void* p1,
890                         const void* p2,
891                         bool byte_swapped) const
892     {
893         if (!byte_swapped)
894             return CBDB_FieldSimpleInt<Int4>::Compare(p1, p2, byte_swapped);
895 
896         Int4 v1, v2;
897         v1 = CByteSwap::GetInt4((unsigned char*)p1);
898         v2 = CByteSwap::GetInt4((unsigned char*)p2);
899         if (v1 < v2) return -1;
900         if (v2 < v1) return 1;
901         return 0;
902     }
903 
904 };
905 
906 
907 ///  Int2 field type
908 ///
909 
910 class NCBI_BDB_EXPORT CBDB_FieldInt2 : public CBDB_FieldSimpleInt<Int2>
911 {
912 public:
operator =(Int2 val)913     CBDB_FieldInt2& operator= (Int2 val)
914     {
915         Set(val);
916         return *this;
917     }
918 
operator =(const CBDB_FieldInt2 & val)919     CBDB_FieldInt2& operator= (const CBDB_FieldInt2& val)
920     {
921         Set(val);
922         return *this;
923     }
924 
Construct(size_t) const925     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
926     {
927         return new CBDB_FieldInt2();
928     }
929 
Get() const930     Int2 Get() const
931     {
932         Int2  v;
933 
934         _ASSERT(!IsNull());
935 
936         if (IsByteSwapped()) {
937             v = CByteSwap::GetInt2((unsigned char*)GetBuffer());
938         } else {
939 #ifdef HAVE_UNALIGNED_READS
940             TFieldType* b = (TFieldType*) GetBuffer();
941             v = *b;
942 #else
943             ::memcpy(&v, GetBuffer(), sizeof(Int2));
944 #endif
945         }
946         return v;
947     }
948 
GetString() const949     virtual string GetString() const
950     {
951         Int4  v = Get();
952         return NStr::IntToString(v);
953     }
954 
ToString(string & str) const955     virtual void ToString(string& str) const
956     {
957         Int4 v = Get();
958         NStr::IntToString(str, v);
959     }
960 
operator Int2() const961     operator Int2() const
962     {
963         return Get();
964     }
965 
GetCompareFunction(bool byte_swapped) const966     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
967     {
968         if (byte_swapped)
969             return BDB_ByteSwap_Int2Compare;
970         return BDB_Int2Compare;
971     }
972 
Compare(const void * p1,const void * p2,bool byte_swapped) const973     virtual int Compare(const void* p1,
974                         const void* p2,
975                         bool byte_swapped) const
976     {
977         if (!byte_swapped)
978             return CBDB_FieldSimpleInt<Int2>::Compare(p1, p2, byte_swapped);
979 
980         Int2 v1, v2;
981         v1 = CByteSwap::GetInt2((unsigned char*)p1);
982         v2 = CByteSwap::GetInt2((unsigned char*)p2);
983         if (v1 < v2) return -1;
984         if (v2 < v1) return 1;
985         return 0;
986     }
987 
988 };
989 
990 
991 /// Uint2 field type
992 ///
993 
994 class NCBI_BDB_EXPORT CBDB_FieldUint2 : public CBDB_FieldSimpleInt<Uint2>
995 {
996 public:
operator =(Uint2 val)997     CBDB_FieldUint2& operator= (Uint2 val)
998     {
999         Set(val);
1000         return *this;
1001     }
1002 
operator =(const CBDB_FieldUint2 & val)1003     CBDB_FieldUint2& operator= (const CBDB_FieldUint2& val)
1004     {
1005         Set(val);
1006         return *this;
1007     }
1008 
Construct(size_t) const1009     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
1010     {
1011         return new CBDB_FieldUint2();
1012     }
1013 
Get() const1014     Uint2 Get() const
1015     {
1016         Uint2  v;
1017 
1018         _ASSERT(!IsNull());
1019 
1020         if (IsByteSwapped()) {
1021             v = CByteSwap::GetInt2((unsigned char*)GetBuffer());
1022         } else {
1023 #ifdef HAVE_UNALIGNED_READS
1024             TFieldType* b = (TFieldType*) GetBuffer();
1025             v = *b;
1026 #else
1027             ::memcpy(&v, GetBuffer(), sizeof(Uint2));
1028 #endif
1029         }
1030         return v;
1031     }
1032 
GetString() const1033     virtual string GetString() const
1034     {
1035         Int4  v = Get();
1036         return NStr::IntToString(v);
1037     }
1038 
ToString(string & str) const1039     virtual void ToString(string& str) const
1040     {
1041         Int4 v = Get();
1042         NStr::IntToString(str, v);
1043     }
1044 
operator Uint2() const1045     operator Uint2() const
1046     {
1047         return Get();
1048     }
1049 
GetCompareFunction(bool byte_swapped) const1050     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
1051     {
1052         if (byte_swapped)
1053             return BDB_ByteSwap_Uint2Compare;
1054         return BDB_Uint2Compare;
1055     }
1056 
Compare(const void * p1,const void * p2,bool byte_swapped) const1057     virtual int Compare(const void* p1,
1058                         const void* p2,
1059                         bool byte_swapped) const
1060     {
1061         if (!byte_swapped)
1062             return CBDB_FieldSimpleInt<Uint2>::Compare(p1, p2, byte_swapped);
1063 
1064         Uint2 v1, v2;
1065         v1 = CByteSwap::GetInt2((unsigned char*)p1);
1066         v2 = CByteSwap::GetInt2((unsigned char*)p2);
1067         if (v1 < v2) return -1;
1068         if (v2 < v1) return 1;
1069         return 0;
1070     }
1071 
1072 };
1073 
1074 /// Char field type
1075 ///
1076 
1077 class CBDB_FieldUChar : public CBDB_FieldSimpleInt<unsigned char>
1078 {
1079 public:
operator =(unsigned char val)1080     CBDB_FieldUChar& operator = (unsigned char val)
1081     {
1082         Set(val);
1083         return *this;
1084     }
1085 
operator =(const CBDB_FieldUChar & val)1086     CBDB_FieldUChar& operator = (const CBDB_FieldUChar& val)
1087     {
1088         Set(val);
1089         return *this;
1090     }
1091 
Construct(size_t) const1092     virtual CBDB_Field * Construct(size_t) const
1093     {
1094         return new CBDB_FieldUChar();
1095     }
1096 
Get() const1097     unsigned char Get() const
1098     {
1099         _ASSERT(!IsNull());
1100 
1101         return *(const unsigned char*)GetBuffer();
1102     }
1103 
operator char() const1104     operator char () const
1105     {
1106         return Get();
1107     }
1108 
GetString() const1109     virtual string GetString() const
1110     {
1111         return string(1, Get());
1112     }
1113 
ToString(string & s) const1114     virtual void ToString(string& s) const
1115     {
1116         s.assign(1, Get());
1117     }
1118 
GetCompareFunction(bool) const1119     virtual BDB_CompareFunction GetCompareFunction(bool) const
1120     {
1121         return BDB_UCharCompare;
1122     }
1123 
Compare(const void * p1,const void * p2,bool) const1124     virtual int Compare(const void * p1,
1125                         const void * p2,
1126                         bool) const
1127     {
1128         const unsigned char& c1 = *(const unsigned char *)p1;
1129         const unsigned char& c2 = *(const unsigned char *)p2;
1130 
1131         return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
1132     }
1133 };
1134 
1135 class CBDB_FieldChar : public CBDB_FieldSimpleInt<char>
1136 {
1137 public:
operator =(char val)1138     CBDB_FieldChar& operator = (char val)
1139     {
1140         Set(val);
1141         return *this;
1142     }
1143 
operator =(const CBDB_FieldChar & val)1144     CBDB_FieldChar& operator = (const CBDB_FieldChar& val)
1145     {
1146         Set(val);
1147         return *this;
1148     }
1149 
Construct(size_t) const1150     virtual CBDB_Field * Construct(size_t) const
1151     {
1152         return new CBDB_FieldChar();
1153     }
1154 
Get() const1155     char Get() const
1156     {
1157         _ASSERT(!IsNull());
1158 
1159         return *(const char*)GetBuffer();
1160     }
1161 
operator char() const1162     operator char () const
1163     {
1164         return Get();
1165     }
1166 
GetString() const1167     virtual string GetString() const
1168     {
1169         return string(1, Get());
1170     }
1171 
ToString(string & s) const1172     virtual void ToString(string& s) const
1173     {
1174         s.assign(1, Get());
1175     }
1176 
GetCompareFunction(bool) const1177     virtual BDB_CompareFunction GetCompareFunction(bool) const
1178     {
1179         return BDB_CharCompare;
1180     }
1181 
Compare(const void * p1,const void * p2,bool) const1182     virtual int Compare(const void * p1,
1183                         const void * p2,
1184                         bool) const
1185     {
1186         const char& c1 = *(const char *)p1;
1187         const char& c2 = *(const char *)p2;
1188 
1189         return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
1190     }
1191 };
1192 
1193 /// Int1 field type
1194 ///
1195 
1196 class CBDB_FieldInt1 : public CBDB_FieldChar
1197 {
1198 public:
operator =(Int1 val)1199     CBDB_FieldInt1& operator=(Int1 val)
1200     {
1201         Set(val);
1202         return *this;
1203     }
1204 
operator =(const CBDB_FieldChar & val)1205     CBDB_FieldInt1& operator=(const CBDB_FieldChar& val)
1206     {
1207         Set(val);
1208         return *this;
1209     }
1210 
Construct(size_t) const1211     virtual CBDB_Field * Construct(size_t) const
1212     {
1213         return new CBDB_FieldInt1();
1214     }
1215 
GetString() const1216     virtual string GetString() const
1217     {
1218         return NStr::UIntToString(Get());
1219     }
1220 
ToString(string & s) const1221     virtual void ToString(string& s) const
1222     {
1223         s = GetString();
1224     }
1225 };
1226 
1227 
1228 /// Uint1 field type
1229 ///
1230 
1231 class CBDB_FieldUint1 : public CBDB_FieldUChar
1232 {
1233 public:
operator =(unsigned char val)1234     CBDB_FieldUint1& operator= (unsigned char val)
1235     {
1236         Set(val);
1237         return *this;
1238     }
1239 
operator =(const CBDB_FieldUChar & val)1240     CBDB_FieldUint1& operator= (const CBDB_FieldUChar& val)
1241     {
1242         Set(val);
1243         return *this;
1244     }
1245 
Construct(size_t) const1246     virtual CBDB_Field * Construct(size_t) const
1247     {
1248         return new CBDB_FieldUint1();
1249     }
1250 
GetString() const1251     virtual string GetString() const
1252     {
1253         return NStr::UIntToString(Get());
1254     }
1255 
ToString(string & s) const1256     virtual void ToString(string& s) const
1257     {
1258         s = GetString();
1259     }
1260 };
1261 
1262 
1263 ///  Uint4 field type
1264 ///
1265 
1266 class NCBI_BDB_EXPORT CBDB_FieldUint4 : public CBDB_FieldSimpleInt<Uint4>
1267 {
1268 public:
operator =(Uint4 val)1269     CBDB_FieldUint4& operator= (Uint4 val)
1270     {
1271         Set(val);
1272         return *this;
1273     }
1274 
operator =(const CBDB_FieldUint4 & val)1275     CBDB_FieldUint4& operator= (const CBDB_FieldUint4& val)
1276     {
1277         Set(val);
1278         return *this;
1279     }
1280 
Construct(size_t) const1281     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
1282     {
1283         return new CBDB_FieldUint4();
1284     }
1285 
Get() const1286     Uint4 Get() const
1287     {
1288         Uint4  v;
1289 
1290         _ASSERT(!IsNull());
1291 
1292         if (IsByteSwapped()) {
1293             v = (Uint4)CByteSwap::GetInt4((unsigned char*)GetBuffer());
1294         } else {
1295 #ifdef HAVE_UNALIGNED_READS
1296             TFieldType* b = (TFieldType*) GetBuffer();
1297             v = *b;
1298 #else
1299             ::memcpy(&v, GetBuffer(), sizeof(Uint4));
1300 #endif
1301         }
1302         return v;
1303     }
1304 
GetString() const1305     virtual string GetString() const
1306     {
1307         Uint4  v = Get();
1308         return NStr::UIntToString(v);
1309     }
1310 
ToString(string & str) const1311     virtual void ToString(string& str) const
1312     {
1313         Uint4 v = Get();
1314         NStr::UIntToString(str, v);
1315     }
1316 
operator Uint4() const1317     operator Uint4() const
1318     {
1319         return Get();
1320     }
1321 
GetCompareFunction(bool byte_swapped) const1322     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
1323     {
1324         if (byte_swapped)
1325             return BDB_ByteSwap_Uint4Compare;
1326         return BDB_Uint4Compare;
1327     }
1328 
Compare(const void * p1,const void * p2,bool byte_swapped) const1329     virtual int Compare(const void* p1,
1330                         const void* p2,
1331                         bool byte_swapped) const
1332     {
1333         if (!byte_swapped)
1334             return CBDB_FieldSimpleInt<Uint4>::Compare(p1, p2, byte_swapped);
1335 
1336         Uint4 v1, v2;
1337         v1 = (Uint4)CByteSwap::GetInt4((unsigned char*)p1);
1338         v2 = (Uint4)CByteSwap::GetInt4((unsigned char*)p2);
1339         if (v1 < v2) return -1;
1340         if (v2 < v1) return 1;
1341         return 0;
1342     }
1343 
1344 };
1345 
1346 
1347 
1348 ///  Float field type
1349 ///
1350 
1351 class NCBI_BDB_EXPORT CBDB_FieldFloat : public CBDB_FieldSimpleFloat<float>
1352 {
1353 public:
operator =(float val)1354     CBDB_FieldFloat& operator= (float val)
1355     {
1356         Set(val);
1357         return *this;
1358     }
1359 
operator =(const CBDB_FieldFloat & val)1360     CBDB_FieldFloat& operator= (const CBDB_FieldFloat& val)
1361     {
1362         Set(val);
1363         return *this;
1364     }
1365 
Construct(size_t) const1366     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
1367     {
1368         return new CBDB_FieldFloat();
1369     }
1370 
Get() const1371     float Get() const
1372     {
1373         float  v;
1374 
1375         _ASSERT(!IsNull());
1376 
1377         if (IsByteSwapped()) {
1378             v = CByteSwap::GetFloat((unsigned char*)GetBuffer());
1379         } else {
1380 #ifdef HAVE_UNALIGNED_READS
1381             TFieldType* b = (TFieldType*) this->GetBuffer();
1382             v = *b;
1383 #else
1384             ::memcpy(&v, GetBuffer(), sizeof(float));
1385 #endif
1386         }
1387         return v;
1388     }
1389 
GetString() const1390     virtual string GetString() const
1391     {
1392         double v = Get();
1393         return NStr::DoubleToString(v);
1394     }
1395 
ToString(string & str) const1396     virtual void ToString(string& str) const
1397     {
1398         double v = Get();
1399         NStr::DoubleToString(str, v);
1400     }
1401 
operator float() const1402     operator float() const
1403     {
1404         return Get();
1405     }
1406 
GetCompareFunction(bool byte_swapped) const1407     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
1408     {
1409         if (byte_swapped)
1410             return BDB_ByteSwap_FloatCompare;
1411 
1412         return BDB_FloatCompare;
1413     }
1414 
Compare(const void * p1,const void * p2,bool byte_swapped) const1415     virtual int Compare(const void* p1,
1416                         const void* p2,
1417                         bool byte_swapped) const
1418     {
1419         if (!byte_swapped)
1420             return CBDB_FieldSimpleFloat<float>::Compare(p1, p2, byte_swapped);
1421 
1422         float v1, v2;
1423         v1 = CByteSwap::GetFloat((unsigned char*)p1);
1424         v2 = CByteSwap::GetFloat((unsigned char*)p2);
1425         if (v1 < v2) return -1;
1426         if (v2 < v1) return 1;
1427         return 0;
1428     }
1429 };
1430 
1431 
1432 ///  Double precision floating point field type
1433 ///
1434 
1435 class NCBI_BDB_EXPORT CBDB_FieldDouble : public CBDB_FieldSimpleFloat<double>
1436 {
1437 public:
operator =(double val)1438     CBDB_FieldDouble& operator= (double val)
1439     {
1440         Set(val);
1441         return *this;
1442     }
1443 
operator =(const CBDB_FieldDouble & val)1444     CBDB_FieldDouble& operator= (const CBDB_FieldDouble& val)
1445     {
1446         Set(val);
1447         return *this;
1448     }
1449 
Construct(size_t) const1450     virtual CBDB_Field* Construct(size_t /*buf_size*/) const
1451     {
1452         return new CBDB_FieldDouble();
1453     }
1454 
Get() const1455     double Get() const
1456     {
1457         double  v;
1458 
1459         _ASSERT(!IsNull());
1460 
1461         if (IsByteSwapped()) {
1462             v = CByteSwap::GetDouble((unsigned char*)GetBuffer());
1463         } else {
1464 #ifdef HAVE_UNALIGNED_READS
1465             TFieldType* b = (TFieldType*) GetBuffer();
1466             v = *b;
1467 #else
1468             ::memcpy(&v, GetBuffer(), sizeof(double));
1469 #endif
1470         }
1471         return v;
1472     }
1473 
GetString() const1474     virtual string GetString() const
1475     {
1476         double v = Get();
1477         return NStr::DoubleToString(v);
1478     }
1479 
ToString(string & str) const1480     virtual void ToString(string& str) const
1481     {
1482         double v = Get();
1483         NStr::DoubleToString(str, v);
1484     }
1485 
operator double() const1486     operator double() const
1487     {
1488         return Get();
1489     }
1490 
GetCompareFunction(bool byte_swapped) const1491     virtual BDB_CompareFunction GetCompareFunction(bool byte_swapped) const
1492     {
1493         if (byte_swapped)
1494             return BDB_ByteSwap_DoubleCompare;
1495 
1496         return BDB_DoubleCompare;
1497     }
1498 
Compare(const void * p1,const void * p2,bool byte_swapped) const1499     virtual int Compare(const void* p1,
1500                         const void* p2,
1501                         bool byte_swapped) const
1502     {
1503         if (!byte_swapped)
1504             return CBDB_FieldSimpleFloat<double>::Compare(p1, p2, byte_swapped);
1505 
1506         double v1, v2;
1507         v1 = CByteSwap::GetDouble((unsigned char*)p1);
1508         v2 = CByteSwap::GetDouble((unsigned char*)p2);
1509         if (v1 < v2) return -1;
1510         if (v2 < v1) return 1;
1511         return 0;
1512     }
1513 
1514 };
1515 
1516 /// Fixed length bytestring. (Can hold 0 chars).
1517 ///
1518 class NCBI_BDB_EXPORT CBDB_FieldFixedByteString : public CBDB_Field
1519 {
1520 public:
1521     CBDB_FieldFixedByteString();
1522 
Construct(size_t buf_size) const1523     virtual CBDB_Field* Construct(size_t buf_size) const
1524     {
1525         CBDB_FieldFixedByteString* fld = new CBDB_FieldFixedByteString();
1526         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
1527         return fld;
1528     }
1529     operator const char* () const;
1530     CBDB_FieldFixedByteString& operator=
1531                     (const CBDB_FieldFixedByteString& str);
1532 
1533     void Set(const char* str);
SetString(const char * val)1534     virtual void SetString (const char*  val) { Set(val); }
1535     string Get() const;
GetString() const1536     virtual string GetString() const { return Get(); }
1537 
IsEmpty() const1538     bool IsEmpty() const { return false; }
IsBlank() const1539     bool IsBlank() const { return false; }
1540 
1541 
1542     // IField
1543     virtual int         Compare(const void* p1,
1544                                 const void* p2,
1545                                 bool /* byte_swapped */) const;
1546     virtual size_t      GetDataLength(const void* buf) const;
1547     virtual void        SetMinVal();
1548     virtual void        SetMaxVal();
1549 
SetStdString(const string & str)1550     virtual void SetStdString(const string& str)
1551     {
1552         _ASSERT(str.length() == GetBufferSize());
1553         SetString(str.c_str());
1554     }
ToString(string & str) const1555     virtual void ToString(string& str) const
1556     {
1557         str.assign((const char*) GetBuffer(), GetBufferSize());
1558     }
1559 
GetCompareFunction(bool) const1560     virtual BDB_CompareFunction GetCompareFunction(bool) const
1561     {
1562         return BDB_FixedByteStringCompare;
1563     }
1564 
1565 };
1566 
1567 
1568 ///
1569 ///  String field type
1570 ///
1571 class NCBI_BDB_EXPORT CBDB_FieldStringBase : public CBDB_Field
1572 {
1573 public:
1574     enum EOverflowAction {
1575         eThrowOnOverflow,
1576         eTruncateOnOverflow,
1577         eTruncateOnOverflowLogError
1578     };
1579 
1580 protected:
CBDB_FieldStringBase()1581     CBDB_FieldStringBase() : CBDB_Field(eVariableLength) {}
1582 };
1583 
1584 
1585 ///
1586 ///  String field type designed to work with C-strings (ASCIIZ)
1587 ///
1588 
1589 class NCBI_BDB_EXPORT CBDB_FieldString : public CBDB_FieldStringBase
1590 {
1591 public:
1592     CBDB_FieldString();
1593 
1594     /// Class factory for string fields.
1595     /// Default (zero) value of 'buf_size' uses GetBufferSize().
Construct(size_t buf_size) const1596     virtual CBDB_Field* Construct(size_t buf_size) const
1597     {
1598         CBDB_FieldString* fld = new CBDB_FieldString();
1599         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
1600         return fld;
1601     }
1602 
1603     operator const char* () const;
1604     CBDB_FieldString& operator= (const CBDB_FieldString& str);
1605     CBDB_FieldString& operator= (const char*             str);
1606     CBDB_FieldString& operator= (const string&           str);
1607 
1608     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
Get() const1609     string Get() const { return string((const char*)GetBuffer()); }
1610 
GetString() const1611     virtual string GetString() const
1612     {
1613         return Get();
1614     }
1615 
1616     bool IsEmpty() const;
1617     bool IsBlank() const;
1618 
1619 
1620     // IField
1621     virtual int         Compare(const void* p1,
1622                                 const void* p2,
1623                                 bool /* byte_swapped */) const;
1624     virtual size_t      GetDataLength(const void* buf) const;
1625     virtual void        SetMinVal();
1626     virtual void        SetMaxVal();
1627 
1628     virtual void SetString(const char*);
SetStdString(const string & str)1629     virtual void SetStdString(const string& str)
1630     {
1631         SetString(str.c_str());
1632     }
ToString(string & str) const1633     virtual void ToString(string& str) const
1634     {
1635         str = (const char*) GetBuffer();
1636     }
1637 
GetCompareFunction(bool) const1638     virtual BDB_CompareFunction GetCompareFunction(bool) const
1639     {
1640         return BDB_StringCompare;
1641     }
1642 };
1643 
1644 
1645 
1646 ///  Case-insensitive (but case preserving) string field type
1647 ///
1648 
1649 class NCBI_BDB_EXPORT CBDB_FieldStringCase : public CBDB_FieldString
1650 {
1651 public:
1652     typedef CBDB_FieldString CParent;
1653 
CBDB_FieldStringCase()1654     explicit CBDB_FieldStringCase() : CBDB_FieldString() {}
1655 
Construct(size_t buf_size) const1656     virtual CBDB_Field* Construct(size_t buf_size) const
1657     {
1658         CBDB_FieldStringCase* fld = new CBDB_FieldStringCase();
1659         fld->SetBufferSize(buf_size ? buf_size : GetBufferSize());
1660         return fld;
1661     }
1662 
1663     // Accessors
operator const char*() const1664     operator const char* () const { return (const char*) GetBuffer(); }
1665 
operator =(const CBDB_FieldString & str)1666     CBDB_FieldStringCase& operator= (const CBDB_FieldString& str)
1667     {
1668         Set(str);
1669         return *this;
1670     }
operator =(const CBDB_FieldStringCase & str)1671     CBDB_FieldStringCase& operator= (const CBDB_FieldStringCase& str)
1672     {
1673         Set(str);
1674         return *this;
1675     }
operator =(const char * str)1676     CBDB_FieldStringCase& operator= (const char* str)
1677     {
1678         Set(str);
1679         return *this;
1680     }
operator =(const string & str)1681     CBDB_FieldStringCase& operator= (const string& str)
1682     {
1683         Set(str.c_str());
1684         return *this;
1685     }
1686 
Compare(const void * p1,const void * p2,bool) const1687     virtual int Compare(const void* p1,
1688                         const void* p2,
1689                         bool/* byte_swapped */) const
1690     {
1691         _ASSERT(p1 && p2);
1692         return NStr::CompareNocase((const char*) p1, (const char*) p2);
1693     }
1694 
1695     virtual
GetCompareFunction(bool) const1696     BDB_CompareFunction GetCompareFunction(bool /* byte_swapped */) const
1697     {
1698         return BDB_StringCaseCompare;
1699     }
1700 
1701 };
1702 
1703 
1704 ///
1705 ///  Length prefised string field type
1706 ///
1707 
1708 class NCBI_BDB_EXPORT CBDB_FieldLString : public CBDB_FieldStringBase
1709 {
1710 public:
1711     CBDB_FieldLString();
1712 
1713     // Class factory for string fields.
1714     // Default (zero) value of 'buf_size' uses GetBufferSize().
1715     virtual CBDB_Field* Construct(size_t buf_size) const;
1716 
operator string() const1717     operator string() const { return GetString(); }
1718     CBDB_FieldLString& operator= (const CBDB_FieldLString& str);
1719     CBDB_FieldLString& operator= (const char*             str);
1720     CBDB_FieldLString& operator= (const string&           str);
1721 
1722     void Set(const char* str, EOverflowAction if_overflow = eThrowOnOverflow);
1723     void Set(const char* str, size_t size,
1724              EOverflowAction if_overflow = eThrowOnOverflow);
1725     string Get() const;
1726 
GetString() const1727     virtual string GetString() const
1728     {
1729         return Get();
1730     }
1731 
1732     bool IsEmpty() const;
1733     bool IsBlank() const;
1734 
1735 
1736     // IField
1737     virtual int         Compare(const void* p1,
1738                                 const void* p2,
1739                                 bool /* byte_swapped */) const;
1740     virtual size_t      GetDataLength(const void* buf) const;
1741     virtual void        SetMinVal();
1742     virtual void        SetMaxVal();
1743 
1744     virtual void SetString(const char*);
1745     virtual void SetStdString(const string& str);
1746 
GetCompareFunction(bool) const1747     virtual BDB_CompareFunction GetCompareFunction(bool) const
1748     {
1749         return BDB_LStringCompare;
1750     }
1751     virtual void ToString(string& str) const;
1752 protected:
1753     const unsigned char* GetLString(const unsigned char* str,
1754                                     bool                 check_legacy,
1755                                     int*                 str_len) const;
1756     virtual size_t GetExtraDataLength();
1757 };
1758 
1759 
1760 
1761 
1762 /// BDB Data Field Buffer manager class.
1763 /// For internal use in BDB library.
1764 ///
1765 /// @internal
1766 
1767 class NCBI_BDB_EXPORT CBDB_BufferManager
1768 {
1769 public:
1770     /// Return number of fields attached using function Bind
1771     unsigned int FieldCount() const;
1772 
1773     const CBDB_Field& GetField(unsigned int idx) const;
1774     CBDB_Field&       GetField(unsigned int idx);
1775 
1776     /// Find the field with the specified name. Name is case insensitive.
1777     /// @return -1 if field cannot be found
1778     int GetFieldIndex(const string& name) const;
1779 
1780     /// Return TRUE if buffer is in a non-native byte order
IsByteSwapped() const1781     bool IsByteSwapped() const { return m_ByteSwapped; }
1782 
1783     /// Sets maximum number of fields participating in comparison
1784     /// Should be less than total number of fields in the buffer
1785     void SetFieldCompareLimit(unsigned int n_fields);
1786 
1787     /// Get number of fields in comparison.
1788     /// 0 - means no forced limit
1789     unsigned int GetFieldCompareLimit() const;
1790 
1791     /// Return TRUE if buffer l-strings should check about legacy
1792     /// c-str compatibility
IsLegacyStrings() const1793     bool IsLegacyStrings() const { return m_LegacyString; }
1794 
1795     /// Get DBT.size of the parent file (key or data area)
1796     /// (Set by CBDB_File after read)
GetDBT_Size() const1797     size_t GetDBT_Size() const { return m_DBT_Size; }
1798 
1799     ~CBDB_BufferManager();
1800 
1801     /// Check if any field is NULL
1802     bool HasNull() const;
1803 
1804     /// Copy all fields from another manager with the same(a must!) structure
1805     void CopyFrom(const CBDB_BufferManager& bman);
1806 
1807     /// Copy packed data (buffer) from an external source
1808     void CopyPackedFrom(void* data, size_t data_size);
1809 
1810 protected:
1811     CBDB_BufferManager();
1812 
1813     /// Create internal data buffer, assign places in this buffer to the fields
1814     void Construct();
1815 
1816     /// Set minimum possible value to buffer fields from 'idx_from' to 'idx_to'
1817     void SetMinVal(unsigned int idx_from, unsigned int idx_to);
1818 
1819     /// Set maximum possible value to buffer fields from 'idx_from' to 'idx_to'
1820     void SetMaxVal(unsigned int idx_from, unsigned int idx_to);
1821 
1822     /// Attach 'field' to the buffer.
1823     /// NOTE: buffer manager will not own the attached object, nor will it
1824     ///       keep ref counters or do any other automagic memory management,
1825     ///       unless field ownership is set to TRUE
1826     void Bind(CBDB_Field* field, ENullable is_nullable = eNotNullable);
1827 
1828     /// Copy all field values from the 'buf_mgr'.
1829     void CopyFieldsFrom(const CBDB_BufferManager& buf_mgr);
1830 
1831     /// Duplicate (dynamic allocation is used) all fields from 'buf_mgr' and
1832     /// bind them to the this buffer manager. Field values are not copied.
1833     /// NOTE: CBDB_BufferManager does not own or deallocate fields,
1834     ///       caller is responsible for deallocation,
1835     ///       unless field ownership is set to TRUE
1836     void DuplicateStructureFrom(const CBDB_BufferManager& buf_mgr);
1837 
1838     /// Compare fields of this buffer with those of 'buf_mgr' using
1839     /// CBDB_Field::CompareWith().
1840     /// Optional 'n_fields' parameter used when we want to compare only
1841     /// several first fields instead of all.
1842     int Compare(const CBDB_BufferManager& buf_mgr,
1843                 unsigned int              n_fields = 0) const;
1844 
1845     /// Return TRUE if any field bound to this buffer manager has variable
1846     /// length (i.e. packable)
1847     bool IsPackable() const;
1848 
1849     /// Check if all NOT NULLABLE fields were assigned.
1850     /// Throw an exception if not.
1851     void CheckNullConstraint() const;
1852 
1853     void ArrangePtrsUnpacked();
1854     void ArrangePtrsPacked();
1855     void Clear();
1856     unsigned Pack();
1857     unsigned Unpack();
1858 
1859     /// Pack the buffer and initialize DBT structure for write operation
1860     void PrepareDBT_ForWrite(DBT* dbt);
1861 
1862     /// Initialize DBT structure for read operation.
1863     void PrepareDBT_ForRead(DBT* dbt);
1864 
1865     /// Calculate buffer size
1866     size_t ComputeBufferSize() const;
1867 
1868     /// Return TRUE if buffer can carry NULL fields
1869     bool IsNullable() const;
1870 
1871     /// Set byte swapping flag for the buffer
SetByteSwapped(bool byte_swapped)1872     void SetByteSwapped(bool byte_swapped) { m_ByteSwapped = byte_swapped; }
1873 
1874     /// Mark buffer as "NULL fields ready".
1875     /// NOTE: Should be called before buffer construction.
1876     void SetNullable();
1877 
1878     void SetNull(unsigned int field_idx, bool value);
1879     bool IsNull (unsigned int field_idx) const;
1880 
1881     size_t ComputeNullSetSize() const;
1882     bool   TestNullBit(unsigned int idx) const;
1883     void   SetNullBit (unsigned int idx, bool value);
1884     void   SetAllNull();
1885 
1886     /// Return buffer compare function
1887     BDB_CompareFunction GetCompareFunction() const;
1888 
1889     /// Return buffer hash function
1890     BDB_HashFunction GetHashFunction() const;
1891 
1892     /// Set C-str detection
SetLegacyStringsCheck(bool value)1893     void SetLegacyStringsCheck(bool value) { m_LegacyString = value; }
1894 
SetDBT_Size(size_t size)1895     void SetDBT_Size(size_t size) { m_DBT_Size = size; }
1896 
1897     /// Fields deletion is managed by the class when own_fields is TRUE
SetFieldOwnership(bool own_fields)1898     void SetFieldOwnership(bool own_fields) { m_OwnFields = own_fields; }
1899 
1900     /// Return fields ownership flag
IsOwnFields() const1901     bool IsOwnFields() const { return m_OwnFields; }
1902 
1903     /// Disable-enable packing
SetPackable(bool packable)1904     void SetPackable(bool packable) { m_Packable = packable; }
1905 
1906 private:
1907     void x_ComputePackOpt();
1908 private:
1909     CBDB_BufferManager(const CBDB_BufferManager&);
1910     CBDB_BufferManager& operator= (const CBDB_BufferManager&);
1911 
1912 private:
1913     typedef vector<CBDB_Field*>  TFieldVector;
1914 
1915 private:
1916     TFieldVector            m_Fields;
1917     /// Array of pointers to the fields' data
1918     vector<void*>           m_Ptrs;
1919     char*                   m_Buffer;
1920     size_t                  m_BufferSize;
1921     size_t                  m_PackedSize;
1922     size_t                  m_DBT_Size;
1923     bool                    m_Packable;
1924     /// TRUE if buffer is in a non-native arch.
1925     bool                    m_ByteSwapped;
1926 
1927     /// TRUE if buffer can carry NULL fields
1928     bool                    m_Nullable;
1929     /// size of the 'is NULL' bitset in bytes
1930     size_t                  m_NullSetSize;
1931 
1932     /// Number of fields in key comparison
1933     unsigned int            m_CompareLimit;
1934 
1935     /// Flag to check for legacy string compatibility
1936     bool                    m_LegacyString;
1937 
1938     /// Field ownership flag
1939     bool                    m_OwnFields;
1940 
1941 
1942     // pack optimization fields
1943 
1944     /// Pack optimization flag (turns TRUE on first Pack call)
1945     bool                    m_PackOptComputed;
1946     /// Index of first variable length field
1947     unsigned int            m_FirstVarFieldIdx;
1948     /// Buffer offset of first variable length field
1949     unsigned int            m_FirstVarFieldIdxOffs;
1950 
1951 private:
1952     friend class CBDB_Field;
1953     friend class CBDB_BLobFile;
1954     friend class CBDB_File;
1955     friend class CBDB_FileCursor;
1956     friend class CBDB_FC_Condition;
1957 };
1958 
1959 /// Class factory for BDB field types
1960 class NCBI_BDB_EXPORT CBDB_FieldFactory
1961 {
1962 public:
1963     enum EType
1964     {
1965         eUnknown,
1966 
1967         eString,
1968         eLString,
1969         eInt8,
1970         eInt4,
1971         eUint4,
1972         eInt2,
1973         eUint1,
1974         eFloat,
1975         eDouble,
1976         eUChar,
1977         eBlob
1978     };
1979 
1980 public:
1981     CBDB_FieldFactory();
1982 
1983     /// Return type enumerator by string type (case insensitive)
1984     EType GetType(const string& type) const;
1985 
1986 
1987     CBDB_Field* Create(EType type) const;
1988 
1989     /// Create field type by string. Caller is responsible for deletion.
1990     ///
1991     /// @param type
1992     ///    string type ("string", "int4", "double"). Case insensitive.
1993 
1994     CBDB_Field* Create(const string& type) const;
1995 };
1996 
1997 
1998 /////////////////////////////////////////////////////////////////////////////
1999 ///
2000 /// Type trait classes for finding the correct BDB field type automagically
2001 ///
2002 
2003 ///
2004 /// SBDB_TypeTraits defines via template parameters a policy for mapping a
2005 /// built-in type to a BDB field type.
2006 ///
2007 template <class Type>
2008 struct SBDB_TypeTraits
2009 {
2010     typedef Type TType;
2011     typedef void* TFieldType;
2012 };
2013 
2014 
2015 ///
2016 /// 8-bit signed and unsigned integral types
2017 ///
2018 template<>
2019 struct SBDB_TypeTraits<Int1>
2020 {
2021     typedef Int4 TType;
2022     typedef CBDB_FieldInt1 TFieldType;
2023 };
2024 
2025 template<>
2026 struct SBDB_TypeTraits<Uint1>
2027 {
2028     typedef Uint4 TType;
2029     typedef CBDB_FieldUint1 TFieldType;
2030 };
2031 
2032 
2033 ///
2034 /// 16-bit signed and unsigned integral types
2035 ///
2036 template<>
2037 struct SBDB_TypeTraits<Int2>
2038 {
2039     typedef Int4 TType;
2040     typedef CBDB_FieldInt2 TFieldType;
2041 };
2042 
2043 template<>
2044 struct SBDB_TypeTraits<Uint2>
2045 {
2046     typedef Uint4 TType;
2047     typedef CBDB_FieldUint2 TFieldType;
2048 };
2049 
2050 
2051 ///
2052 /// 32-bit signed and unsigned integral types
2053 ///
2054 template<>
2055 struct SBDB_TypeTraits<Int4>
2056 {
2057     typedef Int4 TType;
2058     typedef CBDB_FieldInt4 TFieldType;
2059 };
2060 
2061 template<>
2062 struct SBDB_TypeTraits<Uint4>
2063 {
2064     typedef Uint4 TType;
2065     typedef CBDB_FieldUint4 TFieldType;
2066 };
2067 
2068 
2069 ///
2070 /// 64-bit signed and unsigned integral types
2071 ///
2072 template<>
2073 struct SBDB_TypeTraits<Int8>
2074 {
2075     typedef Int8 TType;
2076     typedef CBDB_FieldInt8 TFieldType;
2077 };
2078 
2079 template<>
2080 struct SBDB_TypeTraits<Uint8>
2081 {
2082     typedef Uint8 TType;
2083     typedef CBDB_FieldUint8 TFieldType;
2084 };
2085 
2086 
2087 ///
2088 /// string types
2089 ///
2090 template<>
2091 struct SBDB_TypeTraits<string>
2092 {
2093     typedef string TType;
2094     typedef CBDB_FieldString TFieldType;
2095 };
2096 
2097 
2098 ///
2099 /// 32- and 64- bit floating point types
2100 ///
2101 template<>
2102 struct SBDB_TypeTraits<float>
2103 {
2104     typedef float TType;
2105     typedef CBDB_FieldFloat TFieldType;
2106 };
2107 
2108 template<>
2109 struct SBDB_TypeTraits<double>
2110 {
2111     typedef double TType;
2112     typedef CBDB_FieldDouble TFieldType;
2113 };
2114 
2115 
2116 /* @} */
2117 
2118 /////////////////////////////////////////////////////////////////////////////
2119 //  IMPLEMENTATION of INLINE functions
2120 /////////////////////////////////////////////////////////////////////////////
2121 
2122 
2123 /////////////////////////////////////////////////////////////////////////////
2124 //  CBDB_Field::
2125 //
2126 
2127 
IsVariableLength() const2128 inline bool CBDB_Field::IsVariableLength() const
2129 {
2130     return m_Flags.VariableLength == 1;
2131 }
2132 
2133 
GetBufferSize() const2134 inline size_t CBDB_Field::GetBufferSize() const
2135 {
2136     return m_BufferSize;
2137 }
2138 
2139 
IsBufferAttached() const2140 inline bool CBDB_Field::IsBufferAttached() const
2141 {
2142     return m_Flags.Attached == 1;
2143 }
2144 
2145 
IsNullable() const2146 inline bool CBDB_Field::IsNullable() const
2147 {
2148     return m_Flags.Nullable == 1;
2149 }
2150 
2151 
SetNullable()2152 inline void CBDB_Field::SetNullable()
2153 {
2154     m_Flags.Nullable = 1;
2155 }
2156 
2157 
SetNotNull()2158 inline void CBDB_Field::SetNotNull()
2159 {
2160     m_BufferManager->SetNull(m_BufferIdx, false);
2161 }
2162 
2163 
SetNull()2164 inline void CBDB_Field::SetNull()
2165 {
2166     _ASSERT(m_BufferManager->IsNullable());
2167     m_BufferManager->SetNull(m_BufferIdx, true);
2168 }
2169 
2170 
IsNull() const2171 inline bool CBDB_Field::IsNull() const
2172 {
2173     return m_BufferManager->IsNull(m_BufferIdx);
2174 }
2175 
2176 
Unpack()2177 inline void* CBDB_Field::Unpack()
2178 {
2179     _ASSERT(m_BufferManager);
2180     m_BufferManager->Unpack();
2181     return GetBuffer();
2182 }
2183 
2184 
SetBuffer(void * buf,size_t buf_size)2185 inline void CBDB_Field::SetBuffer(void* buf, size_t buf_size)
2186 {
2187     m_Buffer = buf;
2188     if ( buf_size )
2189         m_BufferSize = buf_size;
2190     m_Flags.Attached = 1;
2191 }
2192 
2193 
SetBufferSize(size_t buf_size)2194 inline void CBDB_Field::SetBufferSize(size_t buf_size)
2195 {
2196     _ASSERT(buf_size != 0);
2197     m_BufferSize = buf_size;
2198 }
2199 
2200 
SetDataSize(size_t size)2201 inline void CBDB_Field::SetDataSize(size_t size)
2202 {
2203     m_BufferSize = size + GetExtraDataLength();
2204 }
2205 
2206 
SetBufferIdx(unsigned int idx)2207 inline void CBDB_Field::SetBufferIdx(unsigned int idx)
2208 {
2209     m_BufferIdx = idx;
2210 }
2211 
2212 
GetBuffer() const2213 inline const void* CBDB_Field::GetBuffer() const
2214 {
2215     return m_Buffer;
2216 }
2217 
2218 
GetBuffer()2219 inline void* CBDB_Field::GetBuffer()
2220 {
2221     return m_Buffer;
2222 }
2223 
2224 
SetBufferManager(CBDB_BufferManager * owner)2225 inline void CBDB_Field::SetBufferManager(CBDB_BufferManager* owner)
2226 {
2227     _ASSERT(owner);
2228     m_BufferManager = owner;
2229 }
2230 
2231 
GetLength() const2232 inline size_t CBDB_Field::GetLength() const
2233 {
2234     return GetDataLength(m_Buffer);
2235 }
2236 
2237 
CompareWith(const CBDB_Field & field) const2238 inline int CBDB_Field::CompareWith(const CBDB_Field& field) const
2239 {
2240     bool byte_swapped = m_BufferManager->IsByteSwapped();
2241     return Compare(GetBuffer(), field.GetBuffer(), byte_swapped);
2242 }
2243 
2244 
IsSameType(const CBDB_Field & field) const2245 inline bool CBDB_Field::IsSameType(const CBDB_Field& field) const
2246 {
2247     try {
2248         const type_info& t1 = typeid(*this);
2249         const type_info& t2 = typeid(field);
2250         return (t1 == t2) != 0;
2251     } catch (...) {
2252     }
2253     return false;
2254 }
2255 
2256 
2257 
CopyFrom(const CBDB_Field & src)2258 inline void CBDB_Field::CopyFrom(const CBDB_Field& src)
2259 {
2260     if (this == &src)
2261         return;
2262 
2263     if ( !IsSameType(src) ) {
2264         BDB_THROW(eType, "Wrong field type");
2265     }
2266 
2267     CopyFrom(src.GetBuffer());
2268 }
2269 
2270 
CopyFrom(const void * src_buf)2271 inline void CBDB_Field::CopyFrom(const void* src_buf)
2272 {
2273     _ASSERT(src_buf);
2274 
2275     void* dst_ptr = Unpack();
2276     _ASSERT(dst_ptr);
2277 
2278     size_t max_len  = GetBufferSize();
2279     size_t copy_len = GetDataLength(src_buf);
2280 
2281     if (copy_len > max_len) {
2282         BDB_THROW(eOverflow, "Cannot copy. Data length exceeds max value");
2283     }
2284     ::memcpy(dst_ptr, src_buf, copy_len);
2285     SetNotNull();
2286 }
2287 
2288 
GetName() const2289 inline const string& CBDB_Field::GetName() const
2290 {
2291     return m_Name;
2292 }
2293 
2294 
SetName(const char * name)2295 inline void CBDB_Field::SetName(const char* name)
2296 {
2297     _ASSERT(name);
2298     m_Name = name;
2299 }
2300 
IsByteSwapped() const2301 inline bool CBDB_Field::IsByteSwapped() const
2302 {
2303     return m_BufferManager->IsByteSwapped();
2304 }
2305 
2306 /////////////////////////////////////////////////////////////////////////////
2307 //  CBDB_FieldString::
2308 //
2309 
operator const char*() const2310 inline CBDB_FieldFixedByteString::operator const char* () const
2311 {
2312     const char* str = (const char*) GetBuffer();
2313     _ASSERT(str);
2314     return str;
2315 }
2316 
2317 
2318 inline
Set(const char * str)2319 void CBDB_FieldFixedByteString::Set(const char* str)
2320 {
2321     ::memcpy((char*)GetBuffer(), str, GetBufferSize());
2322 }
2323 
2324 inline
Get() const2325 string CBDB_FieldFixedByteString::Get() const
2326 {
2327     _ASSERT(!IsNull());
2328 
2329     const char* buf = (const char*) GetBuffer();
2330     return string(buf, GetBufferSize());
2331 }
2332 
2333 inline
Compare(const void * p1,const void * p2,bool) const2334 int CBDB_FieldFixedByteString::Compare(const void* p1,
2335                                        const void* p2,
2336                                        bool /*byte_swapped*/) const
2337 {
2338     return ::memcmp(p1, p2, GetBufferSize());
2339 }
2340 
2341 inline
GetDataLength(const void *) const2342 size_t CBDB_FieldFixedByteString::GetDataLength(const void* /*buf*/) const
2343 {
2344     return GetBufferSize();
2345 }
2346 
2347 inline
SetMinVal()2348 void CBDB_FieldFixedByteString::SetMinVal()
2349 {
2350     void* buf = Unpack();
2351     ::memset(buf, 0, GetBufferSize());
2352 }
2353 
2354 inline
SetMaxVal()2355 void CBDB_FieldFixedByteString::SetMaxVal()
2356 {
2357     void* buf = Unpack();
2358     ::memset(buf, 0xFF, GetBufferSize());
2359 }
2360 
2361 /////////////////////////////////////////////////////////////////////////////
2362 //  CBDB_FieldString::
2363 //
2364 
CBDB_FieldString()2365 inline CBDB_FieldString::CBDB_FieldString()
2366     : CBDB_FieldStringBase()
2367 {
2368     SetBufferSize(256);
2369 }
2370 
2371 
operator const char*() const2372 inline CBDB_FieldString::operator const char* () const
2373 {
2374     const char* str = (const char*) GetBuffer();
2375     _ASSERT(str);
2376     return str;
2377 }
2378 
2379 
2380 inline
2381 CBDB_FieldString&
operator =(const CBDB_FieldString & str)2382 CBDB_FieldString::operator= (const CBDB_FieldString& str)
2383 {
2384     if (this == &str)
2385         return *this;
2386 
2387     size_t len = str.GetLength();
2388     if (len > GetBufferSize()) {
2389         // TODO: allow partial string assignment?
2390         BDB_THROW(eOverflow, "String field overflow.");
2391     }
2392     Unpack();
2393     ::strcpy((char*)GetBuffer(), (const char*) str);
2394 
2395     if ( str.IsNull() ) {
2396         SetNull();
2397     } else {
2398         SetNotNull();
2399     }
2400 
2401     return *this;
2402 }
2403 
2404 
2405 inline
Set(const char * str,EOverflowAction if_overflow)2406 void CBDB_FieldString::Set(const char* str, EOverflowAction if_overflow)
2407 {
2408     if ( !str )
2409         str = kEmptyCStr;
2410 
2411     size_t new_len = ::strlen(str) + 1;
2412 
2413     // check overflow
2414     if (new_len > GetBufferSize()) {
2415         switch (if_overflow) {
2416         case eTruncateOnOverflowLogError:
2417             ERR_POST(Warning << "Value truncated for field '"
2418                     << GetName() << "'");
2419             NCBI_FALLTHROUGH;
2420         case eTruncateOnOverflow:
2421             new_len = GetBufferSize();
2422             break;
2423         case eThrowOnOverflow:
2424             string msg("String field '");
2425             msg += GetName();
2426             msg += "' overflow: max size = ";
2427             msg += NStr::SizetToString(GetBufferSize());
2428             msg += ", assignee size = ";
2429             msg += NStr::SizetToString(new_len);
2430             BDB_THROW(eOverflow, msg);
2431             break;
2432         }
2433     }
2434     Unpack();
2435     ::memcpy(GetBuffer(), str, new_len);
2436     SetNotNull();
2437 }
2438 
2439 inline
SetString(const char * str)2440 void CBDB_FieldString::SetString(const char* str)
2441 {
2442     operator=(str);
2443 }
2444 
Compare(const void * p1,const void * p2,bool) const2445 inline int CBDB_FieldString::Compare(const void* p1,
2446                                      const void* p2,
2447                                      bool /*byte_swapped*/) const
2448 {
2449     _ASSERT(p1 && p2);
2450     return ::strcmp((const char*) p1, (const char*) p2);
2451 }
2452 
2453 
SetMinVal()2454 inline void CBDB_FieldString::SetMinVal()
2455 {
2456     ((char*) Unpack())[0] = '\0';
2457 }
2458 
2459 
SetMaxVal()2460 inline void CBDB_FieldString::SetMaxVal()
2461 {
2462     void* buf = Unpack();
2463     // TODO:  find out whether xFF or 0x7F should be used, and how
2464     //        (because of possible 'signed char' comparison in strcmp()).
2465     ::memset(buf, 0x7F, GetBufferSize()); // 0xFF for international
2466     ((char*) buf)[GetBufferSize() - 1] = '\0';
2467 
2468     SetNotNull();
2469 }
2470 
2471 
IsEmpty() const2472 inline bool CBDB_FieldString::IsEmpty() const
2473 {
2474     const char* str = (const char*) GetBuffer();
2475     _ASSERT(str);
2476     return !*str;
2477 }
2478 
2479 
IsBlank() const2480 inline bool CBDB_FieldString::IsBlank() const
2481 {
2482     const char* str = (const char*) GetBuffer();
2483     _ASSERT(str);
2484     for (;  *str;  ++str) {
2485         if ( !isspace((unsigned char)(*str)) )
2486             return false;
2487     }
2488     return true;
2489 }
2490 
2491 
GetDataLength(const void * buf) const2492 inline size_t CBDB_FieldString::GetDataLength(const void* buf) const
2493 {
2494     _ASSERT(buf);
2495     return ::strlen((const char*) buf) + 1;
2496 }
2497 
2498 
operator =(const char * str)2499 inline CBDB_FieldString& CBDB_FieldString::operator= (const char* str)
2500 {
2501     Set(str, eThrowOnOverflow);
2502     return *this;
2503 }
2504 
operator =(const string & str)2505 inline CBDB_FieldString& CBDB_FieldString::operator= (const string& str)
2506 {
2507     return this->operator=(str.c_str());
2508 }
2509 
2510 
2511 
2512 /////////////////////////////////////////////////////////////////////////////
2513 //  CBDB_BufferManager::
2514 //
2515 
2516 
GetField(unsigned int n) const2517 inline const CBDB_Field& CBDB_BufferManager::GetField(unsigned int n) const
2518 {
2519     return *m_Fields[n];
2520 }
2521 
2522 
GetField(unsigned int n)2523 inline CBDB_Field& CBDB_BufferManager::GetField(unsigned int n)
2524 {
2525     return *m_Fields[n];
2526 }
2527 
2528 
FieldCount() const2529 inline unsigned int CBDB_BufferManager::FieldCount() const
2530 {
2531     return (unsigned int)m_Fields.size();
2532 }
2533 
2534 
IsPackable() const2535 inline bool CBDB_BufferManager::IsPackable() const
2536 {
2537     return m_Packable;
2538 }
2539 
2540 
IsNullable() const2541 inline bool CBDB_BufferManager::IsNullable() const
2542 {
2543     return m_Nullable;
2544 }
2545 
2546 
SetNullable()2547 inline void CBDB_BufferManager::SetNullable()
2548 {
2549     _ASSERT(m_Buffer == 0);
2550     m_Nullable = true;
2551 }
2552 
2553 
ComputeNullSetSize() const2554 inline size_t CBDB_BufferManager::ComputeNullSetSize() const
2555 {
2556     if ( !IsNullable() )
2557         return 0;
2558 
2559     return (FieldCount() + 7) / 8;
2560 }
2561 
2562 
TestNullBit(unsigned int n) const2563 inline bool CBDB_BufferManager::TestNullBit(unsigned int n) const
2564 {
2565     _ASSERT(IsNullable());
2566 
2567     const unsigned char* buf  = (unsigned char*) m_Buffer;
2568     unsigned char        mask = (unsigned char) (1 << (n & 7));
2569     const unsigned char* offs = buf + (n >> 3);
2570 
2571     return ((*offs) & mask) != 0;
2572 }
2573 
2574 
SetNullBit(unsigned int n,bool value)2575 inline void CBDB_BufferManager::SetNullBit(unsigned int n, bool value)
2576 {
2577     _ASSERT(IsNullable());
2578 
2579     unsigned char* buf  = (unsigned char*) m_Buffer;
2580     unsigned char  mask = (unsigned char) (1 << (n & 7));
2581     unsigned char* offs = buf + (n >> 3);
2582 
2583     (void) (value ? (*offs |= mask) : (*offs &= (unsigned char)~mask));
2584 }
2585 
2586 
SetNull(unsigned int field_idx,bool value)2587 inline void CBDB_BufferManager::SetNull(unsigned int field_idx, bool value)
2588 {
2589     if ( !IsNullable() )
2590         return;
2591     _ASSERT(field_idx < m_Fields.size());
2592     SetNullBit(field_idx, value);
2593 }
2594 
2595 
SetAllNull()2596 inline void CBDB_BufferManager::SetAllNull()
2597 {
2598     if ( !IsNullable() )
2599         return;
2600     unsigned char* buf = (unsigned char*) m_Buffer;
2601     for (size_t i = 0;  i < m_NullSetSize;  ++i) {
2602         *buf++ = (unsigned char) 0xFF;
2603     }
2604 }
2605 
2606 
HasNull() const2607 inline bool CBDB_BufferManager::HasNull() const
2608 {
2609     if (IsNullable()) {
2610         for (size_t i = 0;  i < m_NullSetSize;  ++i) {
2611             if (m_Buffer[i])
2612                 return true;
2613         }
2614     }
2615     return false;
2616 }
2617 
2618 
IsNull(unsigned field_idx) const2619 inline bool CBDB_BufferManager::IsNull(unsigned field_idx) const
2620 {
2621     if ( !IsNullable() )
2622         return false;
2623 
2624     _ASSERT(field_idx < m_Fields.size());
2625 
2626     return TestNullBit(field_idx);
2627 }
2628 
2629 
ArrangePtrsUnpacked()2630 inline void CBDB_BufferManager::ArrangePtrsUnpacked()
2631 {
2632     if ( !m_PackedSize )
2633         return;
2634 
2635     if ( !IsPackable() ) {
2636         m_PackedSize = 0;
2637         return;
2638     }
2639 
2640     for (size_t i = 0;  i < m_Fields.size();  ++i) {
2641         CBDB_Field& df = GetField((unsigned)i);
2642         df.SetBuffer(m_Ptrs[i]);
2643     }
2644 
2645     m_PackedSize = 0;  // not packed
2646 }
2647 
2648 
Clear()2649 inline void CBDB_BufferManager::Clear()
2650 {
2651     ::memset(m_Buffer, 0, m_BufferSize);
2652     ArrangePtrsUnpacked();
2653 }
2654 
2655 
2656 inline
CopyFieldsFrom(const CBDB_BufferManager & buf_mgr)2657 void CBDB_BufferManager::CopyFieldsFrom(const CBDB_BufferManager& buf_mgr)
2658 {
2659     unsigned int field_count = min(FieldCount(), buf_mgr.FieldCount());
2660 
2661     for (unsigned int i = 0;  i < field_count;  ++i) {
2662         CBDB_Field* fld = m_Fields[i];
2663         fld->CopyFrom(buf_mgr.GetField(i));
2664     }
2665 }
2666 
2667 
2668 inline
SetMinVal(unsigned int idx_from,unsigned int idx_to)2669 void CBDB_BufferManager::SetMinVal(unsigned int idx_from, unsigned int idx_to)
2670 {
2671     _ASSERT(idx_to <= FieldCount());
2672 
2673     for ( ;  idx_from < idx_to;  ++idx_from) {
2674         CBDB_Field& fld = GetField(idx_from);
2675         fld.SetMinVal();
2676     }
2677 }
2678 
2679 
2680 inline
SetMaxVal(unsigned int idx_from,unsigned int idx_to)2681 void CBDB_BufferManager::SetMaxVal(unsigned int idx_from, unsigned int idx_to)
2682 {
2683     _ASSERT(idx_to <= FieldCount());
2684 
2685     for ( ;  idx_from < idx_to;  ++idx_from) {
2686         CBDB_Field& fld = GetField(idx_from);
2687         fld.SetMaxVal();
2688     }
2689 }
2690 
2691 inline
SetFieldCompareLimit(unsigned int n_fields)2692 void CBDB_BufferManager::SetFieldCompareLimit(unsigned int n_fields)
2693 {
2694     m_CompareLimit = n_fields;
2695 }
2696 
2697 inline
GetFieldCompareLimit() const2698 unsigned int CBDB_BufferManager::GetFieldCompareLimit() const
2699 {
2700     return m_CompareLimit;
2701 }
2702 
2703 // Delete all field objects bound to field buffer.
2704 // Should be used with extreme caution. After calling this buf object should
2705 // never be used again. All fields bound to the buffer must be dynamically
2706 // allocated.
2707 inline
DeleteFields(CBDB_BufferManager & buf)2708 void DeleteFields(CBDB_BufferManager& buf)
2709 {
2710     for (unsigned int i = 0;  i < buf.FieldCount();  ++i) {
2711         CBDB_Field* fld = &buf.GetField(i);
2712         delete fld;
2713     }
2714 }
2715 
2716 
2717 END_NCBI_SCOPE
2718 
2719 
2720 
2721 #endif  /* BDB_TYPES__HPP */
2722