OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [zlib/] [contrib/] [iostream3/] [zfstream.cc] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 745 jeremybenn
/*
2
 * A C++ I/O streams interface to the zlib gz* functions
3
 *
4
 * by Ludwig Schwardt <schwardt@sun.ac.za>
5
 * original version by Kevin Ruland <kevin@rodin.wustl.edu>
6
 *
7
 * This version is standard-compliant and compatible with gcc 3.x.
8
 */
9
 
10
#include "zfstream.h"
11
#include <cstring>          // for strcpy, strcat, strlen (mode strings)
12
#include <cstdio>           // for BUFSIZ
13
 
14
// Internal buffer sizes (default and "unbuffered" versions)
15
#define BIGBUFSIZE BUFSIZ
16
#define SMALLBUFSIZE 1
17
 
18
/*****************************************************************************/
19
 
20
// Default constructor
21
gzfilebuf::gzfilebuf()
22
: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false),
23
  buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true)
24
{
25
  // No buffers to start with
26
  this->disable_buffer();
27
}
28
 
29
// Destructor
30
gzfilebuf::~gzfilebuf()
31
{
32
  // Sync output buffer and close only if responsible for file
33
  // (i.e. attached streams should be left open at this stage)
34
  this->sync();
35
  if (own_fd)
36
    this->close();
37
  // Make sure internal buffer is deallocated
38
  this->disable_buffer();
39
}
40
 
41
// Set compression level and strategy
42
int
43
gzfilebuf::setcompression(int comp_level,
44
                          int comp_strategy)
45
{
46
  return gzsetparams(file, comp_level, comp_strategy);
47
}
48
 
49
// Open gzipped file
50
gzfilebuf*
51
gzfilebuf::open(const char *name,
52
                std::ios_base::openmode mode)
53
{
54
  // Fail if file already open
55
  if (this->is_open())
56
    return NULL;
57
  // Don't support simultaneous read/write access (yet)
58
  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
59
    return NULL;
60
 
61
  // Build mode string for gzopen and check it [27.8.1.3.2]
62
  char char_mode[6] = "\0\0\0\0\0";
63
  if (!this->open_mode(mode, char_mode))
64
    return NULL;
65
 
66
  // Attempt to open file
67
  if ((file = gzopen(name, char_mode)) == NULL)
68
    return NULL;
69
 
70
  // On success, allocate internal buffer and set flags
71
  this->enable_buffer();
72
  io_mode = mode;
73
  own_fd = true;
74
  return this;
75
}
76
 
77
// Attach to gzipped file
78
gzfilebuf*
79
gzfilebuf::attach(int fd,
80
                  std::ios_base::openmode mode)
81
{
82
  // Fail if file already open
83
  if (this->is_open())
84
    return NULL;
85
  // Don't support simultaneous read/write access (yet)
86
  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
87
    return NULL;
88
 
89
  // Build mode string for gzdopen and check it [27.8.1.3.2]
90
  char char_mode[6] = "\0\0\0\0\0";
91
  if (!this->open_mode(mode, char_mode))
92
    return NULL;
93
 
94
  // Attempt to attach to file
95
  if ((file = gzdopen(fd, char_mode)) == NULL)
96
    return NULL;
97
 
98
  // On success, allocate internal buffer and set flags
99
  this->enable_buffer();
100
  io_mode = mode;
101
  own_fd = false;
102
  return this;
103
}
104
 
105
// Close gzipped file
106
gzfilebuf*
107
gzfilebuf::close()
108
{
109
  // Fail immediately if no file is open
110
  if (!this->is_open())
111
    return NULL;
112
  // Assume success
113
  gzfilebuf* retval = this;
114
  // Attempt to sync and close gzipped file
115
  if (this->sync() == -1)
116
    retval = NULL;
117
  if (gzclose(file) < 0)
118
    retval = NULL;
119
  // File is now gone anyway (postcondition [27.8.1.3.8])
120
  file = NULL;
121
  own_fd = false;
122
  // Destroy internal buffer if it exists
123
  this->disable_buffer();
124
  return retval;
125
}
126
 
