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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: pack_string.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:41:27  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: pack_string.cpp,v 1000.1 2004/06/01 19:41:27 gouriano Exp $
  10. * ===========================================================================
  11. *                            PUBLIC DOMAIN NOTICE
  12. *               National Center for Biotechnology Information
  13. *
  14. *  This software/database is a "United States Government Work" under the
  15. *  terms of the United States Copyright Act.  It was written as part of
  16. *  the author's official duties as a United States Government employee and
  17. *  thus cannot be copyrighted.  This software/database is freely available
  18. *  to the public for use. The National Library of Medicine and the U.S.
  19. *  Government have not placed any restriction on its use or reproduction.
  20. *
  21. *  Although all reasonable efforts have been taken to ensure the accuracy
  22. *  and reliability of the software and data, the NLM and the U.S.
  23. *  Government do not and cannot warrant the performance or results that
  24. *  may be obtained by using this software or data. The NLM and the U.S.
  25. *  Government disclaim all warranties, express or implied, including
  26. *  warranties of performance, merchantability or fitness for any particular
  27. *  purpose.
  28. *
  29. *  Please cite the author in any work or product based on this material.
  30. * ===========================================================================
  31. *
  32. *  Author:  Eugene Vasilchenko
  33. *
  34. *  File Description: Serialization hooks to make strings with equal value
  35. *                    to share representation object.
  36. *
  37. */
  38. #include <ncbi_pch.hpp>
  39. #include <serial/pack_string.hpp>
  40. #include <serial/objistr.hpp>
  41. #include <serial/objectiter.hpp>
  42. BEGIN_NCBI_SCOPE
  43. static const char* const STRING_PACK_ENV = "NCBI_SERIAL_PACK_STRINGS";
  44. static const char* const ENV_YES = "YES";
  45. static const size_t kDefaultLengthLimit = 32;
  46. static const size_t kDefaultCountLimit = 32;
  47. CPackString::CPackString(void)
  48.     : m_LengthLimit(kDefaultCountLimit), m_CountLimit(kDefaultCountLimit),
  49.       m_Skipped(0), m_CompressedIn(0),
  50.       m_CompressedOut(0)
  51. {
  52. }
  53. CPackString::CPackString(size_t length_limit, size_t count_limit)
  54.     : m_LengthLimit(length_limit), m_CountLimit(count_limit),
  55.       m_Skipped(0), m_CompressedIn(0),
  56.       m_CompressedOut(0)
  57. {
  58. }
  59. CPackString::~CPackString(void)
  60. {
  61. }
  62. CNcbiOstream& CPackString::DumpStatistics(CNcbiOstream& out) const
  63. {
  64.     size_t total = 0;
  65.     typedef multiset< pair<size_t, string> > TStat;
  66.     TStat stat;
  67.     ITERATE ( TStrings, i, m_Strings ) {
  68.         stat.insert(TStat::value_type(i->GetCount(), i->GetString()));
  69.         total += i->GetCount();
  70.     }
  71.     ITERATE ( TStat, i, stat ) {
  72.         out << setw(10) << i->first << " : "" << i->second << ""n";
  73.     }
  74.     out << setw(10) << total << " = " << m_CompressedIn << " -> " << m_CompressedOut << " stringsn";
  75.     out << setw(10) << m_Skipped << " skippedn";
  76.     return out;
  77. }
  78. bool CPackString::s_GetEnvFlag(const char* env, bool def_val)
  79. {
  80.     const char* val = ::getenv(env);
  81.     if ( !val ) {
  82.         return def_val;
  83.     }
  84.     string s(val);
  85.     return s == "1" || NStr::CompareNocase(s, ENV_YES) == 0;
  86. }
  87. bool CPackString::TryStringPack(void)
  88. {
  89.     static bool use_string_pack = s_GetEnvFlag(STRING_PACK_ENV, true);
  90.     if ( !use_string_pack ) {
  91.         return false;
  92.     }
  93.     string s1("test"), s2;
  94.     s1.c_str();
  95.     s2 = s1;
  96.     if ( s1.c_str() != s2.c_str() ) {
  97.         // strings don't use reference counters
  98.         return (use_string_pack = false);
  99.     }
  100.     return true;
  101. }
  102. void CPackString::x_RefCounterError(void)
  103. {
  104.     THROW1_TRACE(runtime_error,
  105.                  "CPackString: bad ref counting");
  106. }
  107. bool CPackString::x_Assign(string& s, const string& src)
  108. {
  109.     if ( TryStringPack() ) {
  110.         const_cast<string&>(src) = s;
  111.         s = src;
  112.         if ( s.c_str() != src.c_str() ) {
  113.             x_RefCounterError();
  114.         }
  115.         return true;
  116.     }
  117.     else {
  118.         return false;
  119.     }
  120. }
  121. bool CPackString::Pack(string& s)
  122. {
  123.     if ( s.size() <= GetLengthLimit() ) {
  124.         SNode key(s);
  125.         iterator iter = m_Strings.lower_bound(key);
  126.         bool found = iter != m_Strings.end() && *iter == key;
  127.         if ( found ) {
  128.             AddOld(s, iter);
  129.             return false;
  130.         }
  131.         else if ( GetCount() < GetCountLimit() ) {
  132.             iter = m_Strings.insert(iter, key);
  133.             ++m_CompressedOut;
  134.             iter->SetString(s);
  135.             AddOld(s, iter);
  136.             return true;
  137.         }
  138.     }
  139.     Skipped();
  140.     return false;
  141. }
  142. bool CPackString::Pack(string& s, const char* data, size_t size)
  143. {
  144.     if ( size <= GetLengthLimit() ) {
  145.         SNode key(data, size);
  146.         iterator iter = m_Strings.lower_bound(key);
  147.         bool found = iter != m_Strings.end() && *iter == key;
  148.         if ( found ) {
  149.             AddOld(s, iter);
  150.             return false;
  151.         }
  152.         else if ( GetCount() < GetCountLimit() ) {
  153.             iter = m_Strings.insert(iter, key);
  154.             ++m_CompressedOut;
  155.             iter->SetString();
  156.             AddOld(s, iter);
  157.             return true;
  158.         }
  159.     }
  160.     Skipped();
  161.     s.assign(data, size);
  162.     return false;
  163. }
  164. bool CPackString::AddNew(string& s, const char* data, size_t size,
  165.                          iterator iter)
  166. {
  167.     SNode key(data, size);
  168.     _ASSERT(size <= GetLengthLimit());
  169.     _ASSERT(iter == m_Strings.lower_bound(key));
  170.     _ASSERT(!(iter != m_Strings.end() && *iter == key));
  171.     if ( GetCount() < GetCountLimit() ) {
  172.         iter = m_Strings.insert(iter, key);
  173.         ++m_CompressedOut;
  174.         iter->SetString();
  175.         AddOld(s, iter);
  176.         return true;
  177.     }
  178.     Skipped();
  179.     s.assign(data, size);
  180.     return false;
  181. }
  182. CPackStringClassHook::CPackStringClassHook(void)
  183. {
  184. }
  185. CPackStringClassHook::CPackStringClassHook(size_t length_limit,
  186.                                            size_t count_limit)
  187.     : m_PackString(length_limit, count_limit)
  188. {
  189. }
  190. CPackStringClassHook::~CPackStringClassHook(void)
  191. {
  192. #if 0
  193.     NcbiCout << "CPackStringClassHook statistics:n" <<
  194.         m_PackString << NcbiEndl;
  195. #endif
  196. }
  197. CPackStringChoiceHook::CPackStringChoiceHook(void)
  198. {
  199. }
  200. CPackStringChoiceHook::CPackStringChoiceHook(size_t length_limit,
  201.                                              size_t count_limit)
  202.     : m_PackString(length_limit, count_limit)
  203. {
  204. }
  205. CPackStringChoiceHook::~CPackStringChoiceHook(void)
  206. {
  207. #if 0
  208.     NcbiCout << "CPackStringChoiceHook statistics:n" <<
  209.         m_PackString << NcbiEndl;
  210. #endif
  211. }
  212. END_NCBI_SCOPE