Home | History | Annotate | Line # | Download | only in iostream2
zstream.h revision 1.1
      1  1.1  christos /*	$NetBSD: zstream.h,v 1.1 2006/01/14 20:10:54 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  *
      5  1.1  christos  * Copyright (c) 1997
      6  1.1  christos  * Christian Michelsen Research AS
      7  1.1  christos  * Advanced Computing
      8  1.1  christos  * Fantoftvegen 38, 5036 BERGEN, Norway
      9  1.1  christos  * http://www.cmr.no
     10  1.1  christos  *
     11  1.1  christos  * Permission to use, copy, modify, distribute and sell this software
     12  1.1  christos  * and its documentation for any purpose is hereby granted without fee,
     13  1.1  christos  * provided that the above copyright notice appear in all copies and
     14  1.1  christos  * that both that copyright notice and this permission notice appear
     15  1.1  christos  * in supporting documentation.  Christian Michelsen Research AS makes no
     16  1.1  christos  * representations about the suitability of this software for any
     17  1.1  christos  * purpose.  It is provided "as is" without express or implied warranty.
     18  1.1  christos  *
     19  1.1  christos  */
     20  1.1  christos 
     21  1.1  christos #ifndef ZSTREAM__H
     22  1.1  christos #define ZSTREAM__H
     23  1.1  christos 
     24  1.1  christos /*
     25  1.1  christos  * zstream.h - C++ interface to the 'zlib' general purpose compression library
     26  1.1  christos  * Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge
     27  1.1  christos  */
     28  1.1  christos 
     29  1.1  christos #include <strstream.h>
     30  1.1  christos #include <string.h>
     31  1.1  christos #include <stdio.h>
     32  1.1  christos #include "zlib.h"
     33  1.1  christos 
     34  1.1  christos #if defined(_WIN32)
     35  1.1  christos #   include <fcntl.h>
     36  1.1  christos #   include <io.h>
     37  1.1  christos #   define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
     38  1.1  christos #else
     39  1.1  christos #   define SET_BINARY_MODE(file)
     40  1.1  christos #endif
     41  1.1  christos 
     42  1.1  christos class zstringlen {
     43  1.1  christos public:
     44  1.1  christos     zstringlen(class izstream&);
     45  1.1  christos     zstringlen(class ozstream&, const char*);
     46  1.1  christos     size_t value() const { return val.word; }
     47  1.1  christos private:
     48  1.1  christos     struct Val { unsigned char byte; size_t word; } val;
     49  1.1  christos };
     50  1.1  christos 
     51  1.1  christos //  ----------------------------- izstream -----------------------------
     52  1.1  christos 
     53  1.1  christos class izstream
     54  1.1  christos {
     55  1.1  christos     public:
     56  1.1  christos         izstream() : m_fp(0) {}
     57  1.1  christos         izstream(FILE* fp) : m_fp(0) { open(fp); }
     58  1.1  christos         izstream(const char* name) : m_fp(0) { open(name); }
     59  1.1  christos         ~izstream() { close(); }
     60  1.1  christos 
     61  1.1  christos         /* Opens a gzip (.gz) file for reading.
     62  1.1  christos          * open() can be used to read a file which is not in gzip format;
     63  1.1  christos          * in this case read() will directly read from the file without
     64  1.1  christos          * decompression. errno can be checked to distinguish two error
     65  1.1  christos          * cases (if errno is zero, the zlib error is Z_MEM_ERROR).
     66  1.1  christos          */
     67  1.1  christos         void open(const char* name) {
     68  1.1  christos             if (m_fp) close();
     69  1.1  christos             m_fp = ::gzopen(name, "rb");
     70  1.1  christos         }
     71  1.1  christos 
     72  1.1  christos         void open(FILE* fp) {
     73  1.1  christos             SET_BINARY_MODE(fp);
     74  1.1  christos             if (m_fp) close();
     75  1.1  christos             m_fp = ::gzdopen(fileno(fp), "rb");
     76  1.1  christos         }
     77  1.1  christos 
     78  1.1  christos         /* Flushes all pending input if necessary, closes the compressed file
     79  1.1  christos          * and deallocates all the (de)compression state. The return value is
     80  1.1  christos          * the zlib error number (see function error() below).
     81  1.1  christos          */
     82  1.1  christos         int close() {
     83  1.1  christos             int r = ::gzclose(m_fp);
     84  1.1  christos             m_fp = 0; return r;
     85  1.1  christos         }
     86  1.1  christos 
     87  1.1  christos         /* Binary read the given number of bytes from the compressed file.
     88  1.1  christos          */
     89  1.1  christos         int read(void* buf, size_t len) {
     90  1.1  christos             return ::gzread(m_fp, buf, len);
     91  1.1  christos         }
     92  1.1  christos 
     93  1.1  christos         /* Returns the error message for the last error which occurred on the
     94  1.1  christos          * given compressed file. errnum is set to zlib error number. If an
     95  1.1  christos          * error occurred in the file system and not in the compression library,
     96  1.1  christos          * errnum is set to Z_ERRNO and the application may consult errno
     97  1.1  christos          * to get the exact error code.
     98  1.1  christos          */
     99  1.1  christos         const char* error(int* errnum) {
    100  1.1  christos             return ::gzerror(m_fp, errnum);
    101  1.1  christos         }
    102  1.1  christos 
    103  1.1  christos         gzFile fp() { return m_fp; }
    104  1.1  christos 
    105  1.1  christos     private:
    106  1.1  christos         gzFile m_fp;
    107  1.1  christos };
    108  1.1  christos 
    109  1.1  christos /*
    110  1.1  christos  * Binary read the given (array of) object(s) from the compressed file.
    111  1.1  christos  * If the input file was not in gzip format, read() copies the objects number
    112  1.1  christos  * of bytes into the buffer.
    113  1.1  christos  * returns the number of uncompressed bytes actually read
    114  1.1  christos  * (0 for end of file, -1 for error).
    115  1.1  christos  */
    116  1.1  christos template <class T, class Items>
    117  1.1  christos inline int read(izstream& zs, T* x, Items items) {
    118  1.1  christos     return ::gzread(zs.fp(), x, items*sizeof(T));
    119  1.1  christos }
    120  1.1  christos 
    121  1.1  christos /*
    122  1.1  christos  * Binary input with the '>' operator.
    123  1.1  christos  */
    124  1.1  christos template <class T>
    125  1.1  christos inline izstream& operator>(izstream& zs, T& x) {
    126  1.1  christos     ::gzread(zs.fp(), &x, sizeof(T));
    127  1.1  christos     return zs;
    128  1.1  christos }
    129  1.1  christos 
    130  1.1  christos 
    131  1.1  christos inline zstringlen::zstringlen(izstream& zs) {
    132  1.1  christos     zs > val.byte;
    133  1.1  christos     if (val.byte == 255) zs > val.word;
    134  1.1  christos     else val.word = val.byte;
    135  1.1  christos }
    136  1.1  christos 
    137  1.1  christos /*
    138  1.1  christos  * Read length of string + the string with the '>' operator.
    139  1.1  christos  */
    140  1.1  christos inline izstream& operator>(izstream& zs, char* x) {
    141  1.1  christos     zstringlen len(zs);
    142  1.1  christos     ::gzread(zs.fp(), x, len.value());
    143  1.1  christos     x[len.value()] = '\0';
    144  1.1  christos     return zs;
    145  1.1  christos }
    146  1.1  christos 
    147  1.1  christos inline char* read_string(izstream& zs) {
    148  1.1  christos     zstringlen len(zs);
    149  1.1  christos     char* x = new char[len.value()+1];
    150  1.1  christos     ::gzread(zs.fp(), x, len.value());
    151  1.1  christos     x[len.value()] = '\0';
    152  1.1  christos     return x;
    153  1.1  christos }
    154  1.1  christos 
    155  1.1  christos // ----------------------------- ozstream -----------------------------
    156  1.1  christos 
    157  1.1  christos class ozstream
    158  1.1  christos {
    159  1.1  christos     public:
    160  1.1  christos         ozstream() : m_fp(0), m_os(0) {
    161  1.1  christos         }
    162  1.1  christos         ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION)
    163  1.1  christos             : m_fp(0), m_os(0) {
    164  1.1  christos             open(fp, level);
    165  1.1  christos         }
    166  1.1  christos         ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION)
    167  1.1  christos             : m_fp(0), m_os(0) {
    168  1.1  christos             open(name, level);
    169  1.1  christos         }
    170  1.1  christos         ~ozstream() {
    171  1.1  christos             close();
    172  1.1  christos         }
    173  1.1  christos 
    174  1.1  christos         /* Opens a gzip (.gz) file for writing.
    175  1.1  christos          * The compression level parameter should be in 0..9
    176  1.1  christos          * errno can be checked to distinguish two error cases
    177  1.1  christos          * (if errno is zero, the zlib error is Z_MEM_ERROR).
    178  1.1  christos          */
    179  1.1  christos         void open(const char* name, int level = Z_DEFAULT_COMPRESSION) {
    180  1.1  christos             char mode[4] = "wb\0";
    181  1.1  christos             if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
    182  1.1  christos             if (m_fp) close();
    183  1.1  christos             m_fp = ::gzopen(name, mode);
    184  1.1  christos         }
    185  1.1  christos 
    186  1.1  christos         /* open from a FILE pointer.
    187  1.1  christos          */
    188  1.1  christos         void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) {
    189  1.1  christos             SET_BINARY_MODE(fp);
    190  1.1  christos             char mode[4] = "wb\0";
    191  1.1  christos             if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
    192  1.1  christos             if (m_fp) close();
    193  1.1  christos             m_fp = ::gzdopen(fileno(fp), mode);
    194  1.1  christos         }
    195  1.1  christos 
    196  1.1  christos         /* Flushes all pending output if necessary, closes the compressed file
    197  1.1  christos          * and deallocates all the (de)compression state. The return value is
    198  1.1  christos          * the zlib error number (see function error() below).
    199  1.1  christos          */
    200  1.1  christos         int close() {
    201  1.1  christos             if (m_os) {
    202  1.1  christos                 ::gzwrite(m_fp, m_os->str(), m_os->pcount());
    203  1.1  christos                 delete[] m_os->str(); delete m_os; m_os = 0;
    204  1.1  christos             }
    205  1.1  christos             int r = ::gzclose(m_fp); m_fp = 0; return r;
    206  1.1  christos         }
    207  1.1  christos 
    208  1.1  christos         /* Binary write the given number of bytes into the compressed file.
    209  1.1  christos          */
    210  1.1  christos         int write(const void* buf, size_t len) {
    211  1.1  christos             return ::gzwrite(m_fp, (voidp) buf, len);
    212  1.1  christos         }
    213  1.1  christos 
    214  1.1  christos         /* Flushes all pending output into the compressed file. The parameter
    215  1.1  christos          * _flush is as in the deflate() function. The return value is the zlib
    216  1.1  christos          * error number (see function gzerror below). flush() returns Z_OK if
    217  1.1  christos          * the flush_ parameter is Z_FINISH and all output could be flushed.
    218  1.1  christos          * flush() should be called only when strictly necessary because it can
    219  1.1  christos          * degrade compression.
    220  1.1  christos          */
    221  1.1  christos         int flush(int _flush) {
    222  1.1  christos             os_flush();
    223  1.1  christos             return ::gzflush(m_fp, _flush);
    224  1.1  christos         }
    225  1.1  christos 
    226  1.1  christos         /* Returns the error message for the last error which occurred on the
    227  1.1  christos          * given compressed file. errnum is set to zlib error number. If an
    228  1.1  christos          * error occurred in the file system and not in the compression library,
    229  1.1  christos          * errnum is set to Z_ERRNO and the application may consult errno
    230  1.1  christos          * to get the exact error code.
    231  1.1  christos          */
    232  1.1  christos         const char* error(int* errnum) {
    233  1.1  christos             return ::gzerror(m_fp, errnum);
    234  1.1  christos         }
    235  1.1  christos 
    236  1.1  christos         gzFile fp() { return m_fp; }
    237  1.1  christos 
    238  1.1  christos         ostream& os() {
    239  1.1  christos             if (m_os == 0) m_os = new ostrstream;
    240  1.1  christos             return *m_os;
    241  1.1  christos         }
    242  1.1  christos 
    243  1.1  christos         void os_flush() {
    244  1.1  christos             if (m_os && m_os->pcount()>0) {
    245  1.1  christos                 ostrstream* oss = new ostrstream;
    246  1.1  christos                 oss->fill(m_os->fill());
    247  1.1  christos                 oss->flags(m_os->flags());
    248  1.1  christos                 oss->precision(m_os->precision());
    249  1.1  christos                 oss->width(m_os->width());
    250  1.1  christos                 ::gzwrite(m_fp, m_os->str(), m_os->pcount());
    251  1.1  christos                 delete[] m_os->str(); delete m_os; m_os = oss;
    252  1.1  christos             }
    253  1.1  christos         }
    254  1.1  christos 
    255  1.1  christos     private:
    256  1.1  christos         gzFile m_fp;
    257  1.1  christos         ostrstream* m_os;
    258  1.1  christos };
    259  1.1  christos 
    260  1.1  christos /*
    261  1.1  christos  * Binary write the given (array of) object(s) into the compressed file.
    262  1.1  christos  * returns the number of uncompressed bytes actually written
    263  1.1  christos  * (0 in case of error).
    264  1.1  christos  */
    265  1.1  christos template <class T, class Items>
    266  1.1  christos inline int write(ozstream& zs, const T* x, Items items) {
    267  1.1  christos     return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T));
    268  1.1  christos }
    269  1.1  christos 
    270  1.1  christos /*
    271  1.1  christos  * Binary output with the '<' operator.
    272  1.1  christos  */
    273  1.1  christos template <class T>
    274  1.1  christos inline ozstream& operator<(ozstream& zs, const T& x) {
    275  1.1  christos     ::gzwrite(zs.fp(), (voidp) &x, sizeof(T));
    276  1.1  christos     return zs;
    277  1.1  christos }
    278  1.1  christos 
    279  1.1  christos inline zstringlen::zstringlen(ozstream& zs, const char* x) {
    280  1.1  christos     val.byte = 255;  val.word = ::strlen(x);
    281  1.1  christos     if (val.word < 255) zs < (val.byte = val.word);
    282  1.1  christos     else zs < val;
    283  1.1  christos }
    284  1.1  christos 
    285  1.1  christos /*
    286  1.1  christos  * Write length of string + the string with the '<' operator.
    287  1.1  christos  */
    288  1.1  christos inline ozstream& operator<(ozstream& zs, const char* x) {
    289  1.1  christos     zstringlen len(zs, x);
    290  1.1  christos     ::gzwrite(zs.fp(), (voidp) x, len.value());
    291  1.1  christos     return zs;
    292  1.1  christos }
    293  1.1  christos 
    294  1.1  christos #ifdef _MSC_VER
    295  1.1  christos inline ozstream& operator<(ozstream& zs, char* const& x) {
    296  1.1  christos     return zs < (const char*) x;
    297  1.1  christos }
    298  1.1  christos #endif
    299  1.1  christos 
    300  1.1  christos /*
    301  1.1  christos  * Ascii write with the << operator;
    302  1.1  christos  */
    303  1.1  christos template <class T>
    304  1.1  christos inline ostream& operator<<(ozstream& zs, const T& x) {
    305  1.1  christos     zs.os_flush();
    306  1.1  christos     return zs.os() << x;
    307  1.1  christos }
    308  1.1  christos 
    309  1.1  christos #endif
    310