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
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
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
A hierarchy of directories and files that appears to be one continuous file system,...
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,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
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,...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.