127
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
128
 
129
// Convert int open mode to mode string
130
bool
131
gzfilebuf::open_mode(std::ios_base::openmode mode,
132
                     char* c_mode) const
133
{
134
  bool testb = mode & std::ios_base::binary;
135
  bool testi = mode & std::ios_base::in;
136
  bool testo = mode & std::ios_base::out;
137
  bool testt = mode & std::ios_base::trunc;
138
  bool testa = mode & std::ios_base::app;
139
 
140
  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
141
  // Original zfstream hardcoded the compression level to maximum here...
142
  // Double the time for less than 1% size improvement seems
143
  // excessive though - keeping it at the default level
144
  // To change back, just append "9" to the next three mode strings
145
  if (!testi && testo && !testt && !testa)
146
    strcpy(c_mode, "w");
147
  if (!testi && testo && !testt && testa)
148
    strcpy(c_mode, "a");
149
  if (!testi && testo && testt && !testa)
150
    strcpy(c_mode, "w");
151
  if (testi && !testo && !testt && !testa)
152
    strcpy(c_mode, "r");
153
  // No read/write mode yet
154
//  if (testi && testo && !testt && !testa)
155
//    strcpy(c_mode, "r+");
156
//  if (testi && testo && testt && !testa)
157
//    strcpy(c_mode, "w+");
158
 
159
  // Mode string should be empty for invalid combination of flags
160
  if (strlen(c_mode) == 0)
161
    return false;
162
  if (testb)
163
    strcat(c_mode, "b");
164
  return true;
165
}
166
 
167
// Determine number of characters in internal get buffer
168
std::streamsize
169
gzfilebuf::showmanyc()
170
{
171
  // Calls to underflow will fail if file not opened for reading
172
  if (!this->is_open() || !(io_mode & std::ios_base::in))
173
    return -1;
174
  // Make sure get area is in use
175
  if (this->gptr() && (this->gptr() < this->egptr()))
176
    return std::streamsize(this->egptr() - this->gptr());
177
  else
178
    return 0;
179
}
180
 
181
// Fill get area from gzipped file
182
gzfilebuf::int_type
183
gzfilebuf::underflow()
184
{
185
  // If something is left in the get area by chance, return it
186
  // (this shouldn't normally happen, as underflow is only supposed
187
  // to be called when gptr >= egptr, but it serves as error check)
188
  if (this->gptr() && (this->gptr() < this->egptr()))
189
    return traits_type::to_int_type(*(this->gptr()));
190
 
191
  // If the file hasn't been opened for reading, produce error
192
  if (!this->is_open() || !(io_mode & std::ios_base::in))
193
    return traits_type::eof();
194
 
195
  // Attempt to fill internal buffer from gzipped file
196
  // (buffer must be guaranteed to exist...)
197
  int bytes_read = gzread(file, buffer, buffer_size);
198
  // Indicates error or EOF
199
  if (bytes_read <= 0)
200
  {
201
    // Reset get area
202
    this->setg(buffer, buffer, buffer);
203
    return traits_type::eof();
204
  }
205
  // Make all bytes read from file available as get area
206
  this->setg(buffer, buffer, buffer + bytes_read);
207
 
208
  // Return next character in get area
209
  return traits_type::to_int_type(*(this->gptr()));
210
}
211
 
212
// Write put area to gzipped file
213
gzfilebuf::int_type
214
gzfilebuf::overflow(int_type c)
215
{
216
  // Determine whether put area is in use
217
  if (this->pbase())
218
  {
219
    // Double-check pointer range
220
    if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
221
      return traits_type::eof();
222
    // Add extra character to buffer if not EOF
223
    if (!traits_type::eq_int_type(c, traits_type::eof()))
224
    {
225
      *(this->pptr()) = traits_type::to_char_type(c);
226
      this->pbump(1);
227
    }
228
    // Number of characters to write to file
229
    int bytes_to_write = this->pptr() - this->pbase();
230
    // Overflow doesn't fail if nothing is to be written
231
    if (bytes_to_write > 0)
232
    {
233
      // If the file hasn't been opened for writing, produce error
234
      if (!this->is_open() || !(io_mode & std::ios_base::out))
235
        return traits_type::eof();
236
      // If gzipped file won't accept all bytes written to it, fail
237
      if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write)
238
        return traits_type::eof();
239
      // Reset next pointer to point to pbase on success
240
      this->pbump(-bytes_to_write);
241
    }
242
  }
