00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_BITCACHE_HPP_)
00012 #define _XRB_BITCACHE_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include "xrb_endian.hpp"
00017 #include "xrb_enums.hpp"
00018
00019 namespace Xrb
00020 {
00021
00022
00023 class BitCache
00024 {
00025 public:
00026
00027 BitCache (Uint32 cache_size_in_bytes, Endian::Endianness endianness);
00028 virtual ~BitCache ();
00029
00030
00031
00032
00033
00038 inline Endian::Endianness GetEndianness () const
00039 {
00040 return m_endianness;
00041 }
00046 inline bool IsOpen () const
00047 {
00048 return m_is_open;
00049 }
00056 inline IODirection GetIODirection () const
00057 {
00058 return m_io_direction;
00059 }
00064 bool IsAtEnd () const;
00071 bool HasFewerThan8BitsLeft () const;
00076 inline IOError Error () const
00077 {
00078 return m_error;
00079 }
00080
00081 Uint32 ReadUnsignedBits (Uint32 bit_count);
00082 void WriteUnsignedBits (Uint32 value, Uint32 bit_count);
00083
00084 Sint32 ReadSignedBits (Uint32 bit_count);
00085 void WriteSignedBits (Sint32 value, Uint32 bit_count);
00086
00087 bool ReadBool ();
00088 void WriteBool (bool value);
00089
00090 void Read1ByteWordFromCache (void *destination);
00091 void Write1ByteWordToCache (void *source);
00092
00093 void Read2ByteWordFromCache (void *destination);
00094 void Write2ByteWordToCache (void *source);
00095
00096 void Read4ByteWordFromCache (void *destination);
00097 void Write4ByteWordToCache (void *source);
00098
00099 void Read8ByteWordFromCache (void *destination);
00100 void Write8ByteWordToCache (void *source);
00101
00102 void ReadBytes (Uint8 *destination, Uint32 destination_size);
00103 void WriteBytes (Uint8 const *source, Uint32 source_size);
00104
00105 Uint32 ReadBufferString (char *destination, Uint32 destination_length);
00106
00107 Uint32 WriteBufferString (char const *source, Uint32 source_length);
00108
00109
00110 void FlushWriteCache ();
00111
00112 protected:
00113
00114 inline void SetError (IOError error) const { m_error = error; }
00115
00116
00117
00118
00119
00120 inline void IncrementCacheByteIndex (Uint32 requested_byte_count)
00121 {
00122 ASSERT1(IsCacheBitIndexOnByteBoundary());
00123 ASSERT1(CacheByteIndex() + requested_byte_count
00124 <=
00125 m_next_available_cache_byte_index);
00126 m_cache_bit_index += requested_byte_count << 3;
00127 }
00128 inline void IncrementCacheBitIndex (Uint32 requested_bit_count)
00129 {
00130 ASSERT1(m_cache_bit_index + requested_bit_count
00131 <=
00132 NextAvailableCacheBitIndex());
00133 m_cache_bit_index += requested_bit_count;
00134 }
00135
00136 inline void EnsureCacheIsOnByteBoundary ()
00137 {
00138
00139 m_cache_bit_index = ((m_cache_bit_index + 7) >> 3) << 3;
00140 }
00141
00142 void EnsureReadCacheHasEnoughBitsAvailable (Uint32 requested_bit_count) const;
00143 void EnsureReadCacheHasEnoughBytesAvailable (Uint32 requested_byte_count) const;
00144
00145 void EnsureWriteCacheHasEnoughBitsAvailable (Uint32 requested_bit_count) const;
00146 void EnsureWriteCacheHasEnoughBytesAvailable (Uint32 requested_byte_count) const;
00147
00148 void OpenForReading ();
00149 void OpenForWriting ();
00150
00151
00152 void Close ();
00153
00154 virtual Uint32 FlushBytes (
00155 Uint8 const *bytes_to_flush,
00156 Uint32 number_of_bytes_to_flush) const = 0;
00157 virtual Uint32 RenewBytes (
00158 Uint8 *bytes_to_renew,
00159 Uint32 number_of_bytes_to_renew) const = 0;
00160
00161 private:
00162
00163
00164
00165
00166
00167 inline bool IsCacheEmpty () const
00168 {
00169 return m_cache_bit_index == 0;
00170 }
00171 inline bool IsCacheBitIndexOnByteBoundary () const
00172 {
00173 return (m_cache_bit_index & 7) == 0;
00174 }
00175
00176 inline Uint32 UsedCacheByteCount () const
00177 {
00178 return (m_cache_bit_index + 7) >> 3;
00179 }
00180 inline Uint32 CacheByteIndex () const
00181 {
00182 return m_cache_bit_index >> 3;
00183 }
00184 inline Uint32 NextAvailableCacheBitIndex () const
00185 {
00186 return m_next_available_cache_byte_index << 3;
00187 }
00188
00189
00190
00191
00192
00193 inline void SetIsOpen (bool is_open) { m_is_open = is_open; }
00194 inline void SetIODirection (IODirection io_direction)
00195 {
00196 m_io_direction = io_direction;
00197 }
00198
00200 Endian::Endianness m_endianness;
00202 bool m_is_open;
00204 IODirection m_io_direction;
00206 mutable IOError m_error;
00207
00209 Uint32 const m_working_cache_size_in_bytes;
00211 Uint32 const m_working_cache_size_in_bits;
00213 Uint32 const m_actual_cache_size_in_bytes;
00215 Uint32 const m_actual_cache_size_in_bits;
00217 mutable Uint8 *m_cache;
00223 mutable Uint32 m_cache_bit_index;
00227 mutable Uint32 m_next_available_cache_byte_index;
00228 };
00229
00230 }
00231
00232 #endif // !defined(_XRB_BITCACHE_HPP_)