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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: types.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:19:28  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: types.cpp,v 1000.2 2004/06/01 19:19:28 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Vladimir Soussov
  35.  *
  36.  * File Description:  Type conversions
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbitime.hpp>
  41. #include <dbapi/driver/exception.hpp>
  42. #include <dbapi/driver/util/numeric_convert.hpp>
  43. #include "memory_store.hpp"
  44. #include <dbapi/driver/types.hpp>
  45. #include <string.h>
  46. BEGIN_NCBI_SCOPE
  47. /////////////////////////////////////////////////////////////////////////////
  48. //  CDB_Object::
  49. //
  50. CDB_Object::~CDB_Object()
  51. {
  52.     return;
  53. }
  54. void CDB_Object::AssignNULL()
  55. {
  56.     m_Null = true;
  57. }
  58. CDB_Object* CDB_Object::Create(EDB_Type type, size_t size)
  59. {
  60.     switch ( type ) {
  61.     case eDB_Int             : return new CDB_Int           ();
  62.     case eDB_SmallInt        : return new CDB_SmallInt      ();
  63.     case eDB_TinyInt         : return new CDB_TinyInt       ();
  64.     case eDB_BigInt          : return new CDB_BigInt        ();
  65.     case eDB_VarChar         : return new CDB_VarChar       ();
  66.     case eDB_Char            : return new CDB_Char      (size);
  67.     case eDB_VarBinary       : return new CDB_VarBinary     ();
  68.     case eDB_Binary          : return new CDB_Binary    (size);
  69.     case eDB_Float           : return new CDB_Float         ();
  70.     case eDB_Double          : return new CDB_Double        ();
  71.     case eDB_DateTime        : return new CDB_DateTime      ();
  72.     case eDB_SmallDateTime   : return new CDB_SmallDateTime ();
  73.     case eDB_Text            : return new CDB_Text          ();
  74.     case eDB_Image           : return new CDB_Image         ();
  75.     case eDB_Bit             : return new CDB_Bit           ();
  76.     case eDB_Numeric         : return new CDB_Numeric       ();
  77.     case eDB_LongBinary      : return new CDB_LongBinary(size);
  78.     case eDB_LongChar        : return new CDB_LongChar  (size);
  79.     case eDB_UnsupportedType : break;
  80.     }
  81.     throw CDB_ClientEx(eDB_Error, 2, "CDB_Object::Create", "unknown type");
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. //  CDB_Int::
  85. //
  86. EDB_Type CDB_Int::GetType() const
  87. {
  88.     return eDB_Int;
  89. }
  90. CDB_Object* CDB_Int::Clone() const
  91. {
  92.     return m_Null ? new CDB_Int : new CDB_Int(m_Val);
  93. }
  94. void CDB_Int::AssignValue(CDB_Object& v)
  95. {
  96.     switch( v.GetType() ) {
  97.         case eDB_Int     : *this= (CDB_Int&)v; break;
  98.         case eDB_SmallInt: *this= ((CDB_SmallInt&)v).Value(); break;
  99.         case eDB_TinyInt : *this= ((CDB_TinyInt &)v).Value(); break;
  100.         default:
  101.             throw CDB_ClientEx(eDB_Error, 2, "CDB_Int::AssignValue",
  102.                                "wrong type of CDB_Object");
  103.     }
  104. }
  105. /////////////////////////////////////////////////////////////////////////////
  106. //  CDB_SmallInt::
  107. //
  108. EDB_Type CDB_SmallInt::GetType() const
  109. {
  110.     return eDB_SmallInt;
  111. }
  112. CDB_Object* CDB_SmallInt::Clone() const
  113. {
  114.     return m_Null ? new CDB_SmallInt : new CDB_SmallInt(m_Val);
  115. }
  116. void CDB_SmallInt::AssignValue(CDB_Object& v)
  117. {
  118.     switch( v.GetType() ) {
  119.         case eDB_SmallInt: *this= (CDB_SmallInt&)v; break;
  120.         case eDB_TinyInt : *this= ((CDB_TinyInt &)v).Value(); break;
  121.         default:
  122.             throw CDB_ClientEx(eDB_Error, 2, "CDB_SmallInt::AssignValue",
  123.                                          "wrong type of CDB_Object");
  124.     }
  125.     *this= (CDB_SmallInt&)v;
  126. }
  127. /////////////////////////////////////////////////////////////////////////////
  128. //  CDB_TinyInt::
  129. //
  130. EDB_Type CDB_TinyInt::GetType() const
  131. {
  132.     return eDB_TinyInt;
  133. }
  134. CDB_Object* CDB_TinyInt::Clone() const
  135. {
  136.     return m_Null ? new CDB_TinyInt : new CDB_TinyInt(m_Val);
  137. }
  138. void CDB_TinyInt::AssignValue(CDB_Object& v)
  139. {
  140.     if(v.GetType() != eDB_TinyInt) {
  141.         throw CDB_ClientEx(eDB_Error, 2, "CDB_TinyInt::AssignValue",
  142.                            "wrong type of CDB_Object");
  143.     }
  144.     *this= (CDB_TinyInt&)v;
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. //  CDB_BigInt::
  148. //
  149. EDB_Type CDB_BigInt::GetType() const
  150. {
  151.     return eDB_BigInt;
  152. }
  153. CDB_Object* CDB_BigInt::Clone() const
  154. {
  155.     return m_Null ? new CDB_BigInt : new CDB_BigInt(m_Val);
  156. }
  157. void CDB_BigInt::AssignValue(CDB_Object& v)
  158. {
  159.     switch( v.GetType() ) {
  160.         case eDB_BigInt  : *this= (CDB_BigInt&)v; break;
  161.         case eDB_Int     : *this= ((CDB_Int     &)v).Value(); break;
  162.         case eDB_SmallInt: *this= ((CDB_SmallInt&)v).Value(); break;
  163.         case eDB_TinyInt : *this= ((CDB_TinyInt &)v).Value(); break;
  164.         default:
  165.             throw CDB_ClientEx(eDB_Error, 2, "CDB_BigInt::AssignValue",
  166.                                "wrong type of CDB_Object");
  167.     }
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. //  CDB_VarChar::
  171. //
  172. EDB_Type CDB_VarChar::GetType() const
  173. {
  174.     return eDB_VarChar;
  175. }
  176. CDB_Object* CDB_VarChar::Clone() const
  177. {
  178.     return m_Null ? new CDB_VarChar : new CDB_VarChar(m_Val);
  179. }
  180. void CDB_VarChar::AssignValue(CDB_Object& v)
  181. {
  182.     if(v.GetType() != eDB_VarChar) {
  183.         throw CDB_ClientEx(eDB_Error, 2, "CDB_VarChar::AssignValue",
  184.                            "wrong type of CDB_Object");
  185.     }
  186.     *this= (CDB_VarChar&)v;
  187. }
  188. /////////////////////////////////////////////////////////////////////////////
  189. //  CDB_Char::
  190. //
  191. EDB_Type CDB_Char::GetType() const
  192. {
  193.     return eDB_Char;
  194. }
  195. CDB_Object* CDB_Char::Clone() const
  196. {
  197.     return new CDB_Char(*this);
  198. }
  199. void CDB_Char::AssignValue(CDB_Object& v)
  200. {
  201.     if(v.GetType() != eDB_Char) {
  202.         throw CDB_ClientEx(eDB_Error, 2, "CDB_Char::AssignValue",
  203.                            "wrong type of CDB_Object");
  204.     }
  205.     register CDB_Char& cv= (CDB_Char&)v;
  206.     if(m_Size < cv.m_Size) {
  207.         delete [] m_Val;
  208.         m_Val= new char[cv.m_Size+1];
  209.     }
  210.     m_Size= cv.m_Size;
  211.     if(cv.IsNULL()) {
  212.         m_Null= true;
  213.     }
  214.     else {
  215.         m_Null= false;
  216.         memcpy(m_Val, cv.m_Val, m_Size+1);
  217.     }
  218. }
  219. CDB_Char::~CDB_Char()
  220. {
  221.     delete [] m_Val;
  222. }
  223. /////////////////////////////////////////////////////////////////////////////
  224. //  CDB_LongChar::
  225. //
  226. EDB_Type CDB_LongChar::GetType() const
  227. {
  228.     return eDB_LongChar;
  229. }
  230. CDB_Object* CDB_LongChar::Clone() const
  231. {
  232.     return new CDB_LongChar(*this);
  233. }
  234. void CDB_LongChar::AssignValue(CDB_Object& v)
  235. {
  236.     if(v.GetType() != eDB_LongChar) {
  237.         throw CDB_ClientEx(eDB_Error, 2, "CDB_LongChar::AssignValue",
  238.                            "wrong type of CDB_Object");
  239.     }
  240.     register CDB_LongChar& cv= (CDB_LongChar&)v;
  241.     if(m_Size < cv.m_Size) {
  242.         delete [] m_Val;
  243.         m_Val= new char[cv.m_Size+1];
  244.     }
  245.     m_Size= cv.m_Size;
  246.     if(cv.IsNULL()) {
  247.         m_Null= true;
  248.     }
  249.     else {
  250.         m_Null= false;
  251.         memcpy(m_Val, cv.m_Val, m_Size+1);
  252.     }
  253. }
  254. CDB_LongChar::~CDB_LongChar()
  255. {
  256.     delete [] m_Val;
  257. }
  258. /////////////////////////////////////////////////////////////////////////////
  259. //  CDB_VarBinary::
  260. //
  261. EDB_Type CDB_VarBinary::GetType() const
  262. {
  263.     return eDB_VarBinary;
  264. }
  265. CDB_Object* CDB_VarBinary::Clone() const
  266. {
  267.     return m_Null ? new CDB_VarBinary : new CDB_VarBinary(m_Val, m_Size);
  268. }
  269. void CDB_VarBinary::AssignValue(CDB_Object& v)
  270. {
  271.     if(v.GetType() != eDB_VarBinary) {
  272.         throw CDB_ClientEx(eDB_Error, 2, "CDB_VarBinary::AssignValue",
  273.                            "wrong type of CDB_Object");
  274.     }
  275.     *this= (CDB_VarBinary&)v;
  276. }
  277. /////////////////////////////////////////////////////////////////////////////
  278. //  CDB_Binary::
  279. //
  280. EDB_Type CDB_Binary::GetType() const
  281. {
  282.     return eDB_Binary;
  283. }
  284. CDB_Object* CDB_Binary::Clone() const
  285. {
  286.     return m_Null ? new CDB_Binary(m_Size) : new CDB_Binary(*this);
  287. }
  288. void CDB_Binary::AssignValue(CDB_Object& v)
  289. {
  290.     if(v.GetType() != eDB_Binary) {
  291.         throw CDB_ClientEx(eDB_Error, 2, "CDB_Binary::AssignValue",
  292.                            "wrong type of CDB_Object");
  293.     }
  294.     register CDB_Binary& cv= (CDB_Binary&)v;
  295.     if(m_Size < cv.m_Size) {
  296.         delete [] m_Val;
  297.         m_Val= new unsigned char[cv.m_Size];
  298.     }
  299.     m_Size= cv.m_Size;
  300.     if(cv.IsNULL()) {
  301.         m_Null= true;
  302.     }
  303.     else {
  304.         m_Null= false;
  305.         memcpy(m_Val, cv.m_Val, m_Size);
  306.     }
  307. }
  308. CDB_Binary::~CDB_Binary()
  309. {
  310.     delete[] m_Val;
  311. }
  312. /////////////////////////////////////////////////////////////////////////////
  313. //  CDB_LongBinary::
  314. //
  315. EDB_Type CDB_LongBinary::GetType() const
  316. {
  317.     return eDB_LongBinary;
  318. }
  319. CDB_Object* CDB_LongBinary::Clone() const
  320. {
  321.     return new CDB_LongBinary(*this);
  322. }
  323. void CDB_LongBinary::AssignValue(CDB_Object& v)
  324. {
  325.     if(v.GetType() != eDB_LongBinary) {
  326.         throw CDB_ClientEx(eDB_Error, 2, "CDB_LongBinary::AssignValue",
  327.                            "wrong type of CDB_Object");
  328.     }
  329.     register CDB_LongBinary& cv= (CDB_LongBinary&)v;
  330.     if(cv.IsNULL()) {
  331.         m_Null= true;
  332.     }
  333.     else {
  334.         m_Null= false;
  335.         m_DataSize= (m_Size < cv.m_DataSize)? m_Size : cv.m_DataSize;
  336.         memcpy(m_Val, cv.m_Val, m_DataSize);
  337.     }
  338. }
  339. CDB_LongBinary::~CDB_LongBinary()
  340. {
  341.     delete[] m_Val;
  342. }
  343. /////////////////////////////////////////////////////////////////////////////
  344. //  CDB_Float::
  345. //
  346. EDB_Type CDB_Float::GetType() const
  347. {
  348.     return eDB_Float;
  349. }
  350. CDB_Object* CDB_Float::Clone() const
  351. {
  352.     return m_Null ? new CDB_Float : new CDB_Float(m_Val);
  353. }
  354. void CDB_Float::AssignValue(CDB_Object& v)
  355. {
  356.     switch( v.GetType() ) {
  357.         case eDB_Float   : *this= (CDB_Float&)v; break;
  358.         case eDB_SmallInt: *this= ((CDB_SmallInt&)v).Value(); break;
  359.         case eDB_TinyInt : *this= ((CDB_TinyInt &)v).Value(); break;
  360.         default:
  361.             throw CDB_ClientEx(eDB_Error, 2, "CDB_Float::AssignValue",
  362.                                "wrong type of CDB_Object");
  363.     }
  364. }
  365. /////////////////////////////////////////////////////////////////////////////
  366. //  CDB_Double::
  367. //
  368. EDB_Type CDB_Double::GetType() const
  369. {
  370.     return eDB_Double;
  371. }
  372. CDB_Object* CDB_Double::Clone() const
  373. {
  374.     return m_Null ? new CDB_Double : new CDB_Double(m_Val);
  375. }
  376. void CDB_Double::AssignValue(CDB_Object& v)
  377. {
  378.     switch( v.GetType() ) {
  379.         case eDB_Double  : *this= (CDB_Double&)v; break;
  380.         case eDB_Float   : *this= ((CDB_Float   &)v).Value(); break;
  381.         case eDB_Int     : *this= ((CDB_Int     &)v).Value(); break;
  382.         case eDB_SmallInt: *this= ((CDB_SmallInt&)v).Value(); break;
  383.         case eDB_TinyInt : *this= ((CDB_TinyInt &)v).Value(); break;
  384.         default:
  385.             throw CDB_ClientEx(eDB_Error, 2, "CDB_Double::AssignValue",
  386.                                "wrong type of CDB_Object");
  387.     }
  388. }
  389. /////////////////////////////////////////////////////////////////////////////
  390. //  CDB_Stream::
  391. //
  392. CDB_Stream::CDB_Stream()
  393.     : CDB_Object(true)
  394. {
  395.     m_Store = new CMemStore;
  396. }
  397. CDB_Stream& CDB_Stream::Assign(const CDB_Stream& v)
  398. {
  399.     m_Null = v.m_Null;
  400.     m_Store->Truncate();
  401.     if ( !m_Null ) {
  402.         char buff[1024];
  403.         CMemStore* s = (CMemStore*) &v.m_Store;
  404.         size_t pos = s->Tell();
  405.         for (size_t n = s->Read((void*) buff, sizeof(buff));
  406.              n > 0;
  407.              n = s->Read((void*) buff, sizeof(buff))) {
  408.             Append((void*) buff, n);
  409.         }
  410.         s->Seek((long) pos, C_RA_Storage::eHead);
  411.     }
  412.     return *this;
  413. }
  414. void CDB_Stream::AssignNULL()
  415. {
  416.     CDB_Object::AssignNULL();
  417.     Truncate();
  418. }
  419. size_t CDB_Stream::Read(void* buff, size_t nof_bytes)
  420. {
  421.     return m_Store->Read(buff, nof_bytes);
  422. }
  423. size_t CDB_Stream::Append(const void* buff, size_t nof_bytes)
  424. {
  425.     if(buff && (nof_bytes > 0)) m_Null = false;
  426.     return m_Store->Append(buff, nof_bytes);
  427. }
  428. bool CDB_Stream::MoveTo(size_t byte_number)
  429. {
  430.     return m_Store->Seek((long) byte_number, C_RA_Storage::eHead)
  431.         == (long) byte_number;
  432. }
  433. size_t CDB_Stream::Size() const
  434. {
  435.     return m_Store->GetDataSize();
  436. }
  437. void CDB_Stream::Truncate(size_t nof_bytes)
  438. {
  439.     m_Store->Truncate(nof_bytes);
  440.     m_Null = (m_Store->GetDataSize() <= 0);
  441. }
  442. void CDB_Stream::AssignValue(CDB_Object& v)
  443. {
  444.     if((v.GetType() != eDB_Image) && (v.GetType() != eDB_Text)) {
  445.         throw CDB_ClientEx(eDB_Error, 2, "CDB_Stream::AssignValue",
  446.                            "wrong type of CDB_Object");
  447.     }
  448.     Assign((CDB_Stream&)v);
  449. }
  450. CDB_Stream::~CDB_Stream()
  451. {
  452.     delete m_Store;
  453. }
  454. /////////////////////////////////////////////////////////////////////////////
  455. //  CDB_Image::
  456. //
  457. CDB_Image& CDB_Image::operator= (const CDB_Image& image)
  458. {
  459.     return dynamic_cast<CDB_Image&> (Assign(image));
  460. }
  461. EDB_Type CDB_Image::GetType() const
  462. {
  463.     return eDB_Image;
  464. }
  465. CDB_Object* CDB_Image::Clone() const
  466. {
  467.     if ( !m_Null ) {
  468.         throw CDB_ClientEx(eDB_Error, 1, "CDB_Image::Clone",
  469.                            "Clone for the non NULL image is not supported");
  470.     }
  471.     return new CDB_Image;
  472. }
  473. /////////////////////////////////////////////////////////////////////////////
  474. //  CDB_Text::
  475. //
  476. size_t CDB_Text::Append(const void* buff, size_t nof_bytes)
  477. {
  478.     if(!buff) return 0;
  479.     return CDB_Stream::Append
  480.         (buff, nof_bytes ? nof_bytes : strlen((const char*) buff));
  481. }
  482. size_t CDB_Text::Append(const string& s)
  483. {
  484.     return CDB_Stream::Append(s.data(), s.size());
  485. }
  486. CDB_Text& CDB_Text::operator= (const CDB_Text& text)
  487. {
  488.     return dynamic_cast<CDB_Text&> (Assign(text));
  489. }
  490. EDB_Type CDB_Text::GetType() const
  491. {
  492.     return eDB_Text;
  493. }
  494. CDB_Object* CDB_Text::Clone() const
  495. {
  496.     if ( !m_Null ) {
  497.         throw CDB_ClientEx(eDB_Error, 1, "CDB_Text::Clone",
  498.                            "Clone for the non-NULL text is not supported");
  499.     }
  500.     return new CDB_Text;
  501. }
  502. /////////////////////////////////////////////////////////////////////////////
  503. //  CDB_SmallDateTime::
  504. //
  505. EDB_Type CDB_SmallDateTime::GetType() const
  506. {
  507.     return eDB_SmallDateTime;
  508. }
  509. CDB_Object* CDB_SmallDateTime::Clone() const
  510. {
  511.     return m_Null ? new CDB_SmallDateTime : new CDB_SmallDateTime(Value());
  512. }
  513. void CDB_SmallDateTime::AssignValue(CDB_Object& v)
  514. {
  515.     if(v.GetType() != eDB_SmallDateTime) {
  516.         throw CDB_ClientEx(eDB_Error, 2, "CDB_SmallDateTime::AssignValue",
  517.                            "wrong type of CDB_Object");
  518.     }
  519.     *this= (CDB_SmallDateTime&)v;
  520. }
  521. /////////////////////////////////////////////////////////////////////////////
  522. //  CDB_DateTime::
  523. //
  524. EDB_Type CDB_DateTime::GetType() const
  525. {
  526.     return eDB_DateTime;
  527. }
  528. CDB_Object* CDB_DateTime::Clone() const
  529. {
  530.     return m_Null ? new CDB_DateTime : new CDB_DateTime(Value());
  531. }
  532. void CDB_DateTime::AssignValue(CDB_Object& v)
  533. {
  534.     if(v.GetType() != eDB_DateTime) {
  535.         throw CDB_ClientEx(eDB_Error, 2, "CDB_DateTime::AssignValue",
  536.                            "wrong type of CDB_Object");
  537.     }
  538.     *this= (CDB_DateTime&)v;
  539. }
  540. /////////////////////////////////////////////////////////////////////////////
  541. //  CDB_Bit::
  542. //
  543. EDB_Type CDB_Bit::GetType() const
  544. {
  545.     return eDB_Bit;
  546. }
  547. CDB_Object* CDB_Bit::Clone() const
  548. {
  549.     return m_Null ? new CDB_Bit : new CDB_Bit(m_Val ? 1 : 0);
  550. }
  551. void CDB_Bit::AssignValue(CDB_Object& v)
  552. {
  553.     if(v.GetType() != eDB_Bit) {
  554.         throw CDB_ClientEx(eDB_Error, 2, "CDB_Bit::AssignValue",
  555.                            "wrong type of CDB_Object");
  556.     }
  557.     *this= (CDB_Bit&)v;
  558. }
  559. /////////////////////////////////////////////////////////////////////////////
  560. //
  561. //  CDB_Numeric::
  562. //
  563. EDB_Type CDB_Numeric::GetType() const
  564. {
  565.     return eDB_Numeric;
  566. }
  567. CDB_Object* CDB_Numeric::Clone() const
  568. {
  569.     return new CDB_Numeric((unsigned int) m_Precision,
  570.                            (unsigned int) m_Scale, m_Body);
  571. }
  572. static int s_NumericBytesPerPrec[] =
  573. {
  574.     2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9,
  575.     10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15,
  576.     16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21,
  577.     22, 22, 23, 23, 24, 24, 24, 25, 25, 26, 26, 26
  578. };
  579. static const unsigned int kMaxPrecision = 50;
  580. static void s_DoCarry(unsigned char* product)
  581. {
  582.     for (unsigned int j = 0;  j < kMaxPrecision;  j++) {
  583.         if (product[j] > 9) {
  584.             product[j + 1] += product[j] / 10;
  585.             product[j]     %= 10;
  586.         }
  587.     }
  588. }
  589. static void s_MultiplyByte(unsigned char* product, int num,
  590.                            const unsigned char* multiplier)
  591. {
  592.     unsigned char number[3];
  593.     number[0] =  num        % 10;
  594.     number[1] = (num /  10) % 10;
  595.     number[2] = (num / 100) % 10;
  596.     int top;
  597.     for (top = kMaxPrecision - 1;  top >= 0  &&  !multiplier[top];  top--)
  598.         continue;
  599.     int start = 0;
  600.     for (int i = 0;  i <= top;  i++) {
  601.         for (int j =0;  j < 3;  j++) {
  602.             product[j + start] += multiplier[i] * number[j];
  603.         }
  604.         s_DoCarry(product);
  605.         start++;
  606.     }
  607. }
  608. static char* s_ArrayToString(const unsigned char* array, int scale, char* s)
  609. {
  610.     int top;
  611.     for (top = kMaxPrecision - 1;  top >= 0  &&  top > scale  &&  !array[top];
  612.          top--)
  613.         continue;
  614.     if (top == -1) {
  615.         s[0] = '0';
  616.         s[1] = '';
  617.         return s;
  618.     }
  619.     int j = 0;
  620.     for (int i = top;  i >= 0;  i--) {
  621.         if (top + 1 - j == scale)
  622.             s[j++] = '.';
  623.         s[j++] = array[i] + '0';
  624.     }
  625.     s[j] = '';
  626.     return s;
  627. }
  628. string CDB_Numeric::Value() const
  629. {
  630.     unsigned char multiplier[kMaxPrecision];
  631.     unsigned char temp[kMaxPrecision];
  632.     unsigned char product[kMaxPrecision];
  633.     char result[kMaxPrecision + 1];
  634.     char* s = result;
  635.     int num_bytes;
  636.     memset(multiplier, 0, kMaxPrecision);
  637.     memset(product,    0, kMaxPrecision);
  638.     multiplier[0] = 1;
  639.     num_bytes = s_NumericBytesPerPrec[m_Precision-1];
  640.     if (m_Body[0] == 1) {
  641.         *s++ = '-';
  642.     }
  643.     for (int pos = num_bytes - 1;  pos > 0;  pos--) {
  644.         s_MultiplyByte(product, m_Body[pos], multiplier);
  645.         memcpy(temp, multiplier, kMaxPrecision);
  646.         memset(multiplier, 0, kMaxPrecision);
  647.         s_MultiplyByte(multiplier, 256, temp);
  648.     }
  649.     s_ArrayToString(product, m_Scale, s);
  650.     return result;
  651. }
  652. static int s_NextValue(const char** s, int rem, int base)
  653. {
  654.     while (**s < base) {
  655.         rem = rem * base + (int) **s;
  656.         (*s)++;
  657.         if (rem >= 256)
  658.             break;
  659.     }
  660.     return rem;
  661. }
  662. static int s_Div256(const char* value, char* product, int base)
  663. {
  664.     int res = 0;
  665.     int n;
  666.     while (*value < base) {
  667.         n = s_NextValue(&value, res, base);
  668.         *product = (char) (n / 256);
  669.         res = n % 256;
  670.         ++product;
  671.     }
  672.     *product = base;
  673.     return res;
  674. }
  675. void CDB_Numeric::x_MakeFromString(unsigned int precision, unsigned int scale,
  676.                                    const char* val)
  677. {
  678.     if (m_Precision == 0  &&  precision == 0  &&  val) {
  679.         precision= (unsigned int) strlen(val);
  680.         if (scale == 0) {
  681.             scale= precision - (Uint1) strcspn(val, ".");
  682.             if (scale > 1)
  683.                 --scale;
  684.         }
  685.     }
  686.     if (!precision  ||  precision > kMaxPrecision) {
  687.         throw CDB_ClientEx(eDB_Error, 100, "CDB_Numeric::x_MakeFromString",
  688.                            "illegal precision");
  689.     }
  690.     if (scale > precision) {
  691.         throw CDB_ClientEx(eDB_Error, 101, "CDB_Numeric::x_MakeFromString",
  692.                            "scale can not be more than precision");
  693.     }
  694.     bool is_negative= false;
  695.     if(*val == '-') {
  696.         is_negative= true;
  697.         ++val;
  698.     }
  699.     while (*val == '0') {
  700.         ++val;
  701.     }
  702.     char buff1[kMaxPrecision + 1];
  703.     unsigned int n = 0;
  704.     while (*val  &&  n < precision) {
  705.         if (*val >= '0'  &&  *val <= '9') {
  706.             buff1[n++] = *val - '0';
  707.         } else if (*val == '.') {
  708.             break;
  709.         } else {
  710.             throw CDB_ClientEx(eDB_Error, 102, "CDB_Numeric::x_MakeFromString",
  711.                                "string can not be converted");
  712.         }
  713.         ++val;
  714.     }
  715.     if (precision - n < scale) {
  716.         throw CDB_ClientEx(eDB_Error, 103, "CDB_Numeric::x_MakeFromString",
  717.                            "string can not be converted because of overflow");
  718.     }
  719.     unsigned int dec = 0;
  720.     if (*val == '.') {
  721.         ++val;
  722.         while (*val  &&  dec < scale) {
  723.             if (*val >= '0'  &&  *val <= '9') {
  724.                 buff1[n++] = *val - '0';
  725.             } else {
  726.                 throw CDB_ClientEx(eDB_Error, 102,
  727.                                    "CDB_Numeric::x_MakeFromString",
  728.                                    "string can not be converted");
  729.             }
  730.             ++dec;
  731.             ++val;
  732.         }
  733.     }
  734.     while (dec++ < scale) {
  735.         buff1[n++] = 0;
  736.     }
  737.     if (n == 0) {
  738.         buff1[n++] = 0;
  739.     }
  740.     buff1[n] = 10;
  741.     char  buff2[kMaxPrecision + 1];
  742.     char* p[2];
  743.     p[0] = buff1;
  744.     p[1] = buff2;
  745.     // Setup everything now
  746.     memset(m_Body, 0, sizeof(m_Body));
  747.     if (is_negative) {
  748.         m_Body[0] = 1/*sign*/;
  749.     }
  750.     unsigned char* num = m_Body + s_NumericBytesPerPrec[precision - 1] - 1;
  751.     for (int i = 0;  *p[i];  i = 1 - i) {
  752.         *num = s_Div256(p[i], p[1-i], 10);
  753.         --num;
  754.     }
  755.     m_Precision = precision;
  756.     m_Scale     = scale;
  757.     m_Null      = false;
  758. }
  759. void CDB_Numeric::AssignValue(CDB_Object& v)
  760. {
  761.     if(v.GetType() != eDB_Numeric) {
  762.         throw CDB_ClientEx(eDB_Error, 2, "CDB_Numeric::AssignValue",
  763.                            "wrong type of CDB_Object");
  764.     }
  765.     *this= (CDB_Numeric&)v;
  766. }
  767. END_NCBI_SCOPE
  768. /*
  769.  * ===========================================================================
  770.  * $Log: types.cpp,v $
  771.  * Revision 1000.2  2004/06/01 19:19:28  gouriano
  772.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  773.  *
  774.  * Revision 1.17  2004/05/17 21:11:38  gorelenk
  775.  * Added include of PCH ncbi_pch.hpp
  776.  *
  777.  * Revision 1.16  2004/01/21 18:07:35  sapojnik
  778.  * AssignValue() for misc. int, float, double accepts less capable types; only no loss type conversions allowed
  779.  *
  780.  * Revision 1.15  2003/12/10 18:50:22  soussov
  781.  * fixes bug with null value flag in AssignValue methods for CDB_Char, CDB_Binary, CDB_LongChar, CDB_LongBinary
  782.  *
  783.  * Revision 1.14  2003/08/13 18:02:11  soussov
  784.  * fixes bug in Clone() for [Small]DateTime
  785.  *
  786.  * Revision 1.13  2003/05/13 16:54:40  sapojnik
  787.  * CDB_Object::Create() - support for LongChar, LongBinary
  788.  *
  789.  * Revision 1.12  2003/05/05 15:58:22  soussov
  790.  * fixed bug in Clone() method for CDB_Char, CDB_LongChar and CDB_LongBinary when NULL value is cloned
  791.  *
  792.  * Revision 1.11  2003/04/29 21:13:57  soussov
  793.  * new datatypes CDB_LongChar and CDB_LongBinary added
  794.  *
  795.  * Revision 1.10  2002/09/25 21:47:51  soussov
  796.  * adds check for not-empty append before dropping the Null flag in CDB_Stream
  797.  *
  798.  * Revision 1.9  2002/07/19 15:31:43  soussov
  799.  * add check for NULL pointer in CDB_Text::Append
  800.  *
  801.  * Revision 1.8  2002/05/16 21:29:38  soussov
  802.  * AssignValue methods added
  803.  *
  804.  * Revision 1.7  2002/02/14 00:59:42  vakatov
  805.  * Clean-up: warning elimination, fool-proofing, fine-tuning, identation, etc.
  806.  *
  807.  * Revision 1.6  2002/02/13 22:37:26  sapojnik
  808.  * new_CDB_Object() renamed to CDB_Object::create()
  809.  *
  810.  * Revision 1.5  2002/02/13 22:14:50  sapojnik
  811.  * new_CDB_Object() (needed for rdblib)
  812.  *
  813.  * Revision 1.4  2002/02/06 22:22:54  soussov
  814.  * fixes the string to numeric assignment
  815.  *
  816.  * Revision 1.3  2001/11/06 17:59:54  lavr
  817.  * Formatted uniformly as the rest of the library
  818.  *
  819.  * Revision 1.2  2001/09/24 20:38:52  soussov
  820.  * fixed bug in sign processing
  821.  *
  822.  * Revision 1.1  2001/09/21 23:40:00  vakatov
  823.  * -----  Initial (draft) revision.  -----
  824.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  825.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  826.  * The revamp involved massive code shuffling and grooming, numerous local
  827.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  828.  *
  829.  * ===========================================================================
  830.  */