Shadowrun: Awakened 29 September 2011 - Build 871
BitStream.hpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009-2010 Christopher A. Taylor.  All rights reserved.
00003 
00004     Redistribution and use in source and binary forms, with or without
00005     modification, are permitted provided that the following conditions are met:
00006 
00007     * Redistributions of source code must retain the above copyright notice,
00008       this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice,
00010       this list of conditions and the following disclaimer in the documentation
00011       and/or other materials provided with the distribution.
00012     * Neither the name of LibCat nor the names of its contributors may be used
00013       to endorse or promote products derived from this software without
00014       specific prior written permission.
00015 
00016     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00020     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026     POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00029 // Not currently being maintained.
00030 
00031 // FIXME: Big-endian code is untested
00032 // FIXME: Not suitable for storing large buffers > 500 MB in size
00033 
00034 #ifndef CAT_BIT_STREAM_HPP
00035 #define CAT_BIT_STREAM_HPP
00036 
00037 #include <cat/Platform.hpp>
00038 
00039 namespace cat {
00040 
00041 
00043 
00044 namespace bs_bit
00045 {
00046     template<u32 N_BITS> struct set
00047     {
00048         u32 bits;
00049         set(u32 c_bits) : bits(c_bits) { }
00050     };
00051 
00052     template<u32 N_BITS> struct get
00053     {
00054         u32 &ref;
00055         get(u32 &c_ref) : ref(c_ref) { }
00056     };
00057 }
00058 
00059 namespace bs_byte
00060 {
00061     struct set
00062     {
00063         u32 bytes;
00064         const void *ref;
00065 
00066         set(u32 b, const void *r) : ref(r), bytes(b) { }
00067     };
00068 
00069     struct get
00070     {
00071         u32 bytes;
00072         void *ref;
00073 
00074         get(u32 b, void *r) : ref(r), bytes(b) { }
00075     };
00076 }
00077 
00078 
00080 
00081 class BitStream
00082 {
00083     bool fixed_buffer;
00084     u8 *buffer;
00085     u32 buffer_bytes;
00086     bool read_underrun;
00087 
00088     // grow to be able to write a number of bits
00089     void grow(u32 bits);
00090 
00091 public:
00092     u32 read_offset, write_offset; // in bits
00093 
00094 public:
00095     BitStream(u32 bytes = 0, void *vbuffer = 0);
00096     ~BitStream();
00097 
00098     // free unused buffer space
00099     void shrink();
00100 
00101 public:
00102     u8 *get() { return buffer; }
00103 
00104     bool aligned() { return read_offset % 8 == 0; }
00105     u8 *peek() { return buffer + read_offset / 8; }
00106 
00107 public:
00108     // returns true iff the buffer is valid
00109     bool valid() { return buffer != 0; }
00110 
00111     // returns count of remaining readable bits
00112     int unread() { return write_offset - read_offset; }
00113 
00114     // returns true if a recent read operation would have overrun the buffer
00115     bool underrun();
00116 
00117     // skip ahead a number of bits
00118     void skip(u32 bits);
00119 
00120 public:
00121     // insertion
00122     void write1(u8 data); // data MUST be 1 or 0
00123 
00124     template<class T> void write(T data)
00125     {
00126         grow(sizeof(T) * 8);
00127 
00128         u32 byte_offset = write_offset / 8;
00129         u32 shift = write_offset % 8;
00130 
00131         if (shift)
00132         {
00133             buffer[byte_offset] |= (u8)(data << shift);
00134             data = data >> (8 - shift);
00135             ++byte_offset;
00136         }
00137 
00138         *(T*)(buffer + byte_offset) = data;
00139 
00140         write_offset += sizeof(T) * 8;
00141     }
00142     template<> void write(s8 data) { write((u8)data); }
00143     template<> void write(s16 data) { write((u16)data); }
00144     template<> void write(s32 data) { write((u32)data); }
00145     template<> void write(s64 data) { write((u64)data); }
00146     template<> void write(float data) { write(*(u32*)&data); }
00147     template<> void write(double data) { write(*(u64*)&data); }
00148 
00149     void writeBits(u32 data, int count);
00150     void writeBytes(const void *data, u32 byte_count);
00151 
00152 public:
00153     // stream-mode insertion
00154     BitStream &operator<<(const char *data) { writeBytes(data, (u32)strlen(data)); return *this; }
00155 
00156     template<class T> BitStream &operator<<(T data) { write(data); return *this; }
00157 
00158     template<u32 N_BITS> BitStream &operator<<(const bs_bit::set<N_BITS> &n) { writeBits(n.bits, N_BITS); return *this; }
00159     template<> BitStream &operator<<(const bs_bit::set<1> &n) { write1((u8)n.bits); return *this; }
00160     template<> BitStream &operator<<(const bs_bit::set<8> &n) { write((u8)n.bits); return *this; }
00161     template<> BitStream &operator<<(const bs_bit::set<16> &n) { write((u16)n.bits); return *this; }
00162     template<> BitStream &operator<<(const bs_bit::set<32> &n) { write((u32)n.bits); return *this; }
00163 
00164     BitStream &operator<<(const bs_byte::set &n) { writeBytes(n.ref, n.bytes); return *this; }
00165 
00166 public:
00167     // extraction
00168     u8 read1();
00169 
00170     template<class T> void read(T &data)
00171     {
00172         const u32 bits = sizeof(T) * 8;
00173 
00174         if (read_offset + bits > write_offset)
00175         {
00176             read_underrun = true;
00177             return;
00178         }
00179 
00180         u32 byte_offset = read_offset / 8;
00181         u32 shift = read_offset % 8;
00182 
00183         if (shift)
00184             data = (*(T*)(buffer + byte_offset + 1) << (8 - shift)) | (buffer[byte_offset] >> shift);
00185         else
00186             data = *(T*)(buffer + byte_offset);
00187 
00188         read_offset += bits;
00189     }
00190     template<> void read(float &data) { read((u32&)data); }
00191     template<> void read(double &data) { write(*(u64*)&data); }
00192     template<class T> T read() { T temp; read(temp); return temp; }
00193 
00194     u32 readBits(u32 count);
00195     void readBytes(void *data, u32 byte_count);
00196 
00197 public:
00198     // stream-mode extraction
00199     template<class T> BitStream &operator>>(T &data) { read(data); return *this; }
00200 
00201     template<u32 N_BITS> BitStream &operator>>(const bs_bit::get<N_BITS> &n) { n.ref = readBits(N_BITS); return *this; }
00202     template<> BitStream &operator>>(const bs_bit::get<1> &n) { n.ref = read1(); return *this; }
00203     template<> BitStream &operator>>(const bs_bit::get<8> &n) { n.ref = read<u8>(); return *this; }
00204     template<> BitStream &operator>>(const bs_bit::get<16> &n) { n.ref = read<u16>(); return *this; }
00205     template<> BitStream &operator>>(const bs_bit::get<32> &n) { read(n.ref); return *this; }
00206 
00207     BitStream &operator>>(const bs_byte::get &n) { readBytes(n.ref, n.bytes); return *this; }
00208 };
00209 
00210 
00211 } // namespace cat
00212 
00213 #endif // CAT_BIT_STREAM_HPP
00214 

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net