text: /*
   * Copyright (C) 2007 Tommi Maekitalo
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation; either version 2 of the
   * License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
   * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
   * NON-INFRINGEMENT.  See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   *
   */
  
  #ifndef ZIM_ZINTSTREAM_H
  #define ZIM_ZINTSTREAM_H
  
  #include <string>
  #include <iostream>
  #include <zim/zim.h>
  
  /*
    ZInt implements a int compressor and decompressor. The algorithm compresses
    small values into fewer bytes.
    
    The idea is to add information about used bytes in the first byte. The number
    of additional bytes used is specified by the number of set bits counted from
    the most significant bit. So the numbers 0-127 are encoded as is, since they
    fit into the 7 low order bits and the high order bit specifies, that no
    additional bytes are used. The number starting from 128 up to 16383 need more
    than 7 bits, so we need to set the highest order bit to 1 and the next bit to
    0, leaving 6 bits of actual data, which is used as the low order bits of the
    number.
  
    Since the numbers 0-127 are already encoded in one byte, the 127 is
    substracted from the actual number, so a 2 byte zero is actually a 128.
  
    The same logic continues on the 3rd, 4th, ... byte. Up to 7 additional bytes
    could used, since the first byte must contain at least one 0.
  
    This particular implementation only represents uint32_t values (numbers up
    to 2^32-1), so it will only ever emit 5 bytes per input value.
  
    binary                          range
    ------------------------------- --------------------------------------------------
    0xxx xxxx                       0 - 127
    10xx xxxx xxxx xxxx             128 - (2^14+128-1 = 16511)
    110x xxxx xxxx xxxx xxxx xxxx   16512 - (2^21+16512-1 = 2113663)
    1110 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
                                    2113664 - (2^28+2113664-1 = 270549119)
    ...
  
  */
  
  namespace zim
  {
    class ZIntStream
    {
        std::istream* _istream;
        std::ostream* _ostream;
  
      public:
        /// prepare ZIntStream for compression or decompression
        explicit ZIntStream(std::iostream& iostream)
          : _istream(&iostream),
            _ostream(&iostream)
            { }
  
        /// prepare ZIntStream for decompression
        explicit ZIntStream(std::istream& istream)
          : _istream(&istream),
            _ostream(0)
            { }
  
        /// prepare ZIntStream for compression
        explicit ZIntStream(std::ostream& ostream)
          : _istream(0),
            _ostream(&ostream)
            { }
  
        /// decompresses one value from input stream and returns it
        size_type get();
  
        ZIntStream& get(size_type &value)
          { value = get(); return *this; }
  
        /// compresses one value to output stream
        ZIntStream& put(size_type value);
  
        operator bool() const
          { return (_istream == 0 || *_istream)
                && (_ostream == 0 || *_ostream); }
    };
  
  }
  #endif  //  ZIM_ZINTSTREAM_H
  