zstream.h
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

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