![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.