1 /*  $Id: compress.cpp 538813 2017-06-14 12:15:14Z 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  * Authors:  Vladimir Ivanov
27  *
28  * File Description:  The Compression API
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbi_limits.h>
34 #include <util/compress/compress.hpp>
35 
36 
37 BEGIN_NCBI_SCOPE
38 
39 
40 //////////////////////////////////////////////////////////////////////////////
41 //
42 // CCompression
43 //
44 
CCompression(ELevel level)45 CCompression::CCompression(ELevel level)
46     : m_DecompressMode(eMode_Unknown),
47       m_Level(level), m_ErrorCode(0), m_ErrorMsg(kEmptyStr), m_Flags(0)
48 {
49     return;
50 }
51 
52 
~CCompression(void)53 CCompression::~CCompression(void)
54 {
55     return;
56 }
57 
58 
GetLevel(void) const59 CCompression::ELevel CCompression::GetLevel(void) const
60 {
61     if ( m_Level == eLevel_Default) {
62         return GetDefaultLevel();
63     }
64     return m_Level;
65 }
66 
67 
SetLevel(ELevel level)68 void CCompression::SetLevel(ELevel level)
69 {
70     m_Level = level;
71 }
72 
73 
GetErrorCode(void) const74 int CCompression::GetErrorCode(void) const
75 {
76     return m_ErrorCode;
77 }
78 
79 
GetErrorDescription(void) const80 string CCompression::GetErrorDescription(void) const
81 {
82     return m_ErrorMsg;
83 }
84 
85 
SetError(int errcode,const char * description)86 void CCompression::SetError(int errcode, const char* description)
87 {
88     m_ErrorCode = errcode;
89     m_ErrorMsg  = description ? description : kEmptyStr;
90 }
91 
92 
SetError(int errcode,const string & description)93 void CCompression::SetError(int errcode, const string& description)
94 {
95     m_ErrorCode = errcode;
96     m_ErrorMsg  = description;
97 }
98 
99 
GetFlags(void) const100 CCompression::TFlags CCompression::GetFlags(void) const
101 {
102     return m_Flags;
103 }
104 
105 
SetFlags(TFlags flags)106 void CCompression::SetFlags(TFlags flags)
107 {
108     m_Flags = flags;
109 }
110 
111 
x_CompressFile(const string & src_file,CCompressionFile & dst_file,size_t buf_size)112 bool CCompression::x_CompressFile(const string&     src_file,
113                                   CCompressionFile& dst_file,
114                                   size_t            buf_size)
115 {
116     if ( !buf_size ) {
117         SetError(-1, "Buffer size cannot be zero");
118         return false;
119     }
120     _ASSERT(buf_size <= kMax_Int);
121 
122     CNcbiIfstream is(src_file.c_str(), IOS_BASE::in | IOS_BASE::binary);
123     if ( !is.good() ) {
124         SetError(-1, "Cannot open source file");
125         return false;
126     }
127     AutoPtr<char, ArrayDeleter<char> > buf(new char[buf_size]);
128     while ( is ) {
129         is.read(buf.get(), buf_size);
130         size_t nread = (size_t)is.gcount();
131         size_t nwritten = dst_file.Write(buf.get(), nread);
132         if ( nwritten != nread ) {
133             return false;
134         }
135     }
136     return true;
137 }
138 
139 
x_DecompressFile(CCompressionFile & src_file,const string & dst_file,size_t buf_size)140 bool CCompression::x_DecompressFile(CCompressionFile& src_file,
141                                     const string&     dst_file,
142                                     size_t            buf_size)
143 {
144     if ( !buf_size ) {
145         SetError(-1, "Buffer size cannot be zero");
146         return false;
147     }
148     if ( buf_size > kMax_Int ) {
149         buf_size = kMax_Int;
150     }
151     _ASSERT(buf_size <= kMax_Int);
152 
153     CNcbiOfstream os(dst_file.c_str(), IOS_BASE::out | IOS_BASE::binary);
154     if ( !os.good() ) {
155         SetError(-1, "Cannot open destination file");
156         return false;
157     }
158     AutoPtr<char, ArrayDeleter<char> > buf(new char[buf_size]);
159     long nread;
160     while ( (nread = src_file.Read(buf.get(), buf_size)) > 0 ) {
161         os.write(buf.get(), nread);
162         if ( !os.good() ) {
163             SetError(-1, "Error writing to ouput file");
164             return false;
165         }
166     }
167     if ( nread == -1 ) {
168         return false;
169     }
170     return true;
171 }
172 
173 
174 
175 //////////////////////////////////////////////////////////////////////////////
176 //
177 // CCompressionProcessor
178 //
179 
CCompressionProcessor(void)180 CCompressionProcessor::CCompressionProcessor(void)
181 {
182     Reset();
183     return;
184 }
185 
186 
~CCompressionProcessor(void)187 CCompressionProcessor::~CCompressionProcessor(void)
188 {
189     return;
190 }
191 
192 
193 //////////////////////////////////////////////////////////////////////////////
194 //
195 // CCompressionFile
196 //
197 
CCompressionFile(void)198 CCompressionFile::CCompressionFile(void)
199     : m_File(0), m_Mode(eMode_Read)
200 {
201     return;
202 }
203 
204 
~CCompressionFile(void)205 CCompressionFile::~CCompressionFile(void)
206 {
207     return;
208 }
209 
210 
211 
212 //////////////////////////////////////////////////////////////////////////////
213 //
214 // CCompressionUtil
215 //
216 
StoreUI4(void * buffer,unsigned long value)217 void CCompressionUtil::StoreUI4(void* buffer, unsigned long value)
218 {
219     if ( !buffer ) {
220         NCBI_THROW(CCoreException, eInvalidArg, "Incorrect buffer pointer");
221     }
222     if ( value > kMax_UI4 ) {
223         NCBI_THROW(CCoreException, eInvalidArg,
224                    "Stored value exceeded maximum size for Uint4 type");
225     }
226     unsigned char* buf = (unsigned char*)buffer;
227     for (int i = 0; i < 4; i++) {
228         buf[i] = (unsigned char)(value & 0xff);
229         value >>= 8;
230     }
231 }
232 
GetUI4(const void * buffer)233 Uint4 CCompressionUtil::GetUI4(const void* buffer)
234 {
235     if ( !buffer ) {
236         NCBI_THROW(CCoreException, eInvalidArg, "Incorrect buffer pointer");
237     }
238     const unsigned char* buf = (const unsigned char*)buffer;
239     Uint4 value = 0;
240     for (int i = 3; i >= 0; i--) {
241         value <<= 8;
242         value += buf[i];
243     }
244     return value;
245 }
246 
StoreUI2(void * buffer,unsigned long value)247 void CCompressionUtil::StoreUI2(void* buffer, unsigned long value)
248 {
249     if ( !buffer ) {
250         NCBI_THROW(CCoreException, eInvalidArg, "Incorrect buffer pointer");
251     }
252     if ( value > kMax_UI2 ) {
253         NCBI_THROW(CCoreException, eInvalidArg,
254                    "Stored value exceeded maximum size for Uint2 type");
255     }
256     unsigned char* buf = (unsigned char*)buffer;
257     buf[0] = (unsigned char)(value & 0xff);
258     value >>= 8;
259     buf[1] = (unsigned char)(value & 0xff);
260 }
261 
GetUI2(const void * buffer)262 Uint2 CCompressionUtil::GetUI2(const void* buffer)
263 {
264     if ( !buffer ) {
265         NCBI_THROW(CCoreException, eInvalidArg, "Incorrect buffer pointer");
266     }
267     const unsigned char* buf = (const unsigned char*)buffer;
268     return Uint2(((Uint2)(buf[1]) << 8) + buf[0]);
269 }
270 
271 
272 END_NCBI_SCOPE
273