Panda3D
compress_string.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file compress_string.cxx
10  * @author drose
11  * @date 2009-08-09
12  */
13 
14 #include "compress_string.h"
15 
16 #ifdef HAVE_ZLIB
17 #include "zStream.h"
18 #include "virtualFileSystem.h"
19 #include "config_express.h"
20 
21 using std::istream;
22 using std::istringstream;
23 using std::ostream;
24 using std::ostringstream;
25 using std::string;
26 
27 /**
28  * Compress the indicated source string at the given compression level (1
29  * through 9). Returns the compressed string.
30  */
31 string
32 compress_string(const string &source, int compression_level) {
33  ostringstream dest;
34 
35  {
36  OCompressStream compress;
37  compress.open(&dest, false, compression_level);
38  compress.write(source.data(), source.length());
39 
40  if (compress.fail()) {
41  return string();
42  }
43  }
44 
45  return dest.str();
46 }
47 
48 /**
49  * Decompresss the previously-compressed string()). The return value is the
50  * decompressed string.
51  *
52  * Note that a decompression error cannot easily be detected, and the return
53  * value may simply be a garbage or truncated string.
54  */
55 string
56 decompress_string(const string &source) {
57  istringstream source_stream(source);
58  ostringstream dest_stream;
59 
60  if (!decompress_stream(source_stream, dest_stream)) {
61  return string();
62  }
63 
64  return dest_stream.str();
65 }
66 
67 /**
68  * Compresss the data from the source file at the given compression level (1
69  * through 9). The source file is read in its entirety, and the compressed
70  * results are written to the dest file, overwriting its contents. The return
71  * value is bool on success, or false on failure.
72  */
73 EXPCL_PANDA_EXPRESS bool
74 compress_file(const Filename &source, const Filename &dest, int compression_level) {
76  Filename source_filename = source;
77  if (!source_filename.is_binary_or_text()) {
78  // The default is binary, if not specified otherwise.
79  source_filename.set_binary();
80  }
81  istream *source_stream = vfs->open_read_file(source_filename, false);
82  if (source_stream == nullptr) {
83  express_cat.info() << "Couldn't open file " << source_filename << "\n";
84  return false;
85  }
86 
87  Filename dest_filename = Filename::binary_filename(dest);
88  ostream *dest_stream = vfs->open_write_file(dest_filename, false, true);
89  if (dest_stream == nullptr) {
90  express_cat.info() << "Couldn't open file " << dest_filename << "\n";
91  vfs->close_read_file(source_stream);
92  return false;
93  }
94 
95  bool result = compress_stream(*source_stream, *dest_stream, compression_level);
96  vfs->close_read_file(source_stream);
97  vfs->close_write_file(dest_stream);
98  return result;
99 }
100 
101 /**
102  * Decompresss the data from the source file. The source file is read in its
103  * entirety, and the decompressed results are written to the dest file,
104  * overwriting its contents. The return value is bool on success, or false on
105  * failure.
106  *
107  * Note that a decompression error cannot easily be detected, and the output
108  * may simply be a garbage or truncated string.
109  */
110 EXPCL_PANDA_EXPRESS bool
111 decompress_file(const Filename &source, const Filename &dest) {
112  Filename source_filename = Filename::binary_filename(source);
114  istream *source_stream = vfs->open_read_file(source_filename, false);
115  if (source_stream == nullptr) {
116  express_cat.info() << "Couldn't open file " << source_filename << "\n";
117  return false;
118  }
119 
120  Filename dest_filename = dest;
121  if (!dest_filename.is_binary_or_text()) {
122  // The default is binary, if not specified otherwise.
123  dest_filename.set_binary();
124  }
125  ostream *dest_stream = vfs->open_write_file(dest_filename, false, true);
126  if (dest_stream == nullptr) {
127  express_cat.info() << "Couldn't open file " << dest_filename << "\n";
128  vfs->close_read_file(source_stream);
129  return false;
130  }
131 
132  bool result = decompress_stream(*source_stream, *dest_stream);
133  vfs->close_read_file(source_stream);
134  vfs->close_write_file(dest_stream);
135  return result;
136 }
137 
138 /**
139  * Compresss the data from the source stream at the given compression level (1
140  * through 9). The source stream is read from its current position to the
141  * end-of-file, and the compressed results are written to the dest stream.
142  * The return value is bool on success, or false on failure.
143  */
144 bool
145 compress_stream(istream &source, ostream &dest, int compression_level) {
146  OCompressStream compress;
147  compress.open(&dest, false, compression_level);
148 
149  static const size_t buffer_size = 4096;
150  char buffer[buffer_size];
151 
152  source.read(buffer, buffer_size);
153  size_t count = source.gcount();
154  while (count != 0) {
155  compress.write(buffer, count);
156  source.read(buffer, buffer_size);
157  count = source.gcount();
158  }
159  compress.close();
160 
161  return (!source.fail() || source.eof()) && (!compress.fail());
162 }
163 
164 /**
165  * Decompresss the data from the previously-compressed source stream. The
166  * source stream is read from its current position to the end-of-file, and the
167  * decompressed results are written to the dest stream. The return value is
168  * bool on success, or false on failure.
169  *
170  * Note that a decompression error cannot easily be detected, and the output
171  * may simply be a garbage or truncated string.
172  */
173 bool
174 decompress_stream(istream &source, ostream &dest) {
175  IDecompressStream decompress(&source, false);
176 
177  static const size_t buffer_size = 4096;
178  char buffer[buffer_size];
179 
180  decompress.read(buffer, buffer_size);
181  size_t count = decompress.gcount();
182  while (count != 0) {
183  dest.write(buffer, count);
184  decompress.read(buffer, buffer_size);
185  count = decompress.gcount();
186  }
187 
188  return (!decompress.fail() || decompress.eof()) && (!dest.fail());
189 }
190 
191 #endif // HAVE_ZLIB
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A hierarchy of directories and files that appears to be one continuous file system,...
std::istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read,...
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
static void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
std::ostream * open_write_file(const Filename &filename, bool auto_wrap, bool truncate)
Convenience function; returns a newly allocated ostream if the file exists and can be written,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_binary_or_text() const
Returns true either is_binary() or is_text() is true; that is, that the filename has been specified a...
Definition: filename.I:445