243
  // Write extra character to file if not EOF
244
  else if (!traits_type::eq_int_type(c, traits_type::eof()))
245
  {
246
    // If the file hasn't been opened for writing, produce error
247
    if (!this->is_open() || !(io_mode & std::ios_base::out))
248
      return traits_type::eof();
249
    // Impromptu char buffer (allows "unbuffered" output)
250
    char_type last_char = traits_type::to_char_type(c);
251
    // If gzipped file won't accept this character, fail
252
    if (gzwrite(file, &last_char, 1) != 1)
253
      return traits_type::eof();
254
  }
255
 
256
  // If you got here, you have succeeded (even if c was EOF)
257
  // The return value should therefore be non-EOF
258
  if (traits_type::eq_int_type(c, traits_type::eof()))
259
    return traits_type::not_eof(c);
260
  else
261
    return c;
262
}
263
 
264
// Assign new buffer
265
std::streambuf*
266
gzfilebuf::setbuf(char_type* p,
267
                  std::streamsize n)
268
{
269
  // First make sure stuff is sync'ed, for safety
270
  if (this->sync() == -1)
271
    return NULL;
272
  // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
273
  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
274
  // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
275
  // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
276
  if (!p || !n)
277
  {
278
    // Replace existing buffer (if any) with small internal buffer
279
    this->disable_buffer();
280
    buffer = NULL;
281
    buffer_size = 0;
282
    own_buffer = true;
283
    this->enable_buffer();
284
  }
285
  else
286
  {
287
    // Replace existing buffer (if any) with external buffer
288
    this->disable_buffer();
289
    buffer = p;
290
    buffer_size = n;
291
    own_buffer = false;
292
    this->enable_buffer();
293
  }
294
  return this;
295
}
296
 
297
// Write put area to gzipped file (i.e. ensures that put area is empty)
298
int
299
gzfilebuf::sync()
300
{
301
  return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0;
302
}
303
 
304
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
305
 
306
// Allocate internal buffer
307
void
308
gzfilebuf::enable_buffer()
309
{
310
  // If internal buffer required, allocate one
311
  if (own_buffer && !buffer)
312
  {
313
    // Check for buffered vs. "unbuffered"
314
    if (buffer_size > 0)
315
    {
316
      // Allocate internal buffer
317
      buffer = new char_type[buffer_size];
318
      // Get area starts empty and will be expanded by underflow as need arises
319
      this->setg(buffer, buffer, buffer);
320
      // Setup entire internal buffer as put area.
321
      // The one-past-end pointer actually points to the last element of the buffer,
322
      // so that overflow(c) can safely add the extra character c to the sequence.
323
      // These pointers remain in place for the duration of the buffer
324
      this->setp(buffer, buffer + buffer_size - 1);
325
    }
326
    else
327
    {
328
      // Even in "unbuffered" case, (small?) get buffer is still required
329
      buffer_size = SMALLBUFSIZE;
330
      buffer = new char_type[buffer_size];
331
      this->setg(buffer, buffer, buffer);
332
      // "Unbuffered" means no put buffer
333
      this->setp(0, 0);
334
    }
335
  }
336
  else
337
  {
338
    // If buffer already allocated, reset buffer pointers just to make sure no
339
    // stale chars are lying around
340
    this->setg(buffer, buffer, buffer);
341
    this->setp(buffer, buffer + buffer_size - 1);
342
  }
343
}
344
 
