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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: reader_zlib.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:41:00  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: reader_zlib.cpp,v 1000.2 2004/06/01 19:41:00 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: byte reader with gzip decompression
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include <util/compress/reader_zlib.hpp>
  39. #include <util/compress/compress.hpp>
  40. #include <corelib/ncbitime.hpp>
  41. #include <util/compress/zlib.hpp>
  42. BEGIN_NCBI_SCOPE
  43. BEGIN_SCOPE(objects)
  44. class NCBI_XUTIL_EXPORT CResultZBtSrcX
  45. {
  46. public:
  47.     CResultZBtSrcX(CByteSourceReader* reader);
  48.     ~CResultZBtSrcX(void);
  49.     size_t Read(char* buffer, size_t bufferLength);
  50.     void ReadLength(void);
  51.     size_t x_Read(char* buffer, size_t bufferLength);
  52.     size_t GetCompressedSize(void) const
  53.         {
  54.             return m_CompressedSize;
  55.         }
  56.     double GetDecompressionTime(void) const
  57.         {
  58.             return m_DecompressionTime;
  59.         }
  60.     enum {
  61.         kMax_UncomprSize = 1024*1024,
  62.         kMax_ComprSize = 1024*1024
  63.     };
  64. private:
  65.     CResultZBtSrcX(const CResultZBtSrcX&);
  66.     const CResultZBtSrcX& operator=(const CResultZBtSrcX&);
  67.     CRef<CByteSourceReader> m_Src;
  68.     vector<char>      m_Buffer;
  69.     size_t            m_BufferPos;
  70.     size_t            m_BufferEnd;
  71.     CZipCompression   m_Decompressor;
  72.     vector<char>      m_Compressed;
  73.     size_t            m_CompressedSize;
  74.     double            m_DecompressionTime;
  75. };
  76. CNlmZipBtRdr::CNlmZipBtRdr(CByteSourceReader* src)
  77.     : m_Src(src), m_Type(eType_unknown),
  78.       m_TotalReadTime(0)
  79. {
  80. }
  81. CNlmZipBtRdr::~CNlmZipBtRdr()
  82. {
  83. }
  84. size_t CNlmZipBtRdr::Read(char* buffer, size_t buffer_length)
  85. {
  86.     CStopWatch sw;
  87.     if ( 1 ) {
  88.         sw.Start();
  89.     }
  90.     EType type = m_Type;
  91.     if ( type == eType_plain ) {
  92.         size_t ret = m_Src->Read(buffer, buffer_length);
  93.         if ( 1 ) {
  94.             m_TotalReadTime += sw.Elapsed();
  95.         }
  96.         return ret;
  97.     }
  98.     if ( type == eType_unknown ) {
  99.         const size_t kHeaderSize = 4;
  100.         if ( buffer_length < kHeaderSize) {
  101.             NCBI_THROW(CCompressionException, eCompression,
  102.                        "Too small buffer to determine compression type");
  103.         }
  104.         const char* header = buffer;
  105.         size_t got_already = 0;
  106.         do {
  107.             size_t need_more = kHeaderSize - got_already;
  108.             size_t cnt = m_Src->Read(buffer, need_more);
  109.             buffer += cnt;
  110.             got_already += cnt;
  111.             buffer_length -= cnt;
  112.             if ( cnt == 0 || memcmp(header, "ZIP", got_already) != 0 ) {
  113.                 // too few bytes - assume non "ZIP"
  114.                 // or header is not "ZIP"
  115.                 _TRACE("CNlmZipBtRdr: non-ZIP: " << got_already);
  116.                 m_Type = eType_plain;
  117.                 if ( 1 ) {
  118.                     m_TotalReadTime += sw.Elapsed();
  119.                 }
  120.                 return got_already;
  121.             }
  122.         } while ( got_already != kHeaderSize );
  123.         // "ZIP"
  124.         m_Type = eType_zlib;
  125.         // reset buffer
  126.         buffer -= kHeaderSize;
  127.         buffer_length += kHeaderSize;
  128.         m_Decompressor.reset(new CResultZBtSrcX(m_Src));
  129.     }
  130.     size_t ret = m_Decompressor->Read(buffer, buffer_length);
  131.     if ( 1 ) {
  132.         m_TotalReadTime += sw.Elapsed();
  133.     }
  134.     return ret;
  135. }
  136. size_t CNlmZipBtRdr::GetCompressedSize(void) const
  137. {
  138.     return m_Decompressor.get()? m_Decompressor->GetCompressedSize(): 0;
  139. }
  140. double CNlmZipBtRdr::GetDecompressionTime(void) const
  141. {
  142.     return m_Decompressor.get()? m_Decompressor->GetDecompressionTime(): 0.;
  143. }
  144. CResultZBtSrcX::CResultZBtSrcX(CByteSourceReader* src)
  145.     : m_Src(src), m_BufferPos(0), m_BufferEnd(0),
  146.       m_CompressedSize(0), m_DecompressionTime(0)
  147. {
  148.     m_Decompressor.SetFlags(m_Decompressor.fCheckFileHeader |
  149.                             m_Decompressor.GetFlags());
  150. }
  151. CResultZBtSrcX::~CResultZBtSrcX(void)
  152. {
  153. }
  154. size_t CResultZBtSrcX::x_Read(char* buffer, size_t buffer_length)
  155. {
  156.     size_t ret = 0;
  157.     while ( buffer_length > 0 ) {
  158.         size_t cnt = m_Src->Read(buffer, buffer_length);
  159.         if ( cnt == 0 ) {
  160.             break;
  161.         }
  162.         else {
  163.             buffer_length -= cnt;
  164.             buffer += cnt;
  165.             ret += cnt;
  166.         }
  167.     }
  168.     return ret;
  169. }
  170. void CResultZBtSrcX::ReadLength(void)
  171. {
  172.     char header[8];
  173.     if ( x_Read(header, 8) != 8 ) {
  174.         NCBI_THROW(CCompressionException, eCompression,
  175.                    "Too few header bytes");
  176.     }
  177.     unsigned int compr_size = 0;
  178.     for ( size_t i = 0; i < 4; ++i ) {
  179.         compr_size = (compr_size<<8) | (unsigned char)header[i];
  180.     }
  181.     unsigned int uncompr_size = 0;
  182.     for ( size_t i = 4; i < 8; ++i ) {
  183.         uncompr_size = (uncompr_size<<8) | (unsigned char)header[i];
  184.     }
  185.     if ( compr_size > kMax_ComprSize ) {
  186.         NCBI_THROW(CCompressionException, eCompression,
  187.                    "Compressed size is too large");
  188.     }
  189.     if ( uncompr_size > kMax_UncomprSize ) {
  190.         NCBI_THROW(CCompressionException, eCompression,
  191.                    "Uncompressed size is too large");
  192.     }
  193.     m_Compressed.reserve(compr_size);
  194.     if ( x_Read(&m_Compressed[0], compr_size) != compr_size ) {
  195.         NCBI_THROW(CCompressionException, eCompression,
  196.                    "Compressed data is not complete");
  197.     }
  198.     m_BufferPos = m_BufferEnd;
  199.     m_Buffer.reserve(uncompr_size);
  200.     CStopWatch sw;
  201.     if ( 1 ) {
  202.         sw.Start();
  203.     }
  204.     if ( !m_Decompressor.DecompressBuffer(&m_Compressed[0], compr_size,
  205.                                           &m_Buffer[0], uncompr_size,
  206.                                           &uncompr_size) ) {
  207.         NCBI_THROW(CCompressionException, eCompression,
  208.                    "Decompression failed");
  209.     }
  210.     if ( 1 ) {
  211.         m_DecompressionTime += sw.Elapsed();
  212.     }
  213.     m_BufferEnd = uncompr_size;
  214.     m_BufferPos = 0;
  215.     m_CompressedSize += compr_size + 8;
  216. }
  217. size_t CResultZBtSrcX::Read(char* buffer, size_t buffer_length)
  218. {
  219.     while ( m_BufferPos >= m_BufferEnd ) {
  220.         ReadLength();
  221.     }
  222.     size_t cnt = min(buffer_length, m_BufferEnd - m_BufferPos);
  223.     memcpy(buffer, &m_Buffer[m_BufferPos], cnt);
  224.     m_BufferPos += cnt;
  225.     return cnt;
  226. }
  227. END_SCOPE(objects)
  228. END_NCBI_SCOPE
  229. /*
  230.  * ===========================================================================
  231.  * $Log: reader_zlib.cpp,v $
  232.  * Revision 1000.2  2004/06/01 19:41:00  gouriano
  233.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  234.  *
  235.  * Revision 1.4  2004/05/17 21:07:25  gorelenk
  236.  * Added include of PCH ncbi_pch.hpp
  237.  *
  238.  * Revision 1.3  2004/05/10 18:41:47  vasilche
  239.  * Added SetFlags() to skip gzip header.
  240.  *
  241.  * Revision 1.2  2004/04/07 16:16:17  ivanov
  242.  * Cosmeic changes. Fixed header and footer.
  243.  *
  244.  * Revision 1.1  2003/12/23 17:02:09  kuznets
  245.  * Moved from objmgr to util/compress
  246.  *
  247.  * Revision 1.10  2003/11/26 17:55:59  vasilche
  248.  * Implemented ID2 split in ID1 cache.
  249.  * Fixed loading of splitted annotations.
  250.  *
  251.  * Revision 1.9  2003/10/21 14:27:35  vasilche
  252.  * Added caching of gi -> sat,satkey,version resolution.
  253.  * SNP blobs are stored in cache in preprocessed format (platform dependent).
  254.  * Limit number of connections to GenBank servers.
  255.  * Added collection of ID1 loader statistics.
  256.  *
  257.  * Revision 1.8  2003/10/14 22:36:08  ucko
  258.  * Fix typo in last log message
  259.  *
  260.  * Revision 1.7  2003/10/14 22:35:51  ucko
  261.  * Remove initialization of CNlmZipBtRdr::m_CompressedSize (neither
  262.  * declared nor used anywhere)
  263.  *
  264.  * Revision 1.6  2003/10/14 21:06:25  vasilche
  265.  * Fixed compression statistics.
  266.  * Disabled caching of SNP blobs.
  267.  *
  268.  * Revision 1.5  2003/10/14 18:59:55  vasilche
  269.  * Temporarily remove collection of compression statistics.
  270.  *
  271.  * Revision 1.4  2003/10/14 18:31:55  vasilche
  272.  * Added caching support for SNP blobs.
  273.  * Added statistics collection of ID1 connection.
  274.  *
  275.  * Revision 1.3  2003/09/05 17:29:40  grichenk
  276.  * Structurized Object Manager exceptions
  277.  *
  278.  * Revision 1.2  2003/07/24 20:35:42  vasilche
  279.  * Added private constructor to make MSVC-DLL happy.
  280.  *
  281.  * Revision 1.1  2003/07/24 19:28:09  vasilche
  282.  * Implemented SNP split for ID1 loader.
  283.  *
  284.  * ===========================================================================
  285.  */