00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_bitcache.hpp"
00012
00013 #include <string.h>
00014
00015 namespace Xrb
00016 {
00017
00018 BitCache::BitCache (
00019 Uint32 const cache_size_in_bytes,
00020 Endian::Endianness const endianness)
00021 :
00022 m_endianness(endianness),
00023 m_working_cache_size_in_bytes(cache_size_in_bytes),
00024 m_working_cache_size_in_bits(m_working_cache_size_in_bytes * 8),
00025 m_actual_cache_size_in_bytes(m_working_cache_size_in_bytes + 1),
00026 m_actual_cache_size_in_bits(m_actual_cache_size_in_bytes * 8)
00027 {
00028 ASSERT1(m_endianness == Endian::LITTLE || m_endianness == Endian::BIG);
00029 ASSERT1(m_working_cache_size_in_bytes > 0);
00030 ASSERT1(m_working_cache_size_in_bits > m_working_cache_size_in_bytes && "Numerical overflow resulting from requested cache size");
00031 ASSERT1(m_actual_cache_size_in_bytes > m_working_cache_size_in_bytes && "Numerical overflow resulting from requested cache size");
00032 ASSERT1(m_actual_cache_size_in_bits > m_actual_cache_size_in_bytes && "Numerical overflow resulting from requested cache size");
00033
00034 m_cache = new Uint8[m_actual_cache_size_in_bytes];
00035
00036 SetIsOpen(false);
00037 SetIODirection(IOD_NONE);
00038 SetError(IOE_NONE);
00039 }
00040
00041 BitCache::~BitCache ()
00042 {
00043 ASSERT1(!IsOpen() && "You must close a previously opened BitCache before it is destroyed.");
00044 ASSERT1(GetIODirection() == IOD_NONE);
00045 ASSERT1(m_cache != NULL);
00046 ASSERT1(m_working_cache_size_in_bytes > 0);
00047 ASSERT1(m_working_cache_size_in_bits > 0);
00048 ASSERT1(m_actual_cache_size_in_bytes > 0);
00049 ASSERT1(m_actual_cache_size_in_bits > 0);
00050
00051 Delete(m_cache);
00052 m_cache_bit_index = 0;
00053 m_next_available_cache_byte_index = 0;
00054 }
00055
00056 bool BitCache::IsAtEnd () const
00057 {
00058 if (CacheByteIndex() < m_next_available_cache_byte_index)
00059 return false;
00060
00061 switch (GetIODirection())
00062 {
00063 case IOD_READ:
00064 EnsureReadCacheHasEnoughBitsAvailable(1);
00065 return Error() == IOE_IS_AT_END;
00066
00067 case IOD_WRITE:
00068 EnsureWriteCacheHasEnoughBitsAvailable(1);
00069 return Error() == IOE_IS_AT_END;
00070
00071 default:
00072 ASSERT0(false && "Invalid IODirection");
00073 return false;
00074 }
00075 }
00076
00077 bool BitCache::HasFewerThan8BitsLeft () const
00078 {
00079 switch (GetIODirection())
00080 {
00081 case IOD_READ:
00082 EnsureReadCacheHasEnoughBitsAvailable(8);
00083 return Error() == IOE_IS_AT_END ||
00084 Error() == IOE_INSUFFICIENT_AVAILABLE_DATA;
00085
00086 case IOD_WRITE:
00087 EnsureWriteCacheHasEnoughBitsAvailable(8);
00088 return Error() == IOE_IS_AT_END ||
00089 Error() == IOE_INSUFFICIENT_STORAGE;
00090
00091 default:
00092 ASSERT0(false && "Invalid IODirection");
00093 return false;
00094 }
00095 }
00096
00097 Uint32 BitCache::ReadUnsignedBits (Uint32 const bit_count)
00098 {
00099 ASSERT1(IsOpen());
00100 ASSERT1(GetIODirection() == IOD_READ);
00101 ASSERT1(bit_count <= 32);
00102
00103 EnsureReadCacheHasEnoughBitsAvailable(bit_count);
00104 if (Error() != IOE_NONE)
00105 return 0;
00106
00107 Uint32 retval = 0;
00108 Uint32 bits_actually_transferred = 0;
00109 Uint8 *source = m_cache + CacheByteIndex();
00110
00111 while (bits_actually_transferred < bit_count)
00112 {
00113 Uint32 amount_to_shift_retval =
00114 Min(8 - ((m_cache_bit_index + bits_actually_transferred) & 7),
00115 bit_count - bits_actually_transferred);
00116 Uint32 amount_to_shift_source =
00117 8 - Min(
00118 ((m_cache_bit_index + bits_actually_transferred) & 7) +
00119 (bit_count - bits_actually_transferred),
00120 static_cast<Uint32>(8));
00121 Uint32 source_value =
00122 static_cast<Uint32>(*source) >> amount_to_shift_source;
00123 Uint32 source_mask =
00124 (1 << amount_to_shift_retval) - 1;
00125
00126 retval <<= amount_to_shift_retval;
00127 retval |= source_value & source_mask;
00128
00129 bits_actually_transferred += amount_to_shift_retval;
00130 ++source;
00131 }
00132
00133
00134
00135 IncrementCacheBitIndex(bit_count);
00136 return retval;
00137 }
00138
00139 void BitCache::WriteUnsignedBits (Uint32 const value, Uint32 const bit_count)
00140 {
00141 ASSERT1(IsOpen());
00142 ASSERT1(GetIODirection() == IOD_WRITE);
00143 ASSERT1(bit_count <= 32);
00144
00145 EnsureWriteCacheHasEnoughBitsAvailable(bit_count);
00146 if (Error() != IOE_NONE)
00147 return;
00148
00149
00150
00151 Uint32 bits_actually_transferred = 0;
00152 Uint8 *source = m_cache + CacheByteIndex();
00153
00154 while (bits_actually_transferred < bit_count)
00155 {
00156 Uint32 bits_to_transfer_in_this_byte =
00157 Min(8 - ((m_cache_bit_index + bits_actually_transferred) & 7),
00158 bit_count - bits_actually_transferred);
00159 Uint32 amount_to_shift_source =
00160 8 - Min(
00161 ((m_cache_bit_index + bits_actually_transferred) & 7) +
00162 (bit_count - bits_actually_transferred),
00163 static_cast<Uint32>(8));
00164 Uint8 source_write_mask =
00165 static_cast<Uint8>((1 << bits_to_transfer_in_this_byte) - 1);
00166 Uint8 value_to_write =
00167 static_cast<Uint8>(value >> (bit_count -
00168 bits_actually_transferred -
00169 bits_to_transfer_in_this_byte));
00170 *source >>= amount_to_shift_source;
00171 *source &= ~source_write_mask;
00172 *source |= value_to_write & source_write_mask;
00173 *source <<= amount_to_shift_source;
00174
00175 bits_actually_transferred += bits_to_transfer_in_this_byte;
00176 ++source;
00177 }
00178
00179 IncrementCacheBitIndex(bit_count);
00180 ASSERT1(Error() == IOE_NONE);
00181 }
00182
00183 Sint32 BitCache::ReadSignedBits (Uint32 const bit_count)
00184 {
00185 Uint32 retval = ReadUnsignedBits(bit_count);
00186 if (Error() != IOE_NONE)
00187 return 0;
00188
00189
00190 if (bit_count < 32 && (retval & (1 << (bit_count - 1))) != 0)
00191 retval |= ~((1 << bit_count) - 1);
00192
00193 ASSERT1(Error() == IOE_NONE);
00194 return static_cast<Sint32>(retval);
00195 }
00196
00197 void BitCache::WriteSignedBits (Sint32 const value, Uint32 const bit_count)
00198 {
00199 WriteUnsignedBits(static_cast<Uint32>(value), bit_count);
00200 }
00201
00202 bool BitCache::ReadBool ()
00203 {
00204 ASSERT1(IsOpen());
00205 ASSERT1(GetIODirection() == IOD_READ);
00206
00207 EnsureReadCacheHasEnoughBitsAvailable(1);
00208 if (Error() != IOE_NONE)
00209 return false;
00210
00211 Uint32 bit_to_query = 7 - (m_cache_bit_index & 7);
00212 Uint8 bit_mask = static_cast<Uint8>(1 << bit_to_query);
00213 bool retval = (m_cache[CacheByteIndex()] & bit_mask) ? true : false;
00214
00215 IncrementCacheBitIndex(1);
00216 ASSERT1(Error() == IOE_NONE);
00217 return retval;
00218 }
00219
00220 void BitCache::WriteBool (bool const value)
00221 {
00222 ASSERT1(IsOpen());
00223 ASSERT1(GetIODirection() == IOD_WRITE);
00224
00225 EnsureWriteCacheHasEnoughBitsAvailable(1);
00226 if (Error() != IOE_NONE)
00227 return;
00228
00229 Uint32 bit_to_set = 7 - (m_cache_bit_index & 7);
00230 Uint8 bit_mask = static_cast<Uint8>(1 << bit_to_set);
00231 if (value)
00232 m_cache[CacheByteIndex()] |= bit_mask;
00233 else
00234 m_cache[CacheByteIndex()] &= ~bit_mask;
00235
00236 IncrementCacheBitIndex(1);
00237 ASSERT1(Error() == IOE_NONE);
00238 }
00239
00240 void BitCache::Read1ByteWordFromCache (void *const destination)
00241 {
00242 ASSERT1(IsOpen());
00243 ASSERT1(GetIODirection() == IOD_READ);
00244 ASSERT1(destination != NULL);
00245 Uint32 const byte_count = 1;
00246 EnsureCacheIsOnByteBoundary();
00247 EnsureReadCacheHasEnoughBytesAvailable(byte_count);
00248 if (Error() != IOE_NONE)
00249 return;
00250 for (Uint8 *write_to = static_cast<Uint8 *>(destination),
00251 *read_from = m_cache + CacheByteIndex(),
00252 i = 0;
00253 i < byte_count;
00254 ++write_to, ++read_from, ++i)
00255 {
00256 *write_to = *read_from;
00257 }
00258 Endian::ConvertGivenToMachine1ByteWord(GetEndianness(), destination);
00259 IncrementCacheByteIndex(byte_count);
00260 ASSERT1(Error() == IOE_NONE);
00261 }
00262
00263 void BitCache::Write1ByteWordToCache (void *const source)
00264 {
00265 ASSERT1(IsOpen());
00266 ASSERT1(GetIODirection() == IOD_WRITE);
00267 ASSERT1(source != NULL);
00268 Uint32 const byte_count = 1;
00269 EnsureCacheIsOnByteBoundary();
00270 EnsureWriteCacheHasEnoughBytesAvailable(byte_count);
00271 if (Error() != IOE_NONE)
00272 return;
00273 Endian::ConvertMachineToGiven1ByteWord(source, GetEndianness());
00274 for (Uint8 *write_to = m_cache + CacheByteIndex(),
00275 *read_from = static_cast<Uint8 *>(source),
00276 i = 0;
00277 i < byte_count;
00278 ++write_to, ++read_from, ++i)
00279 {
00280 *write_to = *read_from;
00281 }
00282 IncrementCacheByteIndex(byte_count);
00283 ASSERT1(Error() == IOE_NONE);
00284 }
00285
00286 void BitCache::Read2ByteWordFromCache (void *const destination)
00287 {
00288 ASSERT1(IsOpen());
00289 ASSERT1(GetIODirection() == IOD_READ);
00290 ASSERT1(destination != NULL);
00291 Uint32 const byte_count = 2;
00292 EnsureCacheIsOnByteBoundary();
00293 EnsureReadCacheHasEnoughBytesAvailable(byte_count);
00294 if (Error() != IOE_NONE)
00295 return;
00296 for (Uint8 *write_to = static_cast<Uint8 *>(destination),
00297 *read_from = m_cache + CacheByteIndex(),
00298 i = 0;
00299 i < byte_count;
00300 ++write_to, ++read_from, ++i)
00301 {
00302 *write_to = *read_from;
00303 }
00304 Endian::ConvertGivenToMachine2ByteWord(GetEndianness(), destination);
00305 IncrementCacheByteIndex(byte_count);
00306 ASSERT1(Error() == IOE_NONE);
00307 }
00308
00309 void BitCache::Write2ByteWordToCache (void *const source)
00310 {
00311 ASSERT1(IsOpen());
00312 ASSERT1(GetIODirection() == IOD_WRITE);
00313 ASSERT1(source != NULL);
00314 Uint32 const byte_count = 2;
00315 EnsureCacheIsOnByteBoundary();
00316 EnsureWriteCacheHasEnoughBytesAvailable(byte_count);
00317 if (Error() != IOE_NONE)
00318 return;
00319 Endian::ConvertMachineToGiven2ByteWord(source, GetEndianness());
00320 for (Uint8 *write_to = m_cache + CacheByteIndex(),
00321 *read_from = static_cast<Uint8 *>(source),
00322 i = 0;
00323 i < byte_count;
00324 ++write_to, ++read_from, ++i)
00325 {
00326 *write_to = *read_from;
00327 }
00328 IncrementCacheByteIndex(byte_count);
00329 ASSERT1(Error() == IOE_NONE);
00330 }
00331
00332 void BitCache::Read4ByteWordFromCache (void *const destination)
00333 {
00334 ASSERT1(IsOpen());
00335 ASSERT1(GetIODirection() == IOD_READ);
00336 ASSERT1(destination != NULL);
00337 Uint32 const byte_count = 4;
00338 EnsureCacheIsOnByteBoundary();
00339 EnsureReadCacheHasEnoughBytesAvailable(byte_count);
00340 if (Error() != IOE_NONE)
00341 return;
00342 for (Uint8 *write_to = static_cast<Uint8 *>(destination),
00343 *read_from = m_cache + CacheByteIndex(),
00344 i = 0;
00345 i < byte_count;
00346 ++write_to, ++read_from, ++i)
00347 {
00348 *write_to = *read_from;
00349 }
00350 Endian::ConvertGivenToMachine4ByteWord(GetEndianness(), destination);
00351 IncrementCacheByteIndex(byte_count);
00352 ASSERT1(Error() == IOE_NONE);
00353 }
00354
00355 void BitCache::Write4ByteWordToCache (void *const source)
00356 {
00357 ASSERT1(IsOpen());
00358 ASSERT1(GetIODirection() == IOD_WRITE);
00359 ASSERT1(source != NULL);
00360 Uint32 const byte_count = 4;
00361 EnsureCacheIsOnByteBoundary();
00362 EnsureWriteCacheHasEnoughBytesAvailable(byte_count);
00363 if (Error() != IOE_NONE)
00364 return;
00365 Endian::ConvertMachineToGiven4ByteWord(source, GetEndianness());
00366 for (Uint8 *write_to = m_cache + CacheByteIndex(),
00367 *read_from = static_cast<Uint8 *>(source),
00368 i = 0;
00369 i < byte_count;
00370 ++write_to, ++read_from, ++i)
00371 {
00372 *write_to = *read_from;
00373 }
00374 IncrementCacheByteIndex(byte_count);
00375 ASSERT1(Error() == IOE_NONE);
00376 }
00377
00378 void BitCache::Read8ByteWordFromCache (void *const destination)
00379 {
00380 ASSERT1(IsOpen());
00381 ASSERT1(GetIODirection() == IOD_READ);
00382 ASSERT1(destination != NULL);
00383 Uint32 const byte_count = 8;
00384 EnsureCacheIsOnByteBoundary();
00385 EnsureReadCacheHasEnoughBytesAvailable(byte_count);
00386 if (Error() != IOE_NONE)
00387 return;
00388 for (Uint8 *write_to = static_cast<Uint8 *>(destination),
00389 *read_from = m_cache + CacheByteIndex(),
00390 i = 0;
00391 i < byte_count;
00392 ++write_to, ++read_from, ++i)
00393 {
00394 *write_to = *read_from;
00395 }
00396 Endian::ConvertGivenToMachine8ByteWord(GetEndianness(), destination);
00397 IncrementCacheByteIndex(byte_count);
00398 ASSERT1(Error() == IOE_NONE);
00399 }
00400
00401 void BitCache::Write8ByteWordToCache (void *const source)
00402 {
00403 ASSERT1(IsOpen());
00404 ASSERT1(GetIODirection() == IOD_WRITE);
00405 ASSERT1(source != NULL);
00406 Uint32 const byte_count = 8;
00407 EnsureCacheIsOnByteBoundary();
00408 EnsureWriteCacheHasEnoughBytesAvailable(byte_count);
00409 if (Error() != IOE_NONE)
00410 return;
00411 Endian::ConvertMachineToGiven8ByteWord(source, GetEndianness());
00412 for (Uint8 *write_to = m_cache + CacheByteIndex(),
00413 *read_from = static_cast<Uint8 *>(source),
00414 i = 0;
00415 i < byte_count;
00416 ++write_to, ++read_from, ++i)
00417 {
00418 *write_to = *read_from;
00419 }
00420 IncrementCacheByteIndex(byte_count);
00421 ASSERT1(Error() == IOE_NONE);
00422 }
00423
00424 void BitCache::ReadBytes (
00425 Uint8 *const destination,
00426 Uint32 const destination_size)
00427 {
00428 ASSERT1(destination != NULL);
00429 ASSERT1(destination_size > 0);
00430 ASSERT1(destination_size <= m_working_cache_size_in_bytes);
00431
00432 EnsureCacheIsOnByteBoundary();
00433 EnsureReadCacheHasEnoughBytesAvailable(destination_size);
00434 if (Error() != IOE_NONE)
00435 return;
00436
00437 memcpy(destination, m_cache + CacheByteIndex(), destination_size);
00438 IncrementCacheByteIndex(destination_size);
00439 ASSERT1(Error() == IOE_NONE);
00440 }
00441
00442 void BitCache::WriteBytes (
00443 Uint8 const *const source,
00444 Uint32 const source_size)
00445 {
00446 ASSERT1(source != NULL);
00447 ASSERT1(source_size > 0);
00448 ASSERT1(source_size <= m_working_cache_size_in_bytes);
00449
00450 EnsureCacheIsOnByteBoundary();
00451 EnsureWriteCacheHasEnoughBytesAvailable(source_size);
00452 if (Error() != IOE_NONE)
00453 return;
00454
00455 memcpy(m_cache + CacheByteIndex(), source, source_size);
00456 IncrementCacheByteIndex(source_size);
00457 ASSERT1(Error() == IOE_NONE);
00458 }
00459
00460 Uint32 BitCache::ReadBufferString (
00461 char *const destination,
00462 Uint32 const destination_length)
00463 {
00464 ASSERT1(IsOpen());
00465 ASSERT1(GetIODirection() == IOD_READ);
00466 ASSERT1(destination != NULL);
00467 ASSERT1(destination_length > 0);
00468 ASSERT1(destination_length <= m_working_cache_size_in_bytes);
00469
00470 EnsureCacheIsOnByteBoundary();
00471 EnsureReadCacheHasEnoughBytesAvailable(destination_length);
00472
00473
00474
00475
00476
00477 if (Error() != IOE_NONE &&
00478 Error() != IOE_INSUFFICIENT_AVAILABLE_DATA)
00479 {
00480 *destination = '\0';
00481 return 0;
00482 }
00483
00484 char *destination_it = destination;
00485 Uint32 chars_read_count = 0;
00486
00487 while (CacheByteIndex() < m_next_available_cache_byte_index &&
00488 chars_read_count < destination_length - 1 &&
00489 m_cache[CacheByteIndex()] != '\0')
00490 {
00491 *destination_it = m_cache[CacheByteIndex()];
00492 ++destination_it;
00493 ++chars_read_count;
00494 IncrementCacheByteIndex(1);
00495 }
00496
00497 ASSERT1(destination + chars_read_count == destination_it);
00498 *destination_it = '\0';
00499 if (m_cache[CacheByteIndex()] != '\0')
00500 {
00501 IncrementCacheByteIndex(1);
00502 SetError(IOE_OVERSIZED_STRING);
00503 }
00504 else if (CacheByteIndex() == m_next_available_cache_byte_index)
00505 {
00506 SetError(IOE_INSUFFICIENT_AVAILABLE_DATA);
00507 }
00508 else
00509 {
00510 IncrementCacheByteIndex(1);
00511 SetError(IOE_NONE);
00512 }
00513
00514 return chars_read_count;
00515 }
00516
00517 Uint32 BitCache::WriteBufferString (
00518 char const *const source,
00519 Uint32 const source_length)
00520 {
00521 ASSERT1(IsOpen());
00522 ASSERT1(GetIODirection() == IOD_WRITE);
00523 ASSERT1(source_length > 0);
00524 ASSERT1(source_length <= m_working_cache_size_in_bytes);
00525 ASSERT1(source != NULL);
00526
00527 EnsureCacheIsOnByteBoundary();
00528 EnsureWriteCacheHasEnoughBytesAvailable(source_length);
00529 if (Error() != IOE_NONE)
00530 return 0;
00531
00532 char const *source_it = source;
00533 char *destination =
00534 reinterpret_cast<char *>(m_cache + CacheByteIndex());
00535 Uint32 chars_written_count = 0;
00536
00537 while (chars_written_count < source_length - 1 && *source_it != '\0')
00538 {
00539 *destination = *source_it;
00540 ++source_it;
00541 ++destination;
00542 ++chars_written_count;
00543 }
00544
00545 ASSERT1(source + chars_written_count == source_it);
00546 *destination = '\0';
00547 ++chars_written_count;
00548 if (*source_it != '\0')
00549 SetError(IOE_OVERSIZED_STRING);
00550 else
00551 SetError(IOE_NONE);
00552
00553 IncrementCacheByteIndex(chars_written_count);
00554
00555
00556 return chars_written_count - 1;
00557 }
00558
00559 void BitCache::FlushWriteCache ()
00560 {
00561 if (CacheByteIndex() > 0)
00562 {
00563 EnsureCacheIsOnByteBoundary();
00564 Uint32 bytes_written = FlushBytes(m_cache, CacheByteIndex());
00565 if (bytes_written == CacheByteIndex())
00566 SetError(IOE_NONE);
00567 else
00568 SetError(IOE_INSUFFICIENT_STORAGE);
00569
00570 m_cache_bit_index -= bytes_written << 3;
00571 }
00572 else
00573 SetError(IOE_NONE);
00574 }
00575
00576 void BitCache::EnsureReadCacheHasEnoughBitsAvailable (
00577 Uint32 const requested_bit_count) const
00578 {
00579 ASSERT1(GetIODirection() == IOD_READ);
00580 ASSERT1(requested_bit_count > 0);
00581 ASSERT1(requested_bit_count <= m_working_cache_size_in_bits);
00582
00583
00584 if (m_cache_bit_index + requested_bit_count
00585 <=
00586 (m_next_available_cache_byte_index << 3))
00587 {
00588 SetError(IOE_NONE);
00589 return;
00590 }
00591
00592
00593 memmove(m_cache,
00594 m_cache + CacheByteIndex(),
00595 m_next_available_cache_byte_index - CacheByteIndex());
00596 m_next_available_cache_byte_index -= CacheByteIndex();
00597 m_cache_bit_index &= 7;
00598
00599 Uint32 bytes_read =
00600 RenewBytes(m_cache + m_next_available_cache_byte_index,
00601 m_actual_cache_size_in_bytes - m_next_available_cache_byte_index);
00602
00603 m_next_available_cache_byte_index += bytes_read;
00604 ASSERT1(m_next_available_cache_byte_index <= m_actual_cache_size_in_bytes);
00605
00606
00607 if (m_cache_bit_index + requested_bit_count
00608 <=
00609 (m_next_available_cache_byte_index << 3))
00610 {
00611 SetError(IOE_NONE);
00612 }
00613
00614 else if (m_next_available_cache_byte_index < m_actual_cache_size_in_bytes &&
00615 m_cache_bit_index == m_next_available_cache_byte_index << 3)
00616 SetError(IOE_IS_AT_END);
00617 else
00618 SetError(IOE_INSUFFICIENT_AVAILABLE_DATA);
00619 }
00620
00621 void BitCache::EnsureReadCacheHasEnoughBytesAvailable (
00622 Uint32 const requested_byte_count) const
00623 {
00624 ASSERT1(IsCacheBitIndexOnByteBoundary());
00625 EnsureReadCacheHasEnoughBitsAvailable(requested_byte_count << 3);
00626 }
00627
00628 void BitCache::EnsureWriteCacheHasEnoughBitsAvailable (
00629 Uint32 const requested_bit_count) const
00630 {
00631 ASSERT1(GetIODirection() == IOD_WRITE);
00632 ASSERT1(requested_bit_count > 0);
00633 ASSERT1(requested_bit_count <= m_working_cache_size_in_bits);
00634
00635
00636 if (m_cache_bit_index + requested_bit_count <= m_actual_cache_size_in_bits)
00637 {
00638 SetError(IOE_NONE);
00639 return;
00640 }
00641
00642
00643 Uint32 bytes_written = FlushBytes(m_cache, CacheByteIndex());
00644 if (bytes_written == CacheByteIndex())
00645 SetError(IOE_NONE);
00646 else
00647 SetError(IOE_INSUFFICIENT_STORAGE);
00648
00649
00650 memmove(m_cache, m_cache + bytes_written, m_actual_cache_size_in_bytes);
00651
00652 m_cache_bit_index -= bytes_written << 3;
00653 }
00654
00655 void BitCache::EnsureWriteCacheHasEnoughBytesAvailable (
00656 Uint32 const requested_byte_count) const
00657 {
00658 ASSERT1(IsCacheBitIndexOnByteBoundary());
00659 EnsureWriteCacheHasEnoughBitsAvailable(requested_byte_count << 3);
00660 }
00661
00662 void BitCache::OpenForReading ()
00663 {
00664 ASSERT1(!IsOpen());
00665 ASSERT1(GetIODirection() == IOD_NONE);
00666
00667 m_cache_bit_index = 0;
00668 m_next_available_cache_byte_index = 0;
00669 SetIsOpen(true);
00670 SetIODirection(IOD_READ);
00671 SetError(IOE_NONE);
00672 }
00673
00674 void BitCache::OpenForWriting ()
00675 {
00676 ASSERT1(!IsOpen());
00677 ASSERT1(GetIODirection() == IOD_NONE);
00678
00679 m_cache_bit_index = 0;
00680 m_next_available_cache_byte_index = m_actual_cache_size_in_bytes + 1;
00681
00682 ASSERT1(m_next_available_cache_byte_index > m_actual_cache_size_in_bytes);
00683
00684 SetIsOpen(true);
00685 SetIODirection(IOD_WRITE);
00686 SetError(IOE_NONE);
00687 }
00688
00689 void BitCache::Close ()
00690 {
00691 ASSERT1(IsOpen());
00692 ASSERT1(GetIODirection() == IOD_READ ||
00693 GetIODirection() == IOD_WRITE);
00694
00695 if (GetIODirection() == IOD_WRITE)
00696 FlushWriteCache();
00697
00698 SetIsOpen(false);
00699 SetIODirection(IOD_NONE);
00700 SetError(IOE_NONE);
00701 }
00702
00703 }