1 /* $Id: types.cpp 626573 2021-03-01 19:49:53Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Vladimir Soussov
27  *
28  * File Description:  Type conversions
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbitime.hpp>
34 
35 #include <dbapi/driver/interfaces.hpp>
36 #include <dbapi/driver/dbapi_object_convert.hpp>
37 #include <dbapi/driver/util/numeric_convert.hpp>
38 #include "memory_store.hpp"
39 
40 #include <dbapi/driver/types.hpp>
41 #include <dbapi/error_codes.hpp>
42 
43 #include <string.h>
44 
45 
46 #define NCBI_USE_ERRCODE_X   Dbapi_DrvrTypes
47 
48 
49 BEGIN_NCBI_SCOPE
50 
51 
52 inline
s_MakeLittleEndian(TStringUCS2 & s)53 void s_MakeLittleEndian(TStringUCS2& s)
54 {
55 #ifdef WORDS_BIGENDIAN
56     NON_CONST_ITERATE (TStringUCS2, it, s) {
57         *it = (*it << 8) | (*it >> 8);
58     }
59 #endif
60 }
61 
62 
63 /////////////////////////////////////////////////////////////////////////////
64 template<>
operator const char*(void) const65 CGenericSqlString<char>::operator const char*(void) const
66 {
67     return this->c_str();
68 }
69 
70 #ifdef HAVE_WSTRING
71 template<>
operator const wchar_t*(void) const72 CGenericSqlString<wchar_t>::operator const wchar_t*(void) const
73 {
74     return this->c_str();
75 }
76 #endif
77 
78 
79 /////////////////////////////////////////////////////////////////////////////
CWString(void)80 CWString::CWString(void) :
81     m_AvailableValueType(0),
82     m_StringEncoding(eEncoding_Unknown),
83     m_Char(NULL)
84 #ifdef HAVE_WSTRING
85     , m_WChar(NULL)
86 #endif
87 {
88 }
89 
90 
CWString(const CWString & str)91 CWString::CWString(const CWString& str) :
92     m_AvailableValueType(str.m_AvailableValueType),
93     m_StringEncoding(str.m_StringEncoding),
94     m_Char(NULL),
95 #ifdef HAVE_WSTRING
96     m_WChar(NULL),
97 #endif
98     m_String(str.m_String),
99 #ifdef HAVE_WSTRING
100     m_WString(str.m_WString),
101 #endif
102     m_UTF8String(str.m_UTF8String)
103 {
104     // Assign m_Char even if m_String is empty ...
105     m_Char = m_String.c_str();
106 
107 #ifdef HAVE_WSTRING
108     // Assign m_WChar even if m_WString is empty ...
109     m_WChar = m_WString.c_str();
110 #endif
111 }
112 
113 
CWString(const char * str,string::size_type size,EEncoding enc)114 CWString::CWString(const char* str,
115                    string::size_type size,
116                    EEncoding enc) :
117     m_AvailableValueType(eChar),
118     m_StringEncoding(enc),
119     m_Char(NULL)
120 #ifdef HAVE_WSTRING
121     , m_WChar(NULL)
122 #endif
123 {
124     if (size == string::npos) {
125         m_Char = str;
126     } else {
127         if (str) {
128             m_String.assign(str, size);
129             m_Char = m_String.c_str();
130         }
131         m_AvailableValueType |= eString;
132     }
133 }
134 
135 
136 #ifdef HAVE_WSTRING
CWString(const wchar_t * str,wstring::size_type size)137 CWString::CWString(const wchar_t* str,
138                    wstring::size_type size) :
139     m_AvailableValueType(eWChar),
140     m_StringEncoding(eEncoding_Unknown),
141     m_Char(NULL),
142     m_WChar(NULL)
143 {
144     if (size == wstring::npos) {
145         m_WChar = str;
146     } else {
147         if (str) {
148             m_WString.assign(str, size);
149             m_WChar = m_WString.c_str();
150         }
151         m_AvailableValueType |= eWString;
152     }
153 }
154 #endif
155 
156 
CWString(const string & str,EEncoding enc)157 CWString::CWString(const string& str, EEncoding enc) :
158     m_AvailableValueType(eString),
159     m_StringEncoding(enc),
160     m_Char(NULL),
161 #ifdef HAVE_WSTRING
162     m_WChar(NULL),
163 #endif
164     m_String(str)
165 {
166     m_Char = m_String.c_str();
167     m_AvailableValueType |= eChar;
168 }
169 
170 
171 #ifdef HAVE_WSTRING
CWString(const wstring & str)172 CWString::CWString(const wstring& str) :
173     m_AvailableValueType(eWString),
174     m_Char(NULL),
175     m_WChar(NULL),
176     m_WString(str)
177 {
178     m_WChar = m_WString.c_str();
179     m_AvailableValueType |= eWChar;
180 }
181 #endif
182 
183 
~CWString(void)184 CWString::~CWString(void)
185 {
186 }
187 
188 
operator =(const CWString & str)189 CWString& CWString::operator=(const CWString& str)
190 {
191     if (&str != this) {
192         m_AvailableValueType = str.m_AvailableValueType;
193         m_StringEncoding = str.m_StringEncoding;
194         m_Char = NULL;
195         m_String = str.m_String;
196         m_UTF8String = str.m_UTF8String;
197         m_Char = m_String.c_str();
198 
199 #ifdef HAVE_WSTRING
200         m_WChar = NULL;
201         m_WString = str.m_WString;
202         m_WChar = m_WString.c_str();
203 #endif
204     }
205 
206     return *this;
207 }
208 
209 // Deprecated conversions, defined out of line to reduce warnings
operator char*(void) const210 CWString::operator char*(void) const
211 {
212     return const_cast<char*>(AsCString());
213 }
214 
operator const char*(void) const215 CWString::operator const char*(void) const
216 {
217     return AsCString();
218 }
219 
operator wchar_t*(void) const220 CWString::operator wchar_t*(void) const
221 {
222     return const_cast<wchar_t*>(AsCWString());
223 }
224 
operator const wchar_t*(void) const225 CWString::operator const wchar_t*(void) const
226 {
227     return AsCWString();
228 }
229 
230 
x_CalculateEncoding(EEncoding str_enc) const231 void CWString::x_CalculateEncoding(EEncoding str_enc) const
232 {
233     if (str_enc != eEncoding_Unknown) {
234         m_StringEncoding = str_enc;
235     } else {
236         m_StringEncoding = eEncoding_ISO8859_1;
237     }
238 }
239 
x_UTF8ToString(EEncoding str_enc) const240 void CWString::x_UTF8ToString(EEncoding str_enc) const
241 {
242     if (m_StringEncoding == eEncoding_Unknown) {
243         x_CalculateEncoding(str_enc);
244     }
245 
246     if (m_StringEncoding == eEncoding_UTF8) {
247         m_String = m_UTF8String;
248     } else {
249         m_String = CUtf8::AsSingleByteString(m_UTF8String,m_StringEncoding);
250     }
251 
252     m_AvailableValueType |= eString;
253 }
254 
255 
x_StringToUTF8(EEncoding str_enc) const256 void CWString::x_StringToUTF8(EEncoding str_enc) const
257 {
258     if (m_StringEncoding == eEncoding_Unknown) {
259         x_CalculateEncoding(str_enc);
260     }
261 
262     if (m_AvailableValueType & eString) {
263         m_UTF8String = CUtf8::AsUTF8(m_String, m_StringEncoding);
264     } else if (m_AvailableValueType & eChar) {
265         if (m_Char) {
266             m_UTF8String = CUtf8::AsUTF8(m_Char, m_StringEncoding);
267         } else {
268             m_UTF8String.erase();
269         }
270     }
271 
272     m_AvailableValueType |= eUTF8String;
273 }
274 
275 
x_MakeString(EEncoding str_enc) const276 void CWString::x_MakeString(EEncoding str_enc) const
277 {
278     if (m_AvailableValueType & eString) {
279         if (!(m_AvailableValueType & eChar)) {
280             if (m_String.empty()) {
281                 m_Char = NULL;
282             } else {
283                 m_Char = m_String.c_str();
284             }
285             m_AvailableValueType |= eChar;
286         }
287     } else if (m_AvailableValueType & eChar) {
288         if (m_Char) {
289             m_String.assign(m_Char);
290         } else {
291             m_String.erase();
292         }
293         m_AvailableValueType |= eString;
294     } else if (m_AvailableValueType & eUTF8String) {
295         x_UTF8ToString(str_enc);
296         x_MakeString(str_enc);
297 #ifdef HAVE_WSTRING
298     } else if (m_AvailableValueType & eWString) {
299         m_UTF8String = CUtf8::AsUTF8(m_WString);
300         m_AvailableValueType |= eUTF8String;
301         x_UTF8ToString(str_enc);
302         x_MakeString(str_enc);
303     } else if (m_AvailableValueType & eWChar) {
304         if (m_WChar) {
305             m_UTF8String = CUtf8::AsUTF8(m_WChar);
306             m_AvailableValueType |= eUTF8String;
307             x_UTF8ToString(str_enc);
308         } else {
309             m_String.erase();
310             m_AvailableValueType |= eString;
311         }
312         x_MakeString(str_enc);
313 #endif
314     }
315 }
316 
317 #ifdef HAVE_WSTRING
x_MakeWString(EEncoding str_enc) const318 void CWString::x_MakeWString(EEncoding str_enc) const
319 {
320     if (m_AvailableValueType & eWString) {
321         if (!(m_AvailableValueType & eWChar)) {
322             if (m_WString.empty()) {
323                 m_WChar = NULL;
324             } else {
325                 m_WChar = m_WString.c_str();
326             }
327             m_AvailableValueType |= eWChar;
328         }
329     } else if (m_AvailableValueType & eWChar) {
330         if (m_WChar) {
331             m_WString.assign(m_WChar);
332         } else {
333             m_WString.erase();
334         }
335         m_AvailableValueType |= eWString;
336     } else if (m_AvailableValueType & eUTF8String) {
337         m_WString = CUtf8::AsBasicString<wchar_t>(m_UTF8String);
338         m_AvailableValueType |= eWString;
339         x_MakeWString(str_enc);
340     } else if (m_AvailableValueType & eString) {
341         x_StringToUTF8(str_enc);
342         x_MakeWString(str_enc);
343     } else if (m_AvailableValueType & eChar) {
344         if (m_Char) {
345             x_StringToUTF8(str_enc);
346             x_MakeWString(str_enc);
347         } else {
348             m_WString.erase();
349             m_AvailableValueType |= eWString;
350         }
351     }
352 }
353 #endif
354 
x_MakeUTF8String(EEncoding str_enc) const355 void CWString::x_MakeUTF8String(EEncoding str_enc) const
356 {
357     if (m_AvailableValueType & eUTF8String) {
358         return;
359     } else if (m_AvailableValueType & eString) {
360         x_StringToUTF8(str_enc);
361     } else if (m_AvailableValueType & eChar) {
362         x_StringToUTF8(str_enc);
363 #ifdef HAVE_WSTRING
364     } else if (m_AvailableValueType & eWString) {
365         m_UTF8String = CUtf8::AsUTF8(m_WString);
366         m_AvailableValueType |= eUTF8String;
367     } else if (m_AvailableValueType & eWChar) {
368         if (m_WChar) {
369             m_UTF8String = CUtf8::AsUTF8(m_WChar);
370         } else {
371             m_UTF8String.erase();
372         }
373         m_AvailableValueType |= eUTF8String;
374 #endif
375     }
376 }
377 
x_MakeUCS2LEString(EEncoding str_enc) const378 void CWString::x_MakeUCS2LEString(EEncoding str_enc) const
379 {
380     if (m_AvailableValueType & eUCS2LEString) {
381         return;
382     } else {
383         x_MakeUTF8String(str_enc);
384         m_UCS2LEString = CUtf8::AsBasicString<TCharUCS2>(m_UTF8String);
385         s_MakeLittleEndian(m_UCS2LEString);
386         m_AvailableValueType |= eUCS2LEString;
387     }
388 }
389 
GetSymbolNum(void) const390 size_t CWString::GetSymbolNum(void) const
391 {
392     size_t num = 0;
393 
394     if (m_AvailableValueType & eString) {
395         num = m_String.size();
396 #ifdef HAVE_WSTRING
397     } else if (m_AvailableValueType & eWString) {
398         num = m_WString.size();
399 #endif
400     } else if (m_AvailableValueType & eChar) {
401         if (m_Char) {
402             num = strlen(m_Char);
403         }
404 #ifdef HAVE_WSTRING
405     } else if (m_AvailableValueType & eWChar) {
406         if (m_WChar) {
407             // ??? Should be a better solution ...
408             x_MakeWString();
409             num = m_WString.size();
410         }
411 #endif
412     } else if (m_AvailableValueType & eUTF8String) {
413         num = CUtf8::GetSymbolCount(m_UTF8String);
414     }
415 
416     return num;
417 }
418 
Clear(void)419 void CWString::Clear(void)
420 {
421     m_AvailableValueType = 0;
422     m_StringEncoding = eEncoding_Unknown;
423     m_Char = NULL;
424     m_String.erase();
425 #ifdef HAVE_WSTRING
426     m_WChar = NULL;
427     m_WString.erase();
428 #endif
429     m_UTF8String.erase();
430 }
431 
Assign(const char * str,string::size_type size,EEncoding enc)432 void CWString::Assign(const char* str,
433                       string::size_type size,
434                       EEncoding enc)
435 {
436 #ifdef HAVE_WSTRING
437     m_WChar = NULL;
438     m_WString.erase();
439 #endif
440     m_UTF8String.erase();
441 
442     m_StringEncoding = enc;
443     if (size == string::npos) {
444         m_String.erase();
445         m_Char = str;
446         m_AvailableValueType = eChar;
447     } else {
448         if (str) {
449             m_String.assign(str, size);
450             m_Char = m_String.c_str();
451         } else {
452             m_Char = NULL;
453             m_String.erase();
454         }
455         m_AvailableValueType = eChar | eString;
456     }
457 }
458 
459 #ifdef HAVE_WSTRING
Assign(const wchar_t * str,wstring::size_type size)460 void CWString::Assign(const wchar_t* str,
461                       wstring::size_type size)
462 {
463     m_StringEncoding = eEncoding_Unknown;
464     m_Char = NULL;
465     m_String.erase();
466     m_UTF8String.erase();
467 
468     if (size == wstring::npos) {
469         m_WString.erase();
470         m_WChar = str;
471         m_AvailableValueType = eWChar;
472     } else {
473         if (str) {
474             m_WString.assign(str, size);
475             m_WChar = m_WString.c_str();
476         } else {
477             m_WChar = NULL;
478             m_WString.erase();
479         }
480         m_AvailableValueType = eWChar | eWString;
481     }
482 }
483 #endif
484 
Assign(const string & str,EEncoding enc)485 void CWString::Assign(const string& str,
486                       EEncoding enc)
487 {
488 #ifdef HAVE_WSTRING
489     m_WChar = NULL;
490     m_WString.erase();
491 #endif
492     m_UTF8String.erase();
493 
494     m_StringEncoding = enc;
495     m_String = str;
496     m_Char = m_String.c_str();
497     m_AvailableValueType = eChar | eString;
498 }
499 
500 #ifdef HAVE_WSTRING
Assign(const wstring & str)501 void CWString::Assign(const wstring& str)
502 {
503     m_StringEncoding = eEncoding_Unknown;
504     m_Char = NULL;
505     m_String.erase();
506     m_UTF8String.erase();
507 
508     m_WString = str;
509     m_WChar = m_WString.c_str();
510     m_AvailableValueType = eWChar | eWString;
511 }
512 #endif
513 
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 static
CheckStringTruncation(size_t cur_len,size_t max_len)517 void CheckStringTruncation(size_t cur_len, size_t max_len)
518 {
519     if (cur_len > max_len) {
520         ERR_POST_X(1, Warning << "String of size " << cur_len <<
521                       " was truncated to " << max_len << " character(s)");
522     }
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 static
CheckBinaryTruncation(size_t cur_len,size_t max_len)527 void CheckBinaryTruncation(size_t cur_len, size_t max_len)
528 {
529     if (cur_len > max_len) {
530         ERR_POST_X(2, Warning << "Binary data of size " << cur_len <<
531                       " was truncated to " << max_len << " byte(s)");
532     }
533 }
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 //  CDB_Object::
537 //
538 
CDB_Object(bool is_null)539 CDB_Object::CDB_Object(bool is_null) :
540     m_Null(is_null)
541 {
542     return;
543 }
544 
~CDB_Object()545 CDB_Object::~CDB_Object()
546 {
547     return;
548 }
549 
AssignNULL()550 void CDB_Object::AssignNULL()
551 {
552     SetNULL();
553 }
554 
555 
Create(EDB_Type type,size_t size)556 CDB_Object* CDB_Object::Create(EDB_Type type, size_t size)
557 {
558     switch ( type ) {
559     case eDB_Int             : return new CDB_Int           ();
560     case eDB_SmallInt        : return new CDB_SmallInt      ();
561     case eDB_TinyInt         : return new CDB_TinyInt       ();
562     case eDB_BigInt          : return new CDB_BigInt        ();
563     case eDB_VarChar         : return new CDB_VarChar       ();
564     case eDB_Char            : return new CDB_Char      (size);
565     case eDB_VarBinary       : return new CDB_VarBinary     ();
566     case eDB_Binary          : return new CDB_Binary    (size);
567     case eDB_Float           : return new CDB_Float         ();
568     case eDB_Double          : return new CDB_Double        ();
569     case eDB_DateTime        : return new CDB_DateTime      ();
570     case eDB_BigDateTime     : return new CDB_BigDateTime   ();
571     case eDB_SmallDateTime   : return new CDB_SmallDateTime ();
572     case eDB_Text            : return new CDB_Text          ();
573     case eDB_Image           : return new CDB_Image         ();
574     case eDB_Bit             : return new CDB_Bit           ();
575     case eDB_Numeric         : return new CDB_Numeric       ();
576     case eDB_LongBinary      : return new CDB_LongBinary(size);
577     case eDB_LongChar        : return new CDB_LongChar  (size);
578     case eDB_VarCharMax      : return new CDB_VarCharMax    ();
579     case eDB_VarBinaryMax    : return new CDB_VarBinaryMax  ();
580     case eDB_UnsupportedType : break;
581     }
582     DATABASE_DRIVER_ERROR("unknown type " + NStr::IntToString(type), 2);
583 }
584 
585 
GetTypeName(EDB_Type db_type,bool throw_on_unknown)586 const char* CDB_Object::GetTypeName(EDB_Type db_type, bool throw_on_unknown)
587 {
588     switch ( db_type ) {
589     case eDB_Int             : return "DB_Int";
590     case eDB_SmallInt        : return "DB_SmallInt";
591     case eDB_TinyInt         : return "DB_TinyInt";
592     case eDB_BigInt          : return "DB_BigInt";
593     case eDB_VarChar         : return "DB_VarChar";
594     case eDB_Char            : return "DB_Char";
595     case eDB_VarBinary       : return "DB_VarBinary";
596     case eDB_Binary          : return "DB_Binary";
597     case eDB_Float           : return "DB_Float";
598     case eDB_Double          : return "DB_Double";
599     case eDB_DateTime        : return "DB_DateTime";
600     case eDB_BigDateTime     : return "DB_BigDateTime";
601     case eDB_SmallDateTime   : return "DB_SmallDateTime";
602     case eDB_Text            : return "DB_Text";
603     case eDB_Image           : return "DB_Image";
604     case eDB_Bit             : return "DB_Bit";
605     case eDB_Numeric         : return "DB_Numeric";
606     case eDB_LongBinary      : return "DB_LongBinary";
607     case eDB_LongChar        : return "DB_LongChar";
608     case eDB_VarCharMax      : return "DB_VarCharMax";
609     case eDB_VarBinaryMax    : return "DB_VarBinaryMax";
610     case eDB_UnsupportedType : return "DB_UnsupportedType";
611     }
612 
613     if (throw_on_unknown) {
614         DATABASE_DRIVER_ERROR("unknown type " + NStr::IntToString(db_type), 2);
615     }
616 
617     return "DB_???";
618 }
619 
620 
621 NCBI_PARAM_DEF(unsigned int, dbapi, max_logged_param_length, 255);
622 
623 
GetLogString(void) const624 string CDB_Object::GetLogString(void) const
625 {
626     if (IsNULL()) {
627         return "NULL";
628     }
629 
630     unsigned int max_length = TDbapi_MaxLoggedParamLength::GetDefault();
631     string       result;
632 
633     if (IsBlobType(GetType())) {
634         const CDB_Stream& s = static_cast<const CDB_Stream&>(*this);
635         AutoArray<char> buff(max_length + 1);
636         result.assign(buff.get(), s.PeekAt(buff.get(), 0, max_length + 1));
637     } else {
638         try {
639             result = (string)ConvertSQL(*this);
640         } catch (exception& e) {
641             ERR_POST(Warning << "Exception converting from "
642                      << GetTypeName(GetType()) << ": " << e.what());
643             return "???";
644         }
645     }
646 
647     if (result.length() > max_length) {
648         result.resize(max_length);
649         if (max_length > 3) {
650             result[max_length - 1] = result[max_length - 2] =
651                 result[max_length - 3] = '.';
652         }
653     }
654     // XXX - retrim?
655     return NStr::PrintableString
656         (result, NStr::fNewLine_Quote | NStr::fNonAscii_Quote);
657 }
658 
659 
660 /////////////////////////////////////////////////////////////////////////////
661 //  CDB_Int::
662 //
663 
CDB_Int()664 CDB_Int::CDB_Int() :
665     CDB_Object(true),
666     m_Val(0)
667 {
668     return;
669 }
670 
CDB_Int(const Int4 & i)671 CDB_Int::CDB_Int(const Int4& i) :
672     CDB_Object(false),
673     m_Val(i)
674 {
675     return;
676 }
677 
~CDB_Int()678 CDB_Int::~CDB_Int()
679 {
680     return;
681 }
682 
GetType() const683 EDB_Type CDB_Int::GetType() const
684 {
685     return eDB_Int;
686 }
687 
Clone() const688 CDB_Object* CDB_Int::Clone() const
689 {
690     return IsNULL() ? new CDB_Int : new CDB_Int(m_Val);
691 }
692 
AssignValue(const CDB_Object & v)693 void CDB_Int::AssignValue(const CDB_Object& v)
694 {
695     switch( v.GetType() ) {
696         case eDB_Int     : *this = static_cast<const CDB_Int&>(v); break;
697         case eDB_SmallInt: *this = static_cast<const CDB_SmallInt&>(v).Value(); break;
698         case eDB_TinyInt : *this = static_cast<const CDB_TinyInt &>(v).Value(); break;
699         default:
700             DATABASE_DRIVER_ERROR( "wrong type of CDB_Object", 2 );
701     }
702 
703 }
704 
705 
706 /////////////////////////////////////////////////////////////////////////////
707 //  CDB_SmallInt::
708 //
709 
CDB_SmallInt()710 CDB_SmallInt::CDB_SmallInt() :
711     CDB_Object(true),
712     m_Val(0)
713 {
714     return;
715 }
716 
CDB_SmallInt(const Int2 & i)717 CDB_SmallInt::CDB_SmallInt(const Int2& i) :
718     CDB_Object(false),
719     m_Val(i)
720 {
721     return;
722 }
723 
~CDB_SmallInt()724 CDB_SmallInt::~CDB_SmallInt()
725 {
726     return;
727 }
728 
GetType() const729 EDB_Type CDB_SmallInt::GetType() const
730 {
731     return eDB_SmallInt;
732 }
733 
Clone() const734 CDB_Object* CDB_SmallInt::Clone() const
735 {
736     return IsNULL() ? new CDB_SmallInt : new CDB_SmallInt(m_Val);
737 }
738 
AssignValue(const CDB_Object & v)739 void CDB_SmallInt::AssignValue(const CDB_Object& v)
740 {
741     switch( v.GetType() ) {
742         case eDB_SmallInt: *this= (const CDB_SmallInt&)v; break;
743         case eDB_TinyInt : *this= ((const CDB_TinyInt &)v).Value(); break;
744         default:
745             DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
746                                   + GetTypeName(v.GetType(), false),
747                                   2);
748     }
749     *this= (CDB_SmallInt&)v;
750 }
751 
752 /////////////////////////////////////////////////////////////////////////////
753 //  CDB_TinyInt::
754 //
755 
CDB_TinyInt()756 CDB_TinyInt::CDB_TinyInt() :
757     CDB_Object(true),
758     m_Val(0)
759 {
760     return;
761 }
762 
CDB_TinyInt(const Uint1 & i)763 CDB_TinyInt::CDB_TinyInt(const Uint1& i) :
764     CDB_Object(false),
765     m_Val(i)
766 {
767     return;
768 }
769 
~CDB_TinyInt()770 CDB_TinyInt::~CDB_TinyInt()
771 {
772     return;
773 }
774 
GetType() const775 EDB_Type CDB_TinyInt::GetType() const
776 {
777     return eDB_TinyInt;
778 }
779 
Clone() const780 CDB_Object* CDB_TinyInt::Clone() const
781 {
782     return IsNULL() ? new CDB_TinyInt : new CDB_TinyInt(m_Val);
783 }
784 
AssignValue(const CDB_Object & v)785 void CDB_TinyInt::AssignValue(const CDB_Object& v)
786 {
787     CHECK_DRIVER_ERROR(v.GetType() != eDB_TinyInt,
788                        string("wrong type of CDB_Object: ")
789                        + GetTypeName(v.GetType(), false),
790                        2);
791 
792     *this= (const CDB_TinyInt&)v;
793 }
794 
795 
796 /////////////////////////////////////////////////////////////////////////////
797 //  CDB_BigInt::
798 //
799 
CDB_BigInt()800 CDB_BigInt::CDB_BigInt() :
801     CDB_Object(true),
802     m_Val(0)
803 {
804     return;
805 }
806 
CDB_BigInt(const Int8 & i)807 CDB_BigInt::CDB_BigInt(const Int8& i) :
808     CDB_Object(false),
809     m_Val(i)
810 {
811     return;
812 }
813 
~CDB_BigInt()814 CDB_BigInt::~CDB_BigInt()
815 {
816     return;
817 }
818 
GetType() const819 EDB_Type CDB_BigInt::GetType() const
820 {
821     return eDB_BigInt;
822 }
823 
Clone() const824 CDB_Object* CDB_BigInt::Clone() const
825 {
826     return IsNULL() ? new CDB_BigInt : new CDB_BigInt(m_Val);
827 }
828 
AssignValue(const CDB_Object & v)829 void CDB_BigInt::AssignValue(const CDB_Object& v)
830 {
831     switch( v.GetType() ) {
832         case eDB_BigInt  : *this= (const CDB_BigInt&)v; break;
833         case eDB_Int     : *this= ((const CDB_Int     &)v).Value(); break;
834         case eDB_SmallInt: *this= ((const CDB_SmallInt&)v).Value(); break;
835         case eDB_TinyInt : *this= ((const CDB_TinyInt &)v).Value(); break;
836         default:
837             DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
838                                   + GetTypeName(v.GetType(), false),
839                                   2);
840     }
841 }
842 
843 
844 template <typename TChar>
my_strnlen(const TChar * str,size_t maxlen)845 inline size_t my_strnlen(const TChar* str, size_t maxlen)
846 {
847     size_t len = 0;
848     while (len < maxlen  &&  *str != 0) {
849         ++len;
850         ++str;
851     }
852     return len;
853 }
854 
855 
856 /////////////////////////////////////////////////////////////////////////////
857 inline
MakeString(const string & s,string::size_type size,EEncoding enc=eEncoding_Unknown)858 CRef<CWString> MakeString(const string& s, string::size_type size,
859                           EEncoding enc = eEncoding_Unknown)
860 {
861     string value(s, 0, size);
862 
863     if (size != string::npos) {
864         value.resize(size, ' ');
865     }
866 
867     return CRef<CWString>(new CWString(value, enc));
868 }
869 
870 inline
MakeString(const TStringUCS2 & s,TStringUCS2::size_type size,EEncoding enc=eEncoding_Unknown)871 CRef<CWString> MakeString(const TStringUCS2& s, TStringUCS2::size_type size,
872                           EEncoding enc = eEncoding_Unknown)
873 {
874     _ASSERT(enc == eEncoding_Unknown);
875     TStringUCS2 value(s, 0, size);
876 
877     if (size != TStringUCS2::npos) {
878         value.resize(size, TCharUCS2(' '));
879     }
880 
881     s_MakeLittleEndian(value);
882     return CRef<CWString>(new CWString((const char*)value.data(),
883                                        value.size() * sizeof(TCharUCS2)));
884 }
885 
886 template <typename TChar>
887 inline
MakeString(const TChar * s,typename basic_string<TChar>::size_type size,EEncoding enc=eEncoding_Unknown)888 CRef<CWString> MakeString(const TChar* s,
889                           typename basic_string<TChar>::size_type size,
890                           EEncoding enc = eEncoding_Unknown)
891 {
892     typedef basic_string<TChar> TStr;
893     if (s == NULL) {
894         return MakeString(TStr(), size);
895     }
896 
897     TStr str;
898     if (size == TStr::npos)
899         str.assign(s);
900     else {
901         size_t str_size = my_strnlen(s, size);
902         str.assign(s, str_size);
903     }
904     return MakeString(str, size);
905 }
906 
907 /////////////////////////////////////////////////////////////////////////////
908 //  CDB_String::
909 //
910 
CDB_String(void)911 CDB_String::CDB_String(void)
912     : CDB_Object(true), m_BulkInsertionEnc(eBulkEnc_RawBytes)
913 {
914 }
915 
916 
CDB_String(const CDB_String & other,bool share_data)917 CDB_String::CDB_String(const CDB_String& other, bool share_data)
918     : CDB_Object(other), m_WString(other.m_WString),
919       m_BulkInsertionEnc(other.m_BulkInsertionEnc)
920 {
921     if (other.m_WString.NotEmpty()  &&  !share_data) {
922         m_WString.Reset(new CWString(*other.m_WString));
923     }
924 }
925 
926 
CDB_String(const string & s,EEncoding enc)927 CDB_String::CDB_String(const string& s, EEncoding enc)
928     : CDB_Object(false), m_WString(new CWString(s, enc)),
929       m_BulkInsertionEnc(eBulkEnc_RawBytes)
930 {
931 }
932 
933 
CDB_String(const char * s,string::size_type size,EEncoding enc)934 CDB_String::CDB_String(const char* s,
935                        string::size_type size,
936                        EEncoding enc)
937     : CDB_Object(s == NULL), m_WString(MakeString(s, size, enc)),
938       m_BulkInsertionEnc(eBulkEnc_RawBytes)
939 {
940 }
941 
942 
CDB_String(const string & s,string::size_type size,EEncoding enc)943 CDB_String::CDB_String(const string& s,
944                        string::size_type size,
945                        EEncoding enc)
946     : CDB_Object(false), m_WString(MakeString(s, size, enc)),
947       m_BulkInsertionEnc(eBulkEnc_RawBytes)
948 {
949 }
950 
951 
CDB_String(const TStringUCS2 & s,TStringUCS2::size_type size)952 CDB_String::CDB_String(const TStringUCS2& s, TStringUCS2::size_type size)
953     : CDB_Object(false), m_WString(MakeString(s, size)),
954       m_BulkInsertionEnc(eBulkEnc_RawUCS2)
955 {
956 }
957 
958 
959 /*
960 CDB_String::CDB_String(const TCharUCS2* s, string::size_type size)
961     : CDB_Object(s == NULL), m_WString(MakeString(s, size)),
962       m_BulkInsertionEnc(eBulkEnc_RawUCS2)
963 {
964 }
965 */
966 
967 
~CDB_String(void)968 CDB_String::~CDB_String(void)
969 {
970 }
971 
972 
operator =(const CDB_String & other)973 CDB_String& CDB_String::operator= (const CDB_String& other)
974 {
975     if (this != &other) {
976         Assign(other);
977     }
978 
979     return *this;
980 }
981 
982 
operator =(const string & s)983 CDB_String& CDB_String::operator= (const string& s)
984 {
985     Assign(s);
986     return *this;
987 }
988 
989 
operator =(const char * s)990 CDB_String& CDB_String::operator= (const char* s)
991 {
992     Assign(s);
993     return *this;
994 }
995 
996 
operator =(const TStringUCS2 & s)997 CDB_String& CDB_String::operator= (const TStringUCS2& s)
998 {
999     Assign(s);
1000     return *this;
1001 }
1002 
1003 
operator const char*(void) const1004 CDB_String::operator const char*(void) const
1005 {
1006     return m_WString.Empty() ? kEmptyCStr : m_WString->AsCString();
1007 }
1008 
1009 
1010 #ifdef HAVE_WSTRING
AsUnicode(EEncoding enc) const1011 const wchar_t* CDB_String::AsUnicode(EEncoding enc) const
1012 {
1013     return IsNULL() ? NULL : m_WString->AsUnicode(enc).c_str();
1014 }
1015 #endif
1016 
1017 
Assign(const CDB_String & other)1018 void CDB_String::Assign(const CDB_String& other)
1019 {
1020     SetNULL(other.IsNULL());
1021     m_WString.Reset((IsNULL() || other.m_WString.Empty()) ? NULL
1022                     : new CWString(*other.m_WString));
1023     m_BulkInsertionEnc = other.m_BulkInsertionEnc;
1024 }
1025 
1026 
Assign(const char * s,string::size_type size,EEncoding enc)1027 void CDB_String::Assign(const char* s,
1028                         string::size_type size,
1029                         EEncoding enc)
1030 {
1031     if ( s ) {
1032         SetNULL(false);
1033 
1034         if (m_WString.NotEmpty()  &&  size == string::npos) {
1035             m_WString->Assign(string(s), enc);
1036         } else {
1037             m_WString.Reset(MakeString(s, size, enc));
1038         }
1039     } else {
1040         SetNULL();
1041     }
1042     if (m_BulkInsertionEnc == eBulkEnc_RawUCS2) {
1043         m_BulkInsertionEnc = eBulkEnc_UCS2FromChar;
1044     }
1045 }
1046 
1047 
Assign(const string & s,string::size_type size,EEncoding enc)1048 void CDB_String::Assign(const string& s,
1049                         string::size_type size,
1050                         EEncoding enc)
1051 {
1052     SetNULL(false);
1053     m_WString.Reset(MakeString(s, size, enc));
1054     if (m_BulkInsertionEnc == eBulkEnc_RawUCS2) {
1055         m_BulkInsertionEnc = eBulkEnc_UCS2FromChar;
1056     }
1057 }
1058 
1059 
1060 /*
1061 void CDB_String::Assign(const TCharUCS2* s,
1062                         TStringUCS2::size_type size)
1063 {
1064     if ( s ) {
1065         SetNULL(false);
1066         m_WString.Reset(MakeString(s, size));
1067     } else {
1068         SetNULL();
1069     }
1070     m_BulkInsertionEnc = eBulkEnc_RawUCS2;
1071 }
1072 */
1073 
1074 
Assign(const TStringUCS2 & s,TStringUCS2::size_type size)1075 void CDB_String::Assign(const TStringUCS2& s,
1076                         TStringUCS2::size_type size)
1077 {
1078     SetNULL(false);
1079     m_WString.Reset(MakeString(s, size));
1080     m_BulkInsertionEnc = eBulkEnc_RawUCS2;
1081 }
1082 
1083 
GetBulkInsertionData(CTempString * ts,bool convert_raw_bytes) const1084 void CDB_String::GetBulkInsertionData(CTempString* ts, bool convert_raw_bytes)
1085     const
1086 {
1087     _ASSERT(ts);
1088 
1089     if (IsNULL()  ||  m_WString.Empty()) {
1090         ts->clear();
1091         return;
1092     }
1093 
1094     EBulkEnc enc = m_BulkInsertionEnc;
1095     if (convert_raw_bytes  &&  enc == eBulkEnc_RawBytes) {
1096         enc = eBulkEnc_UCS2FromChar;
1097     }
1098 
1099     switch (enc) {
1100     case eBulkEnc_RawBytes:
1101     case eBulkEnc_RawUCS2:
1102         *ts = x_GetWString();
1103         break;
1104     case eBulkEnc_UCS2FromChar:
1105     {
1106         const TStringUCS2& s2 = m_WString->AsUCS2_LE();
1107         ts->assign((char*) s2.data(), s2.size() * sizeof(TCharUCS2));
1108         break;
1109     }
1110     default:
1111         _TROUBLE;
1112     }
1113 }
1114 
1115 /////////////////////////////////////////////////////////////////////////////
1116 template <typename TChar>
1117 static
1118 typename basic_string<TChar>::size_type
get_string_size_varchar(const TChar * str,typename basic_string<TChar>::size_type len)1119 get_string_size_varchar(const TChar* str,
1120                         typename basic_string<TChar>::size_type len)
1121 {
1122     typedef basic_string<TChar> TStr;
1123 
1124     if (len == TStr::npos) {
1125         return len;
1126     } else if (str == NULL) {
1127         return 0;
1128     } else {
1129         return my_strnlen(str, len ? len : TStr::npos);
1130     }
1131 }
1132 
1133 /////////////////////////////////////////////////////////////////////////////
1134 //  CDB_VarChar::
1135 //
1136 
CDB_VarChar(void)1137 CDB_VarChar::CDB_VarChar(void)
1138 {
1139 }
1140 
1141 
CDB_VarChar(const CDB_VarChar & v,bool share_data)1142 CDB_VarChar::CDB_VarChar(const CDB_VarChar& v, bool share_data)
1143 : CDB_String(v, share_data)
1144 {
1145 }
1146 
1147 
CDB_VarChar(const string & s,EEncoding enc)1148 CDB_VarChar::CDB_VarChar(const string& s,
1149                          EEncoding enc)
1150 : CDB_String(s, enc)
1151 {
1152 }
1153 
1154 
CDB_VarChar(const char * s,EEncoding enc)1155 CDB_VarChar::CDB_VarChar(const char* s,
1156                          EEncoding enc)
1157 : CDB_String(s, string::npos, enc)
1158 {
1159 }
1160 
1161 
CDB_VarChar(const char * s,size_t l,EEncoding enc)1162 CDB_VarChar::CDB_VarChar(const char* s,
1163                          size_t l,
1164                          EEncoding enc)
1165 : CDB_String(s, get_string_size_varchar(s, l), enc)
1166 {
1167 }
1168 
1169 
CDB_VarChar(const TStringUCS2 & s,size_t l)1170 CDB_VarChar::CDB_VarChar(const TStringUCS2& s, size_t l)
1171     : CDB_String(s, get_string_size_varchar(s.data(), l))
1172 {
1173 }
1174 
1175 
1176 /*
1177 CDB_VarChar::CDB_VarChar(const TCharUCS2* s, size_t l)
1178     : CDB_String(s, get_string_size_varchar(s, l))
1179 {
1180 }
1181 */
1182 
1183 
~CDB_VarChar(void)1184 CDB_VarChar::~CDB_VarChar(void)
1185 {
1186 }
1187 
1188 
SetValue(const string & s,EEncoding enc)1189 CDB_VarChar& CDB_VarChar::SetValue(const string& s,
1190                                    EEncoding enc)
1191 {
1192     Assign(s, string::npos, enc);
1193 
1194     return *this;
1195 }
1196 
1197 
SetValue(const char * s,EEncoding enc)1198 CDB_VarChar& CDB_VarChar::SetValue(const char* s,
1199                                    EEncoding enc)
1200 {
1201     Assign(s, string::npos, enc);
1202 
1203     return *this;
1204 }
1205 
1206 
SetValue(const char * s,size_t l,EEncoding enc)1207 CDB_VarChar& CDB_VarChar::SetValue(const char* s, size_t l,
1208                                    EEncoding enc)
1209 {
1210     Assign(s, l, enc);
1211 
1212     return *this;
1213 }
1214 
1215 
SetValue(const TStringUCS2 & s)1216 CDB_VarChar& CDB_VarChar::SetValue(const TStringUCS2& s)
1217 {
1218     Assign(s, TStringUCS2::npos);
1219 
1220     return *this;
1221 }
1222 
1223 
1224 /*
1225 CDB_VarChar& CDB_VarChar::SetValue(const TCharUCS2* s, size_t l)
1226 {
1227     Assign(s, l);
1228 
1229     return *this;
1230 }
1231 */
1232 
1233 
GetType() const1234 EDB_Type CDB_VarChar::GetType() const
1235 {
1236     return eDB_VarChar;
1237 }
1238 
1239 
Clone() const1240 CDB_Object* CDB_VarChar::Clone() const
1241 {
1242     return IsNULL() ? new CDB_VarChar() : new CDB_VarChar(*this);
1243 }
1244 
1245 
ShallowClone() const1246 CDB_Object* CDB_VarChar::ShallowClone() const
1247 {
1248     return IsNULL() ? new CDB_VarChar() : new CDB_VarChar(*this, true);
1249 }
1250 
1251 
AssignValue(const CDB_Object & v)1252 void CDB_VarChar::AssignValue(const CDB_Object& v)
1253 {
1254     CHECK_DRIVER_ERROR(v.GetType() != eDB_VarChar,
1255                        string("wrong type of CDB_Object: ")
1256                        + GetTypeName(v.GetType(), false),
1257                        2);
1258 
1259     *this= (const CDB_VarChar&)v;
1260 }
1261 
1262 
1263 /////////////////////////////////////////////////////////////////////////////
1264 //  CDB_Char::
1265 //
1266 
1267 
CDB_Char(size_t s)1268 CDB_Char::CDB_Char(size_t s)
1269 : m_Size((s < 1) ? 1 : s)
1270 {
1271 }
1272 
1273 
CDB_Char(size_t s,const string & v,EEncoding enc)1274 CDB_Char::CDB_Char(size_t s,
1275                    const string& v,
1276                    EEncoding enc) :
1277     CDB_String(v, s, enc),
1278     m_Size(CDB_String::Size())
1279 {
1280 }
1281 
1282 
CDB_Char(size_t s,const char * str,EEncoding enc)1283 CDB_Char::CDB_Char(size_t s,
1284                    const char* str,
1285                    EEncoding enc) :
1286     CDB_String(str, s, enc),
1287     m_Size(CDB_String::Size())
1288 {
1289 }
1290 
1291 
CDB_Char(size_t s,const TStringUCS2 & v)1292 CDB_Char::CDB_Char(size_t s, const TStringUCS2& v)
1293     : CDB_String(v, s), m_Size(CDB_String::Size())
1294 {
1295 }
1296 
1297 
CDB_Char(const CDB_Char & v,bool share_data)1298 CDB_Char::CDB_Char(const CDB_Char& v, bool share_data) :
1299     CDB_String(v, share_data),
1300     m_Size(v.m_Size)
1301 {
1302 }
1303 
1304 
operator =(const CDB_Char & v)1305 CDB_Char& CDB_Char::operator= (const CDB_Char& v)
1306 {
1307     if (this != &v) {
1308         m_Size = v.m_Size;
1309         Assign(v);
1310     }
1311 
1312     return *this;
1313 }
1314 
1315 
operator =(const string & s)1316 CDB_Char& CDB_Char::operator= (const string& s)
1317 {
1318     // Encoding of s ???
1319     CheckStringTruncation(s.size(), m_Size);
1320     Assign(s, m_Size);
1321 
1322     return *this;
1323 }
1324 
1325 
operator =(const char * s)1326 CDB_Char& CDB_Char::operator= (const char* s)
1327 {
1328     if (s) {
1329         // Encoding of s ???
1330         size_t len = strlen(s);
1331         CheckStringTruncation(len, m_Size);
1332         Assign(s, m_Size);
1333     }
1334 
1335     return *this;
1336 }
1337 
1338 
operator =(const TStringUCS2 & s)1339 CDB_Char& CDB_Char::operator= (const TStringUCS2& s)
1340 {
1341     CheckStringTruncation(s.size(), m_Size);
1342     Assign(s, m_Size);
1343 
1344     return *this;
1345 }
1346 
1347 
SetValue(const char * str,size_t len,EEncoding enc)1348 void CDB_Char::SetValue(const char* str, size_t len, EEncoding enc)
1349 {
1350     CDB_VarChar vc_value(str, len, enc);
1351     CheckStringTruncation(vc_value.Size(), m_Size);
1352 
1353     Assign(vc_value.AsCString(), m_Size, enc);
1354 }
1355 
1356 
SetValue(const TStringUCS2 & v,size_t len)1357 void CDB_Char::SetValue(const TStringUCS2& v, size_t len)
1358 {
1359     CDB_VarChar vc_value(v, len);
1360     CheckStringTruncation(vc_value.Size(), m_Size);
1361 
1362     Assign(vc_value.Data(), m_Size);
1363 }
1364 
1365 
GetType() const1366 EDB_Type CDB_Char::GetType() const
1367 {
1368     return eDB_Char;
1369 }
1370 
Clone() const1371 CDB_Object* CDB_Char::Clone() const
1372 {
1373     return new CDB_Char(*this);
1374 }
1375 
ShallowClone() const1376 CDB_Object* CDB_Char::ShallowClone() const
1377 {
1378     return new CDB_Char(*this, true);
1379 }
1380 
AssignValue(const CDB_Object & v)1381 void CDB_Char::AssignValue(const CDB_Object& v)
1382 {
1383     CHECK_DRIVER_ERROR(v.GetType() != eDB_Char,
1384                        string("wrong type of CDB_Object: ")
1385                        + GetTypeName(v.GetType(), false),
1386                        2);
1387 
1388     const CDB_Char& cv = (const CDB_Char&)v;
1389     *this = cv;
1390 }
1391 
~CDB_Char()1392 CDB_Char::~CDB_Char()
1393 {
1394 }
1395 
1396 /////////////////////////////////////////////////////////////////////////////
1397 static
1398 string::size_type
get_string_size_longchar(const char * str,string::size_type len)1399 get_string_size_longchar(const char* str, string::size_type len)
1400 {
1401     if (len == string::npos) {
1402         return len;
1403     }
1404 
1405     if (str != NULL) {
1406         if (len == 0) {
1407             return strlen(str); // Similar to string::npos ...
1408         } else {
1409             return max(len, my_strnlen(str, len)); // This line is "min(len, str_len)" in case of varchar ...
1410         }
1411     }
1412 
1413     return 0;
1414 }
1415 
1416 /////////////////////////////////////////////////////////////////////////////
1417 //  CDB_LongChar::
1418 //
1419 
1420 
CDB_LongChar(size_t s)1421 CDB_LongChar::CDB_LongChar(size_t s)
1422     : m_Size((s < 1) ? 1 : s)
1423 {
1424 }
1425 
1426 
CDB_LongChar(size_t s,const string & v,EEncoding enc)1427 CDB_LongChar::CDB_LongChar(size_t s,
1428                            const string& v,
1429                            EEncoding enc) :
1430     CDB_String(v, s, enc),
1431     m_Size(CDB_String::Size())
1432 {
1433 }
1434 
1435 
CDB_LongChar(size_t len,const char * str,EEncoding enc)1436 CDB_LongChar::CDB_LongChar(size_t len,
1437                            const char* str,
1438                            EEncoding enc) :
1439     CDB_String(str, get_string_size_longchar(str, len), enc),
1440     m_Size(CDB_String::Size())
1441 {
1442 }
1443 
1444 
CDB_LongChar(size_t s,const TStringUCS2 & v)1445 CDB_LongChar::CDB_LongChar(size_t s,
1446                            const TStringUCS2& v)
1447     : CDB_String(v, s), m_Size(CDB_String::Size())
1448 {
1449 }
1450 
1451 
CDB_LongChar(const CDB_LongChar & v,bool share_data)1452 CDB_LongChar::CDB_LongChar(const CDB_LongChar& v, bool share_data) :
1453     CDB_String(v, share_data),
1454     m_Size(v.m_Size)
1455 {
1456 }
1457 
1458 
operator =(const CDB_LongChar & v)1459 CDB_LongChar& CDB_LongChar::operator= (const CDB_LongChar& v)
1460 {
1461     if (this != &v) {
1462         m_Size = v.m_Size;
1463         Assign(v);
1464     }
1465 
1466     return *this;
1467 }
1468 
1469 
operator =(const string & s)1470 CDB_LongChar& CDB_LongChar::operator= (const string& s)
1471 {
1472     // Encoding of s ???
1473     CheckStringTruncation(s.size(), m_Size);
1474     Assign(s, m_Size);
1475 
1476     return *this;
1477 }
1478 
1479 
operator =(const char * s)1480 CDB_LongChar& CDB_LongChar::operator= (const char* s)
1481 {
1482     if (s) {
1483         // Encoding of s ???
1484         size_t len = strlen(s);
1485         CheckStringTruncation(len, m_Size);
1486         Assign(s, m_Size);
1487     }
1488 
1489     return *this;
1490 }
1491 
1492 
operator =(const TStringUCS2 & s)1493 CDB_LongChar& CDB_LongChar::operator= (const TStringUCS2& s)
1494 {
1495     CheckStringTruncation(s.size(), m_Size);
1496     Assign(s, m_Size);
1497 
1498     return *this;
1499 }
1500 
1501 
SetValue(const char * str,size_t len,EEncoding enc)1502 void CDB_LongChar::SetValue(const char* str,
1503                             size_t len,
1504                             EEncoding enc)
1505 {
1506     CDB_VarChar vc(str, len, enc);
1507     CheckStringTruncation(vc.Size(), m_Size);
1508 
1509     Assign(vc.AsCString(), m_Size, enc);
1510 }
1511 
1512 
SetValue(const TStringUCS2 & str,size_t len)1513 void CDB_LongChar::SetValue(const TStringUCS2& str, size_t len)
1514 {
1515     CDB_VarChar vc(str, len);
1516     CheckStringTruncation(vc.Size(), m_Size);
1517 
1518     Assign(vc.Data(), m_Size);
1519 }
1520 
1521 
GetType() const1522 EDB_Type CDB_LongChar::GetType() const
1523 {
1524     return eDB_LongChar;
1525 }
1526 
1527 
Clone() const1528 CDB_Object* CDB_LongChar::Clone() const
1529 {
1530     return new CDB_LongChar(*this);
1531 }
1532 
ShallowClone() const1533 CDB_Object* CDB_LongChar::ShallowClone() const
1534 {
1535     return new CDB_LongChar(*this, true);
1536 }
1537 
1538 
AssignValue(const CDB_Object & v)1539 void CDB_LongChar::AssignValue(const CDB_Object& v)
1540 {
1541     CHECK_DRIVER_ERROR(v.GetType() != eDB_LongChar,
1542                        string("wrong type of CDB_Object: ")
1543                        + GetTypeName(v.GetType(), false),
1544                        2);
1545 
1546     const CDB_LongChar& cv= (const CDB_LongChar&)v;
1547     *this = cv;
1548 }
1549 
1550 
~CDB_LongChar()1551 CDB_LongChar::~CDB_LongChar()
1552 {
1553 }
1554 
1555 
1556 /////////////////////////////////////////////////////////////////////////////
1557 //  CDB_VarBinary::
1558 //
1559 
1560 
CDB_VarBinary(void)1561 CDB_VarBinary::CDB_VarBinary(void)
1562 {
1563 }
1564 
CDB_VarBinary(const CDB_VarBinary & v,bool share_data)1565 CDB_VarBinary::CDB_VarBinary(const CDB_VarBinary& v, bool share_data)
1566     : CDB_Object(v), m_Value(v.m_Value)
1567 {
1568     if (v.m_Value.NotEmpty()  &&  !share_data) {
1569         m_Value.Reset(new TValue(*v.m_Value));
1570     }
1571 }
1572 
CDB_VarBinary(const void * v,size_t l)1573 CDB_VarBinary::CDB_VarBinary(const void* v, size_t l)
1574 {
1575     SetValue(v, l);
1576 }
1577 
~CDB_VarBinary(void)1578 CDB_VarBinary::~CDB_VarBinary(void)
1579 {
1580 }
1581 
SetValue(const void * v,size_t l)1582 void CDB_VarBinary::SetValue(const void* v, size_t l)
1583 {
1584     if (v != NULL) {
1585         if (m_Value.Empty()) {
1586             m_Value.Reset(new TValue);
1587         }
1588         m_Value->GetData().assign(static_cast<const char*>(v), l);
1589         SetNULL(false);
1590     } else {
1591         m_Value.Reset();
1592         SetNULL();
1593     }
1594 }
1595 
1596 
operator =(const CDB_VarBinary & v)1597 CDB_VarBinary& CDB_VarBinary::operator= (const CDB_VarBinary& v)
1598 {
1599     if (this != &v) {
1600         SetNULL(v.IsNULL());
1601         m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1602                       : new TValue(*v.m_Value));
1603     }
1604 
1605     return *this;
1606 }
1607 
1608 
GetType() const1609 EDB_Type CDB_VarBinary::GetType() const
1610 {
1611     return eDB_VarBinary;
1612 }
1613 
1614 
Clone() const1615 CDB_Object* CDB_VarBinary::Clone() const
1616 {
1617     return IsNULL() ? new CDB_VarBinary : new CDB_VarBinary(*this);
1618 }
1619 
ShallowClone() const1620 CDB_Object* CDB_VarBinary::ShallowClone() const
1621 {
1622     return IsNULL() ? new CDB_VarBinary : new CDB_VarBinary(*this, true);
1623 }
1624 
1625 
AssignValue(const CDB_Object & v)1626 void CDB_VarBinary::AssignValue(const CDB_Object& v)
1627 {
1628     CHECK_DRIVER_ERROR(v.GetType() != eDB_VarBinary,
1629                        string("wrong type of CDB_Object: ")
1630                        + GetTypeName(v.GetType(), false),
1631                        2);
1632 
1633     *this= (const CDB_VarBinary&)v;
1634 }
1635 
1636 /////////////////////////////////////////////////////////////////////////////
1637 //  CDB_Binary::
1638 //
1639 
1640 
CDB_Binary(size_t s)1641 CDB_Binary::CDB_Binary(size_t s)
1642 {
1643     m_Size = (s < 1) ? 1 : s;
1644 }
1645 
1646 
CDB_Binary(size_t s,const void * v,size_t v_size)1647 CDB_Binary::CDB_Binary(size_t s, const void* v, size_t v_size)
1648 {
1649     m_Size = (s == 0) ? 1 : s;
1650     SetValue(v, v_size);
1651 }
1652 
1653 
CDB_Binary(const CDB_Binary & v,bool share_data)1654 CDB_Binary::CDB_Binary(const CDB_Binary& v, bool share_data)
1655     : CDB_Object(v), m_Size(v.m_Size), m_Value(v.m_Value)
1656 {
1657     if (v.m_Value.NotEmpty()  &&  !share_data) {
1658         m_Value.Reset(new TValue(*v.m_Value));
1659     }
1660 }
1661 
1662 
SetValue(const void * v,size_t v_size)1663 void CDB_Binary::SetValue(const void* v, size_t v_size)
1664 {
1665     if (v != NULL) {
1666         CheckBinaryTruncation(v_size, m_Size);
1667 
1668         if (m_Value.Empty()) {
1669             m_Value.Reset(new TValue);
1670         }
1671         m_Value->GetData().assign(static_cast<const char*>(v),
1672                                   min(v_size, m_Size));
1673         m_Value->GetData().resize(m_Size, '\0');
1674         SetNULL(false);
1675     } else {
1676         m_Value.Reset();
1677         SetNULL();
1678     }
1679 }
1680 
1681 
operator =(const CDB_Binary & v)1682 CDB_Binary& CDB_Binary::operator= (const CDB_Binary& v)
1683 {
1684     if (this != &v) {
1685         SetNULL(v.IsNULL());
1686         m_Size = v.m_Size;
1687         m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1688                       : new TValue(*v.m_Value));
1689     }
1690 
1691     return *this;
1692 }
1693 
1694 
GetType() const1695 EDB_Type CDB_Binary::GetType() const
1696 {
1697     return eDB_Binary;
1698 }
1699 
1700 
Clone() const1701 CDB_Object* CDB_Binary::Clone() const
1702 {
1703     return IsNULL() ? new CDB_Binary(m_Size) : new CDB_Binary(*this);
1704 }
1705 
ShallowClone() const1706 CDB_Object* CDB_Binary::ShallowClone() const
1707 {
1708     return IsNULL() ? new CDB_Binary(m_Size) : new CDB_Binary(*this, true);
1709 }
1710 
1711 
AssignValue(const CDB_Object & v)1712 void CDB_Binary::AssignValue(const CDB_Object& v)
1713 {
1714     CHECK_DRIVER_ERROR(v.GetType() != eDB_Binary,
1715                        string("wrong type of CDB_Object: ")
1716                        + GetTypeName(v.GetType(), false),
1717                        2);
1718 
1719     const CDB_Binary& cv = static_cast<const CDB_Binary&>(v);
1720     *this = cv;
1721 }
1722 
1723 
~CDB_Binary()1724 CDB_Binary::~CDB_Binary()
1725 {
1726 }
1727 
1728 /////////////////////////////////////////////////////////////////////////////
1729 //  CDB_LongBinary::
1730 //
1731 
1732 
CDB_LongBinary(size_t s)1733 CDB_LongBinary::CDB_LongBinary(size_t s)
1734 : m_Size((s < 1) ? 1 : s)
1735 , m_DataSize(0)
1736 {
1737 }
1738 
1739 
CDB_LongBinary(size_t s,const void * v,size_t v_size)1740 CDB_LongBinary::CDB_LongBinary(size_t s, const void* v, size_t v_size)
1741 : m_Size(s)
1742 {
1743     SetValue(v, v_size);
1744 }
1745 
1746 
CDB_LongBinary(const CDB_LongBinary & v,bool share_data)1747 CDB_LongBinary::CDB_LongBinary(const CDB_LongBinary& v, bool share_data)
1748 : CDB_Object(v)
1749 , m_Size(v.m_Size)
1750 , m_DataSize(v.m_DataSize)
1751 , m_Value(v.m_Value)
1752 {
1753     if (v.m_Value.NotEmpty()  &&  !share_data) {
1754         m_Value.Reset(new TValue(*v.m_Value));
1755     }
1756 }
1757 
1758 
SetValue(const void * v,size_t v_size)1759 void CDB_LongBinary::SetValue(const void* v, size_t v_size)
1760 {
1761     if (v != NULL) {
1762         m_DataSize = min(v_size, m_Size);
1763         CheckBinaryTruncation(v_size, m_Size);
1764         if (m_Value.Empty()) {
1765             m_Value.Reset(new TValue);
1766         }
1767         m_Value->GetData().assign(static_cast<const char*>(v), m_DataSize);
1768         m_Value->GetData().resize(m_Size, '\0');
1769         SetNULL(false);
1770     } else {
1771         m_Value.Reset();
1772         SetNULL();
1773         m_DataSize = 0;
1774     }
1775 }
1776 
1777 
operator =(const CDB_LongBinary & v)1778 CDB_LongBinary& CDB_LongBinary::operator= (const CDB_LongBinary& v)
1779 {
1780     if (this != &v) {
1781         SetNULL(v.IsNULL());
1782         m_Size = v.m_Size;
1783         m_DataSize = v.m_DataSize;
1784         m_Value = v.m_Value;
1785         m_Value.Reset((IsNULL() || v.m_Value.Empty()) ? NULL
1786                       : new TValue(*v.m_Value));
1787     }
1788 
1789     return *this;
1790 }
1791 
1792 
GetType() const1793 EDB_Type CDB_LongBinary::GetType() const
1794 {
1795     return eDB_LongBinary;
1796 }
1797 
1798 
Clone() const1799 CDB_Object* CDB_LongBinary::Clone() const
1800 {
1801     return new CDB_LongBinary(*this);
1802 }
1803 
ShallowClone() const1804 CDB_Object* CDB_LongBinary::ShallowClone() const
1805 {
1806     return new CDB_LongBinary(*this, true);
1807 }
1808 
1809 
AssignValue(const CDB_Object & v)1810 void CDB_LongBinary::AssignValue(const CDB_Object& v)
1811 {
1812     CHECK_DRIVER_ERROR(
1813         v.GetType() != eDB_LongBinary,
1814         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
1815         2 );
1816 
1817     const CDB_LongBinary& cv = static_cast<const CDB_LongBinary&>(v);
1818     *this = cv;
1819 }
1820 
1821 
~CDB_LongBinary()1822 CDB_LongBinary::~CDB_LongBinary()
1823 {
1824 }
1825 
1826 
1827 /////////////////////////////////////////////////////////////////////////////
1828 //  CDB_Float::
1829 //
1830 
1831 
CDB_Float()1832 CDB_Float::CDB_Float() :
1833     CDB_Object(true),
1834     m_Val(0.0)
1835 {
1836     return;
1837 }
1838 
CDB_Float(float i)1839 CDB_Float::CDB_Float(float i) :
1840     CDB_Object(false),
1841     m_Val(i)
1842 {
1843     return;
1844 }
1845 
~CDB_Float(void)1846 CDB_Float::~CDB_Float(void)
1847 {
1848 }
1849 
1850 
operator =(const float & i)1851 CDB_Float& CDB_Float::operator= (const float& i)
1852 {
1853     SetNULL(false);
1854     m_Val  = i;
1855     return *this;
1856 }
1857 
1858 
GetType() const1859 EDB_Type CDB_Float::GetType() const
1860 {
1861     return eDB_Float;
1862 }
1863 
Clone() const1864 CDB_Object* CDB_Float::Clone() const
1865 {
1866     return IsNULL() ? new CDB_Float : new CDB_Float(m_Val);
1867 }
1868 
AssignValue(const CDB_Object & v)1869 void CDB_Float::AssignValue(const CDB_Object& v)
1870 {
1871     switch( v.GetType() ) {
1872         case eDB_Float   : *this = (const CDB_Float&)v; break;
1873         case eDB_SmallInt: *this = ((const CDB_SmallInt&)v).Value(); break;
1874         case eDB_TinyInt : *this = ((const CDB_TinyInt &)v).Value(); break;
1875         default:
1876             DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
1877                                   + GetTypeName(v.GetType(), false),
1878                                   2);
1879     }
1880 }
1881 
1882 /////////////////////////////////////////////////////////////////////////////
1883 //  CDB_Double::
1884 //
1885 
1886 
CDB_Double()1887 CDB_Double::CDB_Double() :
1888     CDB_Object(true),
1889     m_Val(0.0)
1890 {
1891     return;
1892 }
1893 
CDB_Double(double i)1894 CDB_Double::CDB_Double(double i) :
1895     CDB_Object(false),
1896     m_Val(i)
1897 {
1898     return;
1899 }
1900 
~CDB_Double(void)1901 CDB_Double::~CDB_Double(void)
1902 {
1903 }
1904 
operator =(const double & i)1905 CDB_Double& CDB_Double::operator= (const double& i)
1906 {
1907     SetNULL(false);
1908     m_Val  = i;
1909     return *this;
1910 }
1911 
GetType() const1912 EDB_Type CDB_Double::GetType() const
1913 {
1914     return eDB_Double;
1915 }
1916 
Clone() const1917 CDB_Object* CDB_Double::Clone() const
1918 {
1919     return IsNULL() ? new CDB_Double : new CDB_Double(m_Val);
1920 }
1921 
AssignValue(const CDB_Object & v)1922 void CDB_Double::AssignValue(const CDB_Object& v)
1923 {
1924     switch( v.GetType() ) {
1925         case eDB_Double  : *this = (const CDB_Double&)v; break;
1926         case eDB_Float   : *this = ((const CDB_Float   &)v).Value(); break;
1927         case eDB_Int     : *this = ((const CDB_Int     &)v).Value(); break;
1928         case eDB_SmallInt: *this = ((const CDB_SmallInt&)v).Value(); break;
1929         case eDB_TinyInt : *this = ((const CDB_TinyInt &)v).Value(); break;
1930         default:
1931             DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
1932                                   + GetTypeName(v.GetType(), false),
1933                                   2);
1934     }
1935 }
1936 
1937 /////////////////////////////////////////////////////////////////////////////
1938 //  CDB_Stream::
1939 //
1940 
CDB_Stream()1941 CDB_Stream::CDB_Stream()
1942     : CDB_Object(true), m_Encoding(eBulkEnc_RawBytes)
1943 
1944 {
1945     m_Store = new CMemStore;
1946     m_Store->AddReference();
1947 }
1948 
CDB_Stream(const CDB_Stream & s,bool share_data)1949 CDB_Stream::CDB_Stream(const CDB_Stream& s, bool share_data)
1950     : CDB_Object(s), m_Encoding(s.m_Encoding), m_Store(s.m_Store)
1951 {
1952     if (share_data) {
1953         m_Store->AddReference();
1954     } else {
1955         m_Store = new CMemStore;
1956         m_Store->AddReference();
1957         Assign(s);
1958     }
1959 }
1960 
Assign(const CDB_Stream & v)1961 CDB_Stream& CDB_Stream::Assign(const CDB_Stream& v)
1962 {
1963     SetNULL(v.IsNULL());
1964     m_Store->Truncate();
1965     m_Encoding = v.m_Encoding;
1966     if ( !IsNULL() ) {
1967         char buff[1024];
1968         CMemStore* s = const_cast<CMemStore*>(&*v.m_Store);
1969         size_t pos = s->Tell();
1970         s->Seek(0L, C_RA_Storage::eHead);
1971         for (size_t n = s->Read((void*) buff, sizeof(buff));
1972              n > 0;
1973              n = s->Read((void*) buff, sizeof(buff))) {
1974             Append((void*) buff, n);
1975         }
1976         s->Seek((long) pos, C_RA_Storage::eHead);
1977     }
1978     return *this;
1979 }
1980 
AssignNULL()1981 void CDB_Stream::AssignNULL()
1982 {
1983     CDB_Object::AssignNULL();
1984     Truncate();
1985 }
1986 
Read(void * buff,size_t nof_bytes)1987 size_t CDB_Stream::Read(void* buff, size_t nof_bytes)
1988 {
1989     return m_Store->Read(buff, nof_bytes);
1990 }
1991 
Peek(void * buff,size_t nof_bytes) const1992 size_t CDB_Stream::Peek(void* buff, size_t nof_bytes) const
1993 {
1994     return m_Store->Peek(buff, nof_bytes);
1995 }
1996 
PeekAt(void * buff,size_t start,size_t nof_bytes) const1997 size_t CDB_Stream::PeekAt(void* buff, size_t start, size_t nof_bytes) const
1998 {
1999     return m_Store->PeekAt(buff, start, nof_bytes);
2000 }
2001 
Append(const void * buff,size_t nof_bytes)2002 size_t CDB_Stream::Append(const void* buff, size_t nof_bytes)
2003 {
2004     /* if (buff && (nof_bytes > 0)) */ SetNULL(false);
2005     return m_Store->Append(buff, nof_bytes);
2006 }
2007 
MoveTo(size_t byte_number)2008 bool CDB_Stream::MoveTo(size_t byte_number)
2009 {
2010     return m_Store->Seek((long) byte_number, C_RA_Storage::eHead)
2011         == (long) byte_number;
2012 }
2013 
Size() const2014 size_t CDB_Stream::Size() const
2015 {
2016     return m_Store->GetDataSize();
2017 }
2018 
Truncate(size_t nof_bytes)2019 void CDB_Stream::Truncate(size_t nof_bytes)
2020 {
2021     m_Store->Truncate(nof_bytes);
2022     SetNULL(m_Store->GetDataSize() <= 0);
2023 }
2024 
AssignValue(const CDB_Object & v)2025 void CDB_Stream::AssignValue(const CDB_Object& v)
2026 {
2027     CHECK_DRIVER_ERROR( !IsBlobType(v.GetType()),
2028         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2029         2
2030         );
2031     Assign(static_cast<const CDB_Stream&>(v));
2032 }
2033 
~CDB_Stream()2034 CDB_Stream::~CDB_Stream()
2035 {
2036     try {
2037         m_Store->RemoveReference();
2038     }
2039     NCBI_CATCH_ALL_X( 7, NCBI_CURRENT_FUNCTION )
2040 }
2041 
x_SetEncoding(EBulkEnc e)2042 void CDB_Stream::x_SetEncoding(EBulkEnc e)
2043 {
2044     if (e == eBulkEnc_UCS2FromChar) {
2045         e = eBulkEnc_RawUCS2;
2046     }
2047     if (e != m_Encoding  &&  Size() > 0) {
2048         // Alternatively, arrange to recode existing text?
2049         ERR_POST_X(8, string("Creating a mixed-encoding C")
2050                    + GetTypeName(GetType()) + " object.");
2051     }
2052     m_Encoding = e;
2053 }
2054 
x_Append(const void * buff,size_t nof_bytes)2055 size_t CDB_Stream::x_Append(const void* buff, size_t nof_bytes)
2056 {
2057     if (buff == NULL) {
2058         // return 0;
2059         buff = kEmptyCStr;
2060     }
2061     // Warn if nof_bytes == 0?
2062     return CDB_Stream::Append
2063         (buff, nof_bytes ? nof_bytes : strlen((const char*) buff));
2064 }
2065 
x_Append(const CTempString & s,EEncoding enc)2066 size_t CDB_Stream::x_Append(const CTempString& s, EEncoding enc)
2067 {
2068     switch (m_Encoding) {
2069     case eBulkEnc_RawBytes:
2070         return Append(s.data(), s.size());
2071     case eBulkEnc_RawUCS2:
2072     {
2073         TStringUCS2 s2 = CUtf8::AsBasicString<TCharUCS2>
2074             (CUtf8::AsUTF8(s, enc));
2075         s_MakeLittleEndian(s2);
2076         return Append(s2.data(), s2.size() * sizeof(TCharUCS2));
2077     }
2078     default:
2079         _TROUBLE;
2080         return 0;
2081     }
2082 }
2083 
x_Append(const TStringUCS2 & s,size_t l)2084 size_t CDB_Stream::x_Append(const TStringUCS2& s, size_t l)
2085 {
2086     x_SetEncoding(eBulkEnc_RawUCS2);
2087 #ifdef WORDS_BIGENDIAN
2088     if (l == TStringUCS2::npos) {
2089         l = s.size();
2090     }
2091     TStringUCS2 s2(s, l);
2092     s_MakeLittleEndian(s2);
2093     return Append(s2.data(), s2.size() * sizeof(TCharUCS2));
2094 #else
2095     return Append(s.data(), s.size() * sizeof(TCharUCS2));
2096 #endif
2097 }
2098 
2099 /////////////////////////////////////////////////////////////////////////////
2100 //  CDB_Image::
2101 //
2102 
CDB_Image(void)2103 CDB_Image::CDB_Image(void)
2104 {
2105 }
2106 
CDB_Image(const CDB_Image & image,bool share_data)2107 CDB_Image::CDB_Image(const CDB_Image& image, bool share_data)
2108     : CDB_Stream(image, share_data)
2109 {
2110 }
2111 
~CDB_Image(void)2112 CDB_Image::~CDB_Image(void)
2113 {
2114 }
2115 
operator =(const CDB_Image & image)2116 CDB_Image& CDB_Image::operator= (const CDB_Image& image)
2117 {
2118     return dynamic_cast<CDB_Image&> (Assign(image));
2119 }
2120 
GetType() const2121 EDB_Type CDB_Image::GetType() const
2122 {
2123     return eDB_Image;
2124 }
2125 
Clone() const2126 CDB_Object* CDB_Image::Clone() const
2127 {
2128     return new CDB_Image(*this);
2129 }
2130 
ShallowClone() const2131 CDB_Object* CDB_Image::ShallowClone() const
2132 {
2133     return new CDB_Image(*this, true);
2134 }
2135 
2136 
2137 /////////////////////////////////////////////////////////////////////////////
2138 //  CDB_VarBinaryMax::
2139 //
2140 
CDB_VarBinaryMax(void)2141 CDB_VarBinaryMax::CDB_VarBinaryMax(void)
2142 {
2143 }
2144 
CDB_VarBinaryMax(const CDB_VarBinaryMax & v,bool share_data)2145 CDB_VarBinaryMax::CDB_VarBinaryMax(const CDB_VarBinaryMax& v, bool share_data)
2146     : CDB_Stream(v, share_data)
2147 {
2148 }
2149 
CDB_VarBinaryMax(const void * v,size_t l)2150 CDB_VarBinaryMax::CDB_VarBinaryMax(const void* v, size_t l)
2151 {
2152     Append(v, l);
2153 }
2154 
~CDB_VarBinaryMax(void)2155 CDB_VarBinaryMax::~CDB_VarBinaryMax(void)
2156 {
2157 }
2158 
operator =(const CDB_VarBinaryMax & v)2159 CDB_VarBinaryMax& CDB_VarBinaryMax::operator= (const CDB_VarBinaryMax& v)
2160 {
2161     return dynamic_cast<CDB_VarBinaryMax&>(Assign(v));
2162 }
2163 
GetType() const2164 EDB_Type CDB_VarBinaryMax::GetType() const
2165 {
2166     return eDB_VarBinaryMax;
2167 }
2168 
Clone() const2169 CDB_Object* CDB_VarBinaryMax::Clone() const
2170 {
2171     return new CDB_VarBinaryMax(*this);
2172 }
2173 
ShallowClone() const2174 CDB_Object* CDB_VarBinaryMax::ShallowClone() const
2175 {
2176     return new CDB_VarBinaryMax(*this, true);
2177 }
2178 
2179 
2180 /////////////////////////////////////////////////////////////////////////////
2181 //  CDB_Text::
2182 //
2183 
CDB_Text(void)2184 CDB_Text::CDB_Text(void)
2185 {
2186 }
2187 
CDB_Text(const CDB_Text & text,bool share_data)2188 CDB_Text::CDB_Text(const CDB_Text& text, bool share_data)
2189     : CDB_Stream(text, share_data)
2190 {
2191 }
2192 
~CDB_Text(void)2193 CDB_Text::~CDB_Text(void)
2194 {
2195 }
2196 
SetEncoding(EBulkEnc e)2197 void CDB_Text::SetEncoding(EBulkEnc e)
2198 {
2199     x_SetEncoding(e);
2200 }
2201 
Append(const void * buff,size_t nof_bytes)2202 size_t CDB_Text::Append(const void* buff, size_t nof_bytes)
2203 {
2204     return x_Append(buff, nof_bytes);
2205 }
2206 
Append(const CTempString & s,EEncoding enc)2207 size_t CDB_Text::Append(const CTempString& s, EEncoding enc)
2208 {
2209     return x_Append(s, enc);
2210 }
2211 
2212 
Append(const TStringUCS2 & s)2213 size_t CDB_Text::Append(const TStringUCS2& s)
2214 {
2215     return x_Append(s);
2216 }
2217 
operator =(const CDB_Text & text)2218 CDB_Text& CDB_Text::operator= (const CDB_Text& text)
2219 {
2220     m_Encoding = text.m_Encoding;
2221     return dynamic_cast<CDB_Text&> (Assign(text));
2222 }
2223 
GetType() const2224 EDB_Type CDB_Text::GetType() const
2225 {
2226     return eDB_Text;
2227 }
2228 
Clone() const2229 CDB_Object* CDB_Text::Clone() const
2230 {
2231     return new CDB_Text(*this);
2232 }
2233 
ShallowClone() const2234 CDB_Object* CDB_Text::ShallowClone() const
2235 {
2236     return new CDB_Text(*this, true);
2237 }
2238 
2239 
2240 /////////////////////////////////////////////////////////////////////////////
2241 //  CDB_VarCharMax::
2242 //
2243 
CDB_VarCharMax(void)2244 CDB_VarCharMax::CDB_VarCharMax(void)
2245 {
2246 }
2247 
CDB_VarCharMax(const CDB_VarCharMax & v,bool share_data)2248 CDB_VarCharMax::CDB_VarCharMax(const CDB_VarCharMax& v, bool share_data)
2249     : CDB_Stream(v, share_data)
2250 {
2251 }
2252 
CDB_VarCharMax(const string & s,EEncoding enc)2253 CDB_VarCharMax::CDB_VarCharMax(const string& s, EEncoding enc)
2254 {
2255     SetValue(s, enc);
2256 }
2257 
CDB_VarCharMax(const char * s,EEncoding enc)2258 CDB_VarCharMax::CDB_VarCharMax(const char* s, EEncoding enc)
2259 {
2260     SetValue(s, enc);
2261 }
2262 
CDB_VarCharMax(const char * s,size_t l,EEncoding enc)2263 CDB_VarCharMax::CDB_VarCharMax(const char* s, size_t l, EEncoding enc)
2264 {
2265     SetValue(s, l, enc);
2266 }
2267 
CDB_VarCharMax(const TStringUCS2 & s,size_t l)2268 CDB_VarCharMax::CDB_VarCharMax(const TStringUCS2& s, size_t l)
2269 {
2270     SetValue(s);
2271 }
2272 
~CDB_VarCharMax(void)2273 CDB_VarCharMax::~CDB_VarCharMax(void)
2274 {
2275 }
2276 
SetEncoding(EBulkEnc e)2277 void CDB_VarCharMax::SetEncoding(EBulkEnc e)
2278 {
2279     x_SetEncoding(e);
2280 }
2281 
Append(const void * buff,size_t nof_bytes)2282 size_t CDB_VarCharMax::Append(const void* buff, size_t nof_bytes)
2283 {
2284     return x_Append(buff, nof_bytes);
2285 }
2286 
Append(const CTempString & s,EEncoding enc)2287 size_t CDB_VarCharMax::Append(const CTempString& s, EEncoding enc)
2288 {
2289     return x_Append(s, enc);
2290 }
2291 
Append(const TStringUCS2 & s,size_t l)2292 size_t CDB_VarCharMax::Append(const TStringUCS2& s, size_t l)
2293 {
2294     return x_Append(s);
2295 }
2296 
operator =(const CDB_VarCharMax & v)2297 CDB_VarCharMax& CDB_VarCharMax::operator= (const CDB_VarCharMax& v)
2298 {
2299     m_Encoding = v.m_Encoding;
2300     return dynamic_cast<CDB_VarCharMax&>(Assign(v));
2301 }
2302 
GetType() const2303 EDB_Type CDB_VarCharMax::GetType() const
2304 {
2305     return eDB_VarCharMax;
2306 }
2307 
Clone() const2308 CDB_Object* CDB_VarCharMax::Clone() const
2309 {
2310     return new CDB_VarCharMax(*this);
2311 }
2312 
ShallowClone() const2313 CDB_Object* CDB_VarCharMax::ShallowClone() const
2314 {
2315     return new CDB_VarCharMax(*this, true);
2316 }
2317 
2318 
2319 
2320 /////////////////////////////////////////////////////////////////////////////
2321 //  CDB_SmallDateTime::
2322 //
2323 
2324 
CDB_SmallDateTime(CTime::EInitMode mode)2325 CDB_SmallDateTime::CDB_SmallDateTime(CTime::EInitMode mode)
2326 : m_NCBITime(mode)
2327 , m_Status( 0x1 )
2328 {
2329     m_DBTime.days = 0;
2330     m_DBTime.time = 0;
2331     SetNULL(mode == CTime::eEmpty);
2332 }
2333 
2334 
CDB_SmallDateTime(const CTime & t)2335 CDB_SmallDateTime::CDB_SmallDateTime(const CTime& t)
2336 : m_NCBITime( t )
2337 , m_Status( 0x1 )
2338 {
2339     m_DBTime.days = 0;
2340     m_DBTime.time = 0;
2341     SetNULL(t.IsEmpty());
2342 }
2343 
2344 
CDB_SmallDateTime(Uint2 days,Uint2 minutes)2345 CDB_SmallDateTime::CDB_SmallDateTime(Uint2 days, Uint2 minutes)
2346 : m_Status( 0x2 )
2347 {
2348     m_DBTime.days = days;
2349     m_DBTime.time = minutes;
2350     SetNULL(false);
2351 }
2352 
2353 
~CDB_SmallDateTime(void)2354 CDB_SmallDateTime::~CDB_SmallDateTime(void)
2355 {
2356 }
2357 
Assign(Uint2 days,Uint2 minutes)2358 CDB_SmallDateTime& CDB_SmallDateTime::Assign(Uint2 days, Uint2 minutes)
2359 {
2360     m_DBTime.days = days;
2361     m_DBTime.time = minutes;
2362     m_Status      = 0x2;
2363     SetNULL(false);
2364 
2365     return *this;
2366 }
2367 
2368 
operator =(const CTime & t)2369 CDB_SmallDateTime& CDB_SmallDateTime::operator= (const CTime& t)
2370 {
2371     m_NCBITime = t;
2372     m_DBTime.days = 0;
2373     m_DBTime.time = 0;
2374     m_Status = 0x1;
2375     SetNULL(t.IsEmpty());
2376 
2377     return *this;
2378 }
2379 
2380 
Value(void) const2381 const CTime& CDB_SmallDateTime::Value(void) const
2382 {
2383     if((m_Status & 0x1) == 0) {
2384         m_NCBITime.SetTimeDBU(m_DBTime);
2385         m_Status |= 0x1;
2386     }
2387     return m_NCBITime;
2388 }
2389 
2390 
GetDays(void) const2391 Uint2 CDB_SmallDateTime::GetDays(void) const
2392 {
2393     if((m_Status & 0x2) == 0) {
2394         m_DBTime = m_NCBITime.GetTimeDBU();
2395         m_Status |= 0x2;
2396     }
2397     return m_DBTime.days;
2398 }
2399 
2400 
GetMinutes(void) const2401 Uint2 CDB_SmallDateTime::GetMinutes(void) const
2402 {
2403     if((m_Status & 0x2) == 0) {
2404         m_DBTime = m_NCBITime.GetTimeDBU();
2405         m_Status |= 0x2;
2406     }
2407     return m_DBTime.time;
2408 }
2409 
2410 
GetType() const2411 EDB_Type CDB_SmallDateTime::GetType() const
2412 {
2413     return eDB_SmallDateTime;
2414 }
2415 
Clone() const2416 CDB_Object* CDB_SmallDateTime::Clone() const
2417 {
2418     return IsNULL() ? new CDB_SmallDateTime : new CDB_SmallDateTime(Value());
2419 }
2420 
AssignValue(const CDB_Object & v)2421 void CDB_SmallDateTime::AssignValue(const CDB_Object& v)
2422 {
2423     CHECK_DRIVER_ERROR(
2424         v.GetType() != eDB_SmallDateTime,
2425         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2426         2 );
2427     *this= (const CDB_SmallDateTime&)v;
2428 }
2429 
2430 
2431 /////////////////////////////////////////////////////////////////////////////
2432 //  CDB_DateTime::
2433 //
2434 
2435 
CDB_DateTime(CTime::EInitMode mode)2436 CDB_DateTime::CDB_DateTime(CTime::EInitMode mode)
2437 : m_NCBITime(mode)
2438 , m_Status(0x1)
2439 {
2440     m_DBTime.days = 0;
2441     m_DBTime.time = 0;
2442     SetNULL(mode == CTime::eEmpty);
2443 }
2444 
2445 
CDB_DateTime(const CTime & t)2446 CDB_DateTime::CDB_DateTime(const CTime& t)
2447 : m_NCBITime( t )
2448 , m_Status( 0x1 )
2449 {
2450     m_DBTime.days = 0;
2451     m_DBTime.time = 0;
2452     SetNULL(t.IsEmpty());
2453 }
2454 
2455 
CDB_DateTime(Int4 d,Int4 s300)2456 CDB_DateTime::CDB_DateTime(Int4 d, Int4 s300)
2457 : m_Status( 0x2 )
2458 {
2459     m_DBTime.days = d;
2460     m_DBTime.time = s300;
2461     SetNULL(false);
2462 }
2463 
2464 
~CDB_DateTime(void)2465 CDB_DateTime::~CDB_DateTime(void)
2466 {
2467 }
2468 
2469 
operator =(const CTime & t)2470 CDB_DateTime& CDB_DateTime::operator= (const CTime& t)
2471 {
2472     m_NCBITime = t;
2473     m_DBTime.days = 0;
2474     m_DBTime.time = 0;
2475     m_Status = 0x1;
2476     SetNULL(t.IsEmpty());
2477     return *this;
2478 }
2479 
2480 
Assign(Int4 d,Int4 s300)2481 CDB_DateTime& CDB_DateTime::Assign(Int4 d, Int4 s300)
2482 {
2483     m_DBTime.days = d;
2484     m_DBTime.time = s300;
2485     m_Status = 0x2;
2486     SetNULL(false);
2487     return *this;
2488 }
2489 
2490 
Value(void) const2491 const CTime& CDB_DateTime::Value(void) const
2492 {
2493     if((m_Status & 0x1) == 0) {
2494         m_NCBITime.SetTimeDBI(m_DBTime);
2495         m_Status |= 0x1;
2496     }
2497     return m_NCBITime;
2498 }
2499 
2500 
GetDays(void) const2501 Int4 CDB_DateTime::GetDays(void) const
2502 {
2503     if((m_Status & 0x2) == 0) {
2504         m_DBTime = m_NCBITime.GetTimeDBI();
2505         m_Status |= 0x2;
2506     }
2507     return m_DBTime.days;
2508 }
2509 
2510 
Get300Secs(void) const2511 Int4 CDB_DateTime::Get300Secs(void) const
2512 {
2513     if((m_Status & 0x2) == 0) {
2514         m_DBTime = m_NCBITime.GetTimeDBI();
2515         m_Status |= 0x2;
2516     }
2517     return m_DBTime.time;
2518 }
2519 
2520 
GetType() const2521 EDB_Type CDB_DateTime::GetType() const
2522 {
2523     return eDB_DateTime;
2524 }
2525 
Clone() const2526 CDB_Object* CDB_DateTime::Clone() const
2527 {
2528     return IsNULL() ? new CDB_DateTime : new CDB_DateTime(Value());
2529 }
2530 
AssignValue(const CDB_Object & v)2531 void CDB_DateTime::AssignValue(const CDB_Object& v)
2532 {
2533     CHECK_DRIVER_ERROR(
2534         v.GetType() != eDB_DateTime,
2535         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2536         2 );
2537     *this= (const CDB_DateTime&)v;
2538 }
2539 
2540 
2541 /////////////////////////////////////////////////////////////////////////////
2542 //  CDB_BigDateTime::
2543 //
2544 
2545 
CDB_BigDateTime(CTime::EInitMode mode,ESQLType sql_type)2546 CDB_BigDateTime::CDB_BigDateTime(CTime::EInitMode mode, ESQLType sql_type)
2547     : m_Time(mode), m_SQLType(sql_type)
2548 {
2549     SetNULL(mode == CTime::eEmpty);
2550 }
2551 
2552 
CDB_BigDateTime(const CTime & t,ESQLType sql_type)2553 CDB_BigDateTime::CDB_BigDateTime(const CTime& t, ESQLType sql_type)
2554     : m_Time(t), m_SQLType(sql_type)
2555 {
2556     SetNULL(t.IsEmpty());
2557 }
2558 
2559 
Assign(const CTime & t,ESQLType sql_type)2560 CDB_BigDateTime& CDB_BigDateTime::Assign(const CTime& t, ESQLType sql_type)
2561 {
2562     m_Time    = t;
2563     m_SQLType = sql_type;
2564     SetNULL(t.IsEmpty());
2565     return *this;
2566 }
2567 
GetSQLTypeName(ESyntax syntax)2568 const char * CDB_BigDateTime::GetSQLTypeName(ESyntax syntax)
2569 {
2570     switch (syntax) {
2571     case eSyntax_Unknown:
2572         break;
2573     case eSyntax_Microsoft:
2574         switch (m_SQLType) {
2575         case eDate:           return "DATE";
2576         case eTime:           return "TIME";
2577         case eDateTime:       return "DATETIME2";
2578         case eDateTimeOffset: return "DATETIMEOFFSET";
2579         }
2580     case eSyntax_Sybase:
2581         switch (m_SQLType) {
2582         case eDate:           return "BIGDATE";
2583         case eTime:           return "BIGTIME";
2584         case eDateTime:       return "BIGDATETIME";
2585         case eDateTimeOffset: break;
2586         }
2587     }
2588     return kEmptyCStr;
2589 }
2590 
GetType() const2591 EDB_Type CDB_BigDateTime::GetType() const
2592 {
2593     return eDB_BigDateTime;
2594 }
2595 
Clone() const2596 CDB_Object* CDB_BigDateTime::Clone() const
2597 {
2598     return IsNULL() ? new CDB_BigDateTime : new CDB_BigDateTime(*this);
2599 }
2600 
AssignValue(const CDB_Object & v)2601 void CDB_BigDateTime::AssignValue(const CDB_Object& v)
2602 {
2603     switch (v.GetType()) {
2604     case eDB_BigDateTime: *this = (const CDB_BigDateTime&) v;        break;
2605     case eDB_DateTime   : *this = ((const CDB_DateTime&)v).Value();  break;
2606     case eDB_VarChar    :
2607     {
2608         const string& s = (const CDB_VarChar&) v;
2609         pair<ESyntax, ESQLType> id = Identify(s);
2610         Assign(CTime(s, GetTimeFormat(id.first, id.second)), id.second);
2611         break;
2612     }
2613     default:
2614         DATABASE_DRIVER_ERROR(string("wrong type of CDB_Object: ")
2615                               + GetTypeName(v.GetType(), false), 2);
2616     }
2617 }
2618 
GetTimeFormat(ESyntax syntax,ESQLType sql_type)2619 CTimeFormat CDB_BigDateTime::GetTimeFormat(ESyntax syntax, ESQLType sql_type)
2620 {
2621     const char* s = kEmptyCStr;
2622     switch (syntax) {
2623     case eSyntax_Unknown: // go with ISO
2624         switch (sql_type) {
2625         case eDate:           s = "Y-M-D"       ;  break;
2626         case eTime:           s =       "h:m:G" ;  break;
2627         case eDateTime:       s = "Y-M-DTh:m:G" ;  break;
2628         case eDateTimeOffset: s = "Y-M-DTh:m:Go";  break;
2629         }
2630         break;
2631     case eSyntax_Microsoft:
2632         switch (sql_type) {
2633         case eDate:           s = "Y-M-D"       ;  break;
2634         case eTime:           s =       "h:m:G" ;  break;
2635         case eDateTime:       s = "Y-M-D h:m:G" ;  break;
2636         case eDateTimeOffset: s = "Y-M-D h:m:Go";  break;
2637         }
2638         break;
2639     case eSyntax_Sybase: // cap time precision to avoid syntax errors(!)
2640         switch (sql_type) {
2641         case eDate:           s = "b D Y"           ;  break;
2642         case eTime:           s =        "H:m:s.rP" ;  break;
2643         case eDateTime:       s = "b D Y  H:m:s.rP" ;  break;
2644         case eDateTimeOffset: s = "b D Y  H:m:s.rPo";  break;
2645         }
2646         break;
2647     }
2648     return CTimeFormat(s);
2649 }
2650 
2651 pair<CDB_BigDateTime::ESyntax, CDB_BigDateTime::ESQLType>
Identify(const CTempString & s)2652 CDB_BigDateTime::Identify(const CTempString& s)
2653 {
2654     ESyntax  syntax   = eSyntax_Unknown;
2655     ESQLType sql_type = eDateTime;
2656 
2657     if (s.size() >= 8) {
2658         if (s[s.size() - 1] == 'M'  ||  isalpha((unsigned char) s[0])) {
2659             syntax = eSyntax_Sybase;
2660             if (s.find("  ") == NPOS) {
2661                 sql_type = (s[2] == ':') ? eTime : eDate;
2662             }
2663         } else {
2664             SIZE_TYPE pos = s.find_first_of(" T");
2665             if (pos == NPOS) {
2666                 sql_type = (s[2] == ':') ? eTime : eDate;
2667             } else {
2668                 if (s[pos] == ' ') {
2669                     syntax = eSyntax_Microsoft;
2670                 }
2671                 char c = s[s.size() - 6];
2672                 if (c == '+'  ||  c == '-') {
2673                     sql_type = eDateTimeOffset;
2674                 }
2675             }
2676         }
2677     }
2678 
2679     return make_pair(syntax, sql_type);
2680 }
2681 
2682 /////////////////////////////////////////////////////////////////////////////
2683 //  CDB_Bit::
2684 //
2685 
2686 
CDB_Bit()2687 CDB_Bit::CDB_Bit() :
2688     CDB_Object(true),
2689     m_Val(0)
2690 {
2691     return;
2692 }
2693 
CDB_Bit(int i)2694 CDB_Bit::CDB_Bit(int i) :
2695     CDB_Object(false)
2696 {
2697     m_Val = i ? 1 : 0;
2698 }
2699 
CDB_Bit(bool i)2700 CDB_Bit::CDB_Bit(bool i) :
2701     CDB_Object(false)
2702 {
2703     m_Val = i ? 1 : 0;
2704 }
2705 
~CDB_Bit(void)2706 CDB_Bit::~CDB_Bit(void)
2707 {
2708 }
2709 
operator =(const int & i)2710 CDB_Bit& CDB_Bit::operator= (const int& i)
2711 {
2712     SetNULL(false);
2713     m_Val = i ? 1 : 0;
2714     return *this;
2715 }
2716 
2717 
operator =(const bool & i)2718 CDB_Bit& CDB_Bit::operator= (const bool& i)
2719 {
2720     SetNULL(false);
2721     m_Val = i ? 1 : 0;
2722     return *this;
2723 }
2724 
2725 
GetType() const2726 EDB_Type CDB_Bit::GetType() const
2727 {
2728     return eDB_Bit;
2729 }
2730 
Clone() const2731 CDB_Object* CDB_Bit::Clone() const
2732 {
2733     return IsNULL() ? new CDB_Bit : new CDB_Bit(m_Val ? 1 : 0);
2734 }
2735 
AssignValue(const CDB_Object & v)2736 void CDB_Bit::AssignValue(const CDB_Object& v)
2737 {
2738     CHECK_DRIVER_ERROR(
2739         v.GetType() != eDB_Bit,
2740         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
2741         2 );
2742     *this= (const CDB_Bit&)v;
2743 }
2744 
2745 
2746 /////////////////////////////////////////////////////////////////////////////
2747 //
2748 //  CDB_Numeric::
2749 //
2750 
2751 
CDB_Numeric()2752 CDB_Numeric::CDB_Numeric() :
2753     CDB_Object(true),
2754     m_Precision(0),
2755     m_Scale(0)
2756 {
2757     memset(m_Body, 0, sizeof(m_Body));
2758 }
2759 
2760 
CDB_Numeric(unsigned int precision,unsigned int scale)2761 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale)
2762     : CDB_Object(false),
2763     m_Precision(precision),
2764     m_Scale(scale)
2765 {
2766     memset(m_Body, 0, sizeof(m_Body));
2767 }
2768 
2769 
CDB_Numeric(unsigned int precision,unsigned int scale,const unsigned char * arr)2770 CDB_Numeric::CDB_Numeric(unsigned int precision,
2771                          unsigned int scale,
2772                          const unsigned char* arr) :
2773     CDB_Object(false),
2774     m_Precision(precision),
2775     m_Scale(scale)
2776 {
2777     memcpy(m_Body, arr, sizeof(m_Body));
2778 }
2779 
2780 
CDB_Numeric(unsigned int precision,unsigned int scale,bool is_negative,const unsigned char * arr)2781 CDB_Numeric::CDB_Numeric(unsigned int precision,
2782                          unsigned int scale,
2783                          bool is_negative,
2784                          const unsigned char* arr) :
2785     CDB_Object(false),
2786     m_Precision(precision),
2787     m_Scale(scale)
2788 {
2789     m_Body[0]= is_negative? 1 : 0;
2790     memcpy(m_Body+1, arr, sizeof(m_Body)-1);
2791 }
2792 
2793 
CDB_Numeric(unsigned int precision,unsigned int scale,const char * val)2794 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale, const char* val)
2795     : m_Precision(0),
2796     m_Scale(0)
2797 {
2798     x_MakeFromString(precision, scale, val);
2799 }
2800 
2801 
CDB_Numeric(unsigned int precision,unsigned int scale,const string & val)2802 CDB_Numeric::CDB_Numeric(unsigned int precision, unsigned int scale, const string& val)
2803     : m_Precision(0),
2804     m_Scale(0)
2805 {
2806     x_MakeFromString(precision, scale, val);
2807 }
2808 
2809 
~CDB_Numeric(void)2810 CDB_Numeric::~CDB_Numeric(void)
2811 {
2812 }
2813 
2814 
Assign(unsigned int precision,unsigned int scale,const unsigned char * arr)2815 CDB_Numeric& CDB_Numeric::Assign(unsigned int precision,
2816                                  unsigned int scale,
2817                                  const unsigned char* arr)
2818 {
2819     m_Precision = precision;
2820     m_Scale     = scale;
2821     SetNULL(false);
2822     memcpy(m_Body, arr, sizeof(m_Body));
2823     return *this;
2824 }
2825 
2826 
Assign(unsigned int precision,unsigned int scale,bool is_negative,const unsigned char * arr)2827 CDB_Numeric& CDB_Numeric::Assign(unsigned int precision,
2828                                  unsigned int scale,
2829                                  bool is_negative,
2830                                  const unsigned char* arr)
2831 {
2832     m_Precision = precision;
2833     m_Scale     = scale;
2834     SetNULL(false);
2835     m_Body[0] = is_negative? 1 : 0;
2836     memcpy(m_Body + 1, arr, sizeof(m_Body) - 1);
2837     return *this;
2838 }
2839 
2840 
operator =(const char * val)2841 CDB_Numeric& CDB_Numeric::operator= (const char* val)
2842 {
2843     x_MakeFromString(m_Precision, m_Scale, val);
2844     return *this;
2845 }
2846 
2847 
operator =(const string & val)2848 CDB_Numeric& CDB_Numeric::operator= (const string& val)
2849 {
2850     x_MakeFromString(m_Precision, m_Scale, val);
2851     return *this;
2852 }
2853 
2854 
GetType() const2855 EDB_Type CDB_Numeric::GetType() const
2856 {
2857     return eDB_Numeric;
2858 }
2859 
2860 
Clone() const2861 CDB_Object* CDB_Numeric::Clone() const
2862 {
2863     return new CDB_Numeric((unsigned int) m_Precision,
2864                            (unsigned int) m_Scale, m_Body);
2865 }
2866 
2867 
2868 static int s_NumericBytesPerPrec[] =
2869 {
2870     2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9,
2871     10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15,
2872     16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21,
2873     22, 22, 23, 23, 24, 24, 24, 25, 25, 26, 26, 26
2874 };
2875 
2876 
2877 static const unsigned int kMaxPrecision = 50;
2878 
2879 
s_DoCarry(unsigned char * product)2880 static void s_DoCarry(unsigned char* product)
2881 {
2882     for (unsigned int j = 0;  j < kMaxPrecision;  j++) {
2883         if (product[j] > 9) {
2884             product[j + 1] += product[j] / 10;
2885             product[j]     %= 10;
2886         }
2887     }
2888 }
2889 
2890 
s_MultiplyByte(unsigned char * product,int num,const unsigned char * multiplier)2891 static void s_MultiplyByte(unsigned char* product, int num,
2892                            const unsigned char* multiplier)
2893 {
2894     unsigned char number[3];
2895     number[0] =  num        % 10;
2896     number[1] = (num /  10) % 10;
2897     number[2] = (num / 100) % 10;
2898 
2899     int top;
2900     for (top = kMaxPrecision - 1;  top >= 0  &&  !multiplier[top];  top--)
2901         continue;
2902 
2903     int start = 0;
2904     for (int i = 0;  i <= top;  i++) {
2905         for (int j =0;  j < 3;  j++) {
2906             product[j + start] += multiplier[i] * number[j];
2907         }
2908         s_DoCarry(product);
2909         start++;
2910     }
2911 }
2912 
2913 
s_ArrayToString(const unsigned char * array,int scale,char * s)2914 static char* s_ArrayToString(const unsigned char* array, int scale, char* s)
2915 {
2916     int top;
2917 
2918     for (top = kMaxPrecision - 1;  top >= 0  &&  top > scale  &&  !array[top];
2919          top--)
2920         continue;
2921 
2922     if (top == -1) {
2923         s[0] = '0';
2924         s[1] = '\0';
2925         return s;
2926     }
2927 
2928     int j = 0;
2929     for (int i = top;  i >= 0;  i--) {
2930         if (top + 1 - j == scale)
2931             s[j++] = '.';
2932         s[j++] = array[i] + '0';
2933     }
2934     s[j] = '\0';
2935 
2936     return s;
2937 }
2938 
2939 
Value() const2940 string CDB_Numeric::Value() const
2941 {
2942     unsigned char multiplier[kMaxPrecision];
2943     unsigned char temp[kMaxPrecision];
2944     unsigned char product[kMaxPrecision];
2945     char result[kMaxPrecision + 1];
2946     char* s = result;
2947     int num_bytes = 0;
2948 
2949     memset(multiplier, 0, kMaxPrecision);
2950     memset(product,    0, kMaxPrecision);
2951     multiplier[0] = 1;
2952     if (m_Precision != 0) {
2953         num_bytes = s_NumericBytesPerPrec[m_Precision-1];
2954     }
2955 
2956     if (m_Body[0] == 1) {
2957         *s++ = '-';
2958     }
2959 
2960     for (int pos = num_bytes - 1;  pos > 0;  pos--) {
2961         s_MultiplyByte(product, m_Body[pos], multiplier);
2962 
2963         memcpy(temp, multiplier, kMaxPrecision);
2964         memset(multiplier, 0, kMaxPrecision);
2965         s_MultiplyByte(multiplier, 256, temp);
2966     }
2967 
2968     s_ArrayToString(product, m_Scale, s);
2969     return result;
2970 }
2971 
2972 
2973 
s_Div256(const char * value,char * product,int base)2974 static int s_Div256(const char* value, char* product, int base)
2975 {
2976     int res = 0;
2977     char* const initial = product;
2978 
2979     while (*value < base) {
2980         res = res % 256 * base + (int)*value;
2981         ++value;
2982         while (product == initial && *value < base && res < 256) {
2983             res = res * base + (int)*value;
2984             ++value;
2985         }
2986         *product = (char) (res / 256);
2987         ++product;
2988     }
2989     *product = base;
2990     return res % 256;
2991 }
2992 
2993 
x_MakeFromString(unsigned int precision,unsigned int scale,const CTempString & s)2994 void CDB_Numeric::x_MakeFromString(unsigned int precision, unsigned int scale,
2995                                    const CTempString& s)
2996 {
2997 
2998     if (m_Precision == 0  &&  precision == 0  &&  !s.empty()) {
2999         precision = (unsigned int) s.size();
3000         if (scale == 0) {
3001             SIZE_TYPE dot_pos = s.find('.');
3002             scale = (dot_pos == NPOS) ? 0 : precision - (unsigned int) dot_pos;
3003             if (scale > 1)
3004                 --scale;
3005         }
3006     }
3007 
3008     CHECK_DRIVER_ERROR(
3009         !precision  ||  precision > kMaxPrecision,
3010         "illegal precision " + NStr::NumericToString(precision),
3011         100 );
3012     CHECK_DRIVER_ERROR(
3013         scale > precision,
3014         "scale (" + NStr::NumericToString(scale)
3015         + ") cannot be more than precision ("
3016         + NStr::NumericToString(precision) + ')',
3017         101 );
3018 
3019     bool is_negative= false;
3020     CTempString::const_iterator val = s.begin();
3021     if (val != s.end()  &&  *val == '-') {
3022         is_negative= true;
3023         ++val;
3024     }
3025 
3026     while (val != s.end()  &&  *val == '0') {
3027         ++val;
3028     }
3029 
3030     char buff1[kMaxPrecision + 1];
3031     unsigned int n = 0;
3032     while (val != s.end()  &&  n < precision) {
3033         if (*val >= '0'  &&  *val <= '9') {
3034             buff1[n++] = *val - '0';
3035         } else if (*val == '.') {
3036             break;
3037         } else {
3038             DATABASE_DRIVER_ERROR("string cannot be converted: " + string(s),
3039                                   102 );
3040         }
3041         ++val;
3042     }
3043 
3044     CHECK_DRIVER_ERROR(
3045         precision - n < scale,
3046         "string cannot be converted because of overflow: " + string(s),
3047         103 );
3048 
3049     unsigned int dec = 0;
3050     if (val != s.end()  &&  *val == '.') {
3051         ++val;
3052         while (val != s.end()  &&  dec < scale) {
3053             if (*val >= '0'  &&  *val <= '9') {
3054                 buff1[n++] = *val - '0';
3055             } else {
3056                 DATABASE_DRIVER_ERROR
3057                     ("string cannot be converted: " + string(s), 102);
3058             }
3059             ++dec;
3060             ++val;
3061         }
3062     }
3063 
3064     while (dec++ < scale) {
3065         buff1[n++] = 0;
3066     }
3067     if (n == 0) {
3068         buff1[n++] = 0;
3069     }
3070     buff1[n] = 10;
3071 
3072     char  buff2[kMaxPrecision + 1];
3073     char* p[2];
3074     p[0] = buff1;
3075     p[1] = buff2;
3076 
3077     // Setup everything now
3078     memset(m_Body, 0, sizeof(m_Body));
3079     if (is_negative) {
3080         m_Body[0] = 1/*sign*/;
3081     }
3082     unsigned char* num = m_Body + s_NumericBytesPerPrec[precision - 1] - 1;
3083     for (int i = 0;  *p[i]  ||  p[i][1] != 10;  i = 1 - i) {
3084         _ASSERT(num > m_Body);
3085         *num = s_Div256(p[i], p[1-i], 10);
3086         --num;
3087     }
3088 
3089     m_Precision = precision;
3090     m_Scale     = scale;
3091     SetNULL(false);
3092 }
3093 
AssignValue(const CDB_Object & v)3094 void CDB_Numeric::AssignValue(const CDB_Object& v)
3095 {
3096     CHECK_DRIVER_ERROR(
3097         v.GetType() != eDB_Numeric,
3098         string("wrong type of CDB_Object: ") + GetTypeName(v.GetType(), false),
3099         2 );
3100     *this = (const CDB_Numeric&)v;
3101 }
3102 
3103 END_NCBI_SCOPE
3104 
3105 
3106