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