zipios 2.2.0
Zipios -- a small C++ library that provides easy access to .zip files.
zipoutputstreambuf.cpp
Go to the documentation of this file.
1/*
2 Zipios -- a small C++ library that provides easy access to .zip files.
3
4 Copyright (C) 2000-2007 Thomas Sondergaard
5 Copyright (C) 2015-2019 Made to Order Software Corporation
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
30
32
33#include "ziplocalentry.hpp"
35
36
37namespace zipios
38{
39
40
41namespace
42{
43
44
56void writeZipCentralDirectory(std::ostream &os, FileEntry::vector_t& entries, std::string const& comment)
57{
58 ZipEndOfCentralDirectory eocd(comment);
59 eocd.setOffset(os.tellp()); // start position
60 eocd.setCount(entries.size());
61
62 size_t central_directory_size(0);
63 for(auto it = entries.begin(); it != entries.end(); ++it)
64 {
65 (*it)->write(os);
66 central_directory_size += (*it)->getHeaderSize();
67 }
68
69 eocd.setCentralDirectorySize(central_directory_size);
70 eocd.write(os);
71}
72
73
74} // no name namespace
75
76
94 //, m_zip_comment("") -- auto-init
95 //, m_entries() -- auto-init
96 //, m_compression_level(FileEntry::COMPRESSION_LEVEL_DEFAULT) -- auto-init
97 //, m_open_entry(false) -- auto-init
98 //, m_open(true) -- auto-init
99{
100}
101
102
117{
118 // avoid possible exceptions when writing the central directory
119 try
120 {
121 finish();
122 }
123 catch(...)
124 {
125 }
126}
127
128
135{
136 if(!m_open_entry)
137 {
138 return;
139 }
140
141 switch(m_compression_level)
142 {
144 overflow(); // flush
145 break;
146
147 default:
148 closeStream();
149 break;
150
151 }
152
155}
156
157
164{
165 finish();
166}
167
168
177{
178 if(!m_open)
179 {
180 return;
181 }
182 m_open = false;
183
184 std::ostream os(m_outbuf);
185 closeEntry();
186 writeZipCentralDirectory(os, m_entries, m_zip_comment);
187}
188
189
201{
202 closeEntry();
203
204 // if the method is STORED force uncompressed data
205 if(entry->getMethod() == StorageMethod::STORED)
206 {
207 // force to "no compression" when the method is STORED
209 }
210 else
211 {
212 // get the user defined compression level
213 m_compression_level = entry->getLevel();
214 }
216 switch(m_compression_level)
217 {
219 setp(&m_invec[0], &m_invec[0] + getBufferSize());
220 break;
221
222 default:
224 break;
225
226 }
227
228 m_entries.push_back(entry);
229
230 std::ostream os(m_outbuf);
231
232 // Update entry header info
233 entry->setEntryOffset(os.tellp());
238 static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
239
240 m_open_entry = true;
241}
242
243
256void ZipOutputStreambuf::setComment(std::string const& comment)
257{
258 m_zip_comment = comment;
259}
260
261
262//
263// Protected and private methods
264//
265
277{
278 size_t const size(pptr() - pbase());
279 m_overflown_bytes += size;
280 switch(m_compression_level)
281 {
283 {
284 // Ok, we are STORED, so we handle it ourselves to avoid "side
285 // effects" from zlib, which adds markers every now and then.
286 size_t const bc(m_outbuf->sputn(&m_invec[0], size));
287 if(size != bc)
288 {
289 // Without implementing our own stream in our test, this
290 // cannot really be reached because it is all happening
291 // inside the same loop in ZipFile::saveCollectionToArchive()
292 throw IOException("ZipOutputStreambuf::overflow(): write to buffer failed."); // LCOV_EXCL_LINE
293 }
294 setp(&m_invec[0], &m_invec[0] + getBufferSize());
295
296 if(c != EOF)
297 {
298 *pptr() = c;
299 pbump(1);
300 }
301
302 return 0;
303 }
304
305 default:
307
308 }
309}
310
311
312
321int ZipOutputStreambuf::sync() // LCOV_EXCL_LINE
322{
323 return DeflateOutputStreambuf::sync(); // LCOV_EXCL_LINE
324}
325
326
327
343
344
357{
358 if(!m_open_entry)
359 {
360 return;
361 }
362
363 std::ostream os(m_outbuf);
364 int const curr_pos(os.tellp());
365
366 // update fields in m_entries.back()
367 FileEntry::pointer_t entry(m_entries.back());
368 entry->setSize(getSize());
369 entry->setCrc(getCrc32());
374 entry->setCompressedSize(curr_pos - entry->getEntryOffset() - static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::getHeaderSize());
375
376 // write ZipLocalEntry header to header position
377 os.seekp(entry->getEntryOffset());
382 static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
383 os.seekp(curr_pos);
384}
385
386
387} // zipios namespace
388
389// Local Variables:
390// mode: cpp
391// indent-tabs-mode: nil
392// c-basic-offset: 4
393// tab-width: 4
394// End:
395
396// vim: ts=4 sw=4 et
A class to handle stream deflate on the fly.
bool init(FileEntry::CompressionLevel compression_level)
Initialize the zlib library.
uint32_t getCrc32() const
Get the CRC32 of the file.
virtual int sync()
Synchronize the buffer.
virtual int overflow(int c=EOF)
Handle an overflow.
size_t getSize() const
Retrieve the size of the file deflated.
std::vector< pointer_t > vector_t
Definition fileentry.hpp:79
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition fileentry.hpp:90
std::shared_ptr< FileEntry > pointer_t
Definition fileentry.hpp:78
An IOException is used to signal an I/O error.
Marker at the end of a Zip archive file.
void setOffset(offset_t new_offset)
Offset of the Central Directory.
void write(std::ostream &os)
Write the ZipEndOfCentralDirectory structure to a stream.
void setCentralDirectorySize(size_t size)
Define the size of the central directory.
void setCount(size_t c)
Set the number of entries.
An implementation of the FileEntry for Zip archives.
void setComment(std::string const &comment)
Set the archive comment.
ZipOutputStreambuf(std::streambuf *outbuf)
Initialize a ZipOutputStreambuf object.
virtual ~ZipOutputStreambuf()
Clean up the buffer.
void close()
Close the output stream buffer.
void putNextEntry(FileEntry::pointer_t entry)
Start saving an entry in the output buffer.
void closeEntry()
Close this buffer entry.
FileEntry::CompressionLevel m_compression_level
virtual int sync() override
Implement the sync() functionality.
void updateEntryHeaderInfo()
Save the header information.
virtual int overflow(int c=EOF) override
Implementation of the overflow() function.
void finish()
Finish up an output stream buffer.
void setEntryClosedState()
Mark the current entry as closed.
void writeZipCentralDirectory(std::ostream &os, FileEntry::vector_t &entries, std::string const &comment)
Help function used to write the central directory.
The zipios namespace includes the Zipios library definitions.
size_t getBufferSize()
Declaration of the zipios::ZipEndOfCentralDirectory class.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
Declare the zipios::ZipLocalEntry class used to handle Zip entries.
Define the zipios::ZipOutputStreambuf class.