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