345
// Destroy internal buffer
346
void
347
gzfilebuf::disable_buffer()
348
{
349
  // If internal buffer exists, deallocate it
350
  if (own_buffer && buffer)
351
  {
352
    // Preserve unbuffered status by zeroing size
353
    if (!this->pbase())
354
      buffer_size = 0;
355
    delete[] buffer;
356
    buffer = NULL;
357
    this->setg(0, 0, 0);
358
    this->setp(0, 0);
359
  }
360
  else
361
  {
362
    // Reset buffer pointers to initial state if external buffer exists
363
    this->setg(buffer, buffer, buffer);
364
    if (buffer)
365
      this->setp(buffer, buffer + buffer_size - 1);
366
    else
367
      this->setp(0, 0);
368
  }
369
}
370
 
371
/*****************************************************************************/
372
 
373
// Default constructor initializes stream buffer
374
gzifstream::gzifstream()
375
: std::istream(NULL), sb()
376
{ this->init(&sb); }
377
 
378
// Initialize stream buffer and open file
379
gzifstream::gzifstream(const char* name,
380
                       std::ios_base::openmode mode)
381
: std::istream(NULL), sb()
382
{
383
  this->init(&sb);
384
  this->open(name, mode);
385
}
386
 
387
// Initialize stream buffer and attach to file
388
gzifstream::gzifstream(int fd,
389
                       std::ios_base::openmode mode)
390
: std::istream(NULL), sb()
391
{
392
  this->init(&sb);
393
  this->attach(fd, mode);
394
}
395
 
396
// Open file and go into fail() state if unsuccessful
397
void
398
gzifstream::open(const char* name,
399
                 std::ios_base::openmode mode)
400
{
401
  if (!sb.open(name, mode | std::ios_base::in))
402
    this->setstate(std::ios_base::failbit);
403
  else
404
    this->clear();
405
}
406
 
407
// Attach to file and go into fail() state if unsuccessful
408
void
409
gzifstream::attach(int fd,
410
                   std::ios_base::openmode mode)
411
{
412
  if (!sb.attach(fd, mode | std::ios_base::in))
413
    this->setstate(std::ios_base::failbit);
414
  else
415
    this->clear();
416
}
417
 
418
// Close file
419
void
420
gzifstream::close()
421
{
422
  if (!sb.close())
423
    this->setstate(std::ios_base::failbit);
424
}
425
 
426
/*****************************************************************************/
427
 
428
// Default constructor initializes stream buffer
429
gzofstream::gzofstream()
430
: std::ostream(NULL), sb()
431
{ this->init(&sb); }
432
 
433
// Initialize stream buffer and open file
434
gzofstream::gzofstream(const char* name,
435
                       std::ios_base::openmode mode)
436
: std::ostream(NULL), sb()
437
{
438
  this->init(&sb);
439
  this->open(name, mode);
440
}
441
 
442
// Initialize stream buffer and attach to file
443
gzofstream::gzofstream(int fd,
444
                       std::ios_base::openmode mode)
445
: std::ostream(NULL), sb()
446
{
447
  this->init(&sb);
448
  this->attach(fd, mode);
449
}
450
 
451
// Open file and go into fail() state if unsuccessful
452
void
453
gzofstream::open(const char* name,
454
                 std::ios_base::openmode mode)
455
{
456
  if (!sb.open(name, mode | std::ios_base::out))
457
    this->setstate(std::ios_base::failbit);
458
  else
459
    this->clear();
460
}
461
 
462
// Attach to file and go into fail() state if unsuccessful
463
void
464
gzofstream::attach(int fd,
465
                   std::ios_base::openmode mode)
466
{
467
  if (!sb.attach(fd, mode | std::ios_base::out))
468
    this->setstate(std::ios_base::failbit);
469
  else
470
    this->clear();
471
}
472
 
473
// Close file
474
void
475
gzofstream::close()
476
{
477
  if (!sb.close())
478
    this->setstate(std::ios_base::failbit);
479
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.