home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 15.7 KB | 530 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWCharIt.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FWCHARIT_H
- #include "FWCharIt.h"
- #endif
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWString
- #endif
-
- //========================================================================================
- // CLASS FW_CTextReader
- //========================================================================================
-
- #ifdef FW_DEBUG_TEXT_ITERATORS
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::ClassInvariants
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::ClassInvariants() const
- {
- if (fNext == 0)
- {
- // Must be in initial state, before first GetNextBuffer
- FW_ASSERT(fStart == 0);
- FW_ASSERT(fLimit == 0);
- FW_ASSERT(fBufferSum == 0);
- }
- else if (fNext == fLimit)
- {
- // Must be at end of data structure
- FW_ASSERT(fBufferSum == fByteLength);
- }
- else
- {
- FW_ASSERT(fBufferSum < fByteLength);
- if (fNext<fStart)
- {
- // Must be at position -1 (backup past beginning)
- FW_ASSERT(fBufferSum == 0);
- FW_ASSERT(fNext == fStart-1); // may not be correct anymore
- }
- else
- {
- // Must be somewhere in middle of stream
- FW_ASSERT(fStart <= fNext);
- FW_ASSERT(fNext <= fLimit);
- }
- }
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::FW_CTextReader
- //----------------------------------------------------------------------------------------
-
- FW_CTextReader::FW_CTextReader( const FW_Byte *chunk1Start,
- const FW_Byte *chunk1Limit,
- FW_ByteCount totalLength) :
- fStart(chunk1Start),
- fLimit(chunk1Limit),
- fNext(chunk1Start),
- fByteLength(totalLength),
- fBufferSum(0),
- fBytesPerChar(sizeof(FW_Char))
- {
- ClassInvariants();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::~FW_CTextReader
- //----------------------------------------------------------------------------------------
-
- FW_CTextReader::~FW_CTextReader()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::CharactersInBlock
- //----------------------------------------------------------------------------------------
-
- FW_CharacterCount FW_CTextReader::CharactersInBlock(const FW_Byte* last,
- const FW_Byte* first)
- {
- return (last-first)/fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetLength
- //----------------------------------------------------------------------------------------
-
- FW_CharacterCount FW_CTextReader::GetLength()
- {
- return fByteLength/fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetCharacterAndAdvance
- //----------------------------------------------------------------------------------------
-
- FW_Char FW_CTextReader::GetCharacterAndAdvance()
- {
- ClassInvariants();
- register FW_Char temp = PeekCharacter();
- if (temp != FW_kNulCharacter)
- Advance(1);
- ClassInvariants();
- return temp;
- }
-
- //----------------------------------------------------------------------------------------
- FW_LChar FW_CTextReader::GetCharacterAndAdvance(FW_ByteCount& bytesInChar)
- {
- ClassInvariants();
- register FW_LChar temp = PeekCharacter(bytesInChar);
- if (temp != FW_kNulCharacter)
- Advance(bytesInChar);
- ClassInvariants();
- return temp;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::BackupAndGetCharacter
- //----------------------------------------------------------------------------------------
-
- FW_Char FW_CTextReader::BackupAndGetCharacter()
- {
- ClassInvariants();
- Backup(1);
- ClassInvariants();
- return PeekCharacter();
- }
-
- //----------------------------------------------------------------------------------------
- FW_LChar FW_CTextReader::BackupAndGetCharacter(FW_ByteCount& bytesInChar)
- {
- ClassInvariants();
- Backup(fBytesPerChar);
- ClassInvariants();
- return PeekCharacter(bytesInChar);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::PeekCharacter
- //----------------------------------------------------------------------------------------
-
- FW_Char FW_CTextReader::PeekCharacter()
- {
- ClassInvariants();
-
- if (fNext>=fStart && fNext<fLimit)
- return *((FW_Char*)fNext); // default to one byte characters
- else
- return FW_kNulCharacter;
- }
-
- //----------------------------------------------------------------------------------------
- FW_LChar FW_CTextReader::PeekCharacter(FW_ByteCount& bytesInChar)
- {
- ClassInvariants();
- bytesInChar = fBytesPerChar;
-
- if (fNext>=fStart && fNext<fLimit)
- {
- FW_LChar ch = *((FW_Char*)fNext); // default to one byte characters
- if (fBytesPerChar == 2)
- ch = *((FW_WChar*)fNext);
- if (fBytesPerChar == 4)
- ch = *((FW_LChar*)fNext);
- return ch;
- }
- else
- return FW_kNulCharacter;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::Advance
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::Advance(FW_ByteCount delta)
- {
- ClassInvariants();
- FW_ASSERT(delta>=0);
- FW_ASSERT(delta+GetPosition() <= fByteLength);
- FW_ByteCount inThisBuf = BytesInBlock(fLimit, fNext);
- while (delta >= inThisBuf)
- {
- delta -= inThisBuf;
- fNext += inThisBuf;
- GetNextBuffer();
- inThisBuf = BytesInBlock(fLimit, fStart);
- }
- fNext += delta;
- ClassInvariants();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::Backup
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::Backup(FW_ByteCount delta)
- {
- ClassInvariants();
- FW_ASSERT(delta>=0);
- /* FW_ASSERT(delta<=GetPosition()); * doesn't allow backup at start */
-
- if (delta > 0)
- {
- if (fNext==fStart) // at the start of a buffer
- {
- GetPreviousBuffer();
- }
- else if (fNext == fLimit) // at the end of the last buffer
- { // subtract bytes that were added by GetNextBuffer
- fBufferSum -= BytesInBlock(fLimit, fStart);
- }
-
- FW_ByteCount inThisBuf = BytesInBlock(fNext, fStart);
- if (inThisBuf > 0)
- while (delta > inThisBuf)
- {
- delta -= inThisBuf;
- fNext = fStart;
- GetPreviousBuffer();
- inThisBuf = BytesInBlock(fNext, fStart);
- }
- fNext = PreviousByte(fNext, delta); // may backup before fStart (-1)
- ClassInvariants();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetNextBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::GetNextBuffer()
- {
- // ClassInvariants won't hold here.
- // This function is called to (among other things) restore class invariants.
- FW_ASSERT(fNext == fLimit); // Must hold, but violates invariants
- fBufferSum += BytesInBlock(fLimit, fStart);
- if (fBufferSum < fByteLength)
- {
- DoGetNextBuffer();
- fNext = fStart;
- }
- else
- {
- FW_ASSERT(fBufferSum == fByteLength);
- fNext = fLimit;
- }
- ClassInvariants();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetPreviousBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::GetPreviousBuffer()
- {
- ClassInvariants();
- if (fBufferSum == 0)
- {
- fNext = fStart;
- }
- else if (fBufferSum == fByteLength)
- {
- FW_ASSERT(fLimit == fNext);
- fBufferSum -= BytesInBlock(fLimit, fStart);
- }
- else
- {
- FW_ASSERT(fStart == fNext);
- DoGetPreviousBuffer();
- FW_ASSERT(fStart < fLimit);
- fBufferSum -= BytesInBlock(fLimit, fStart);
- FW_ASSERT(fBufferSum >= 0);
- fNext = fLimit;
- }
- // Invariants won't hold here
- // The calling function must modify fNext appropriately
- // Note that GetPreviousBuffer is a protected method,
- // so clients are not held responsible to restore invariants.
- // Also, subclasses shouldn't need to call this function directly.
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetPosition
- //----------------------------------------------------------------------------------------
-
- FW_ByteCount FW_CTextReader::GetPosition(FW_Boolean inChars)
- {
- ClassInvariants();
- FW_ByteCount result;
-
- if (fNext == fLimit)
- result = fBufferSum;
- else
- result = fBufferSum + (fNext - fStart);
-
- if (inChars)
- {
- result = BytesToChars(result);
- }
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::SetPosition
- //----------------------------------------------------------------------------------------
-
- void FW_CTextReader::SetPosition(FW_ByteCount position)
- {
- ClassInvariants();
- FW_ASSERT(position>=0);
- FW_ASSERT(position<=fByteLength);
- FW_ByteCount curPosition = GetPosition();
- if (position < curPosition)
- Backup(curPosition-position);
- else if (position > curPosition)
- Advance(position-curPosition);
- ClassInvariants();
- }
-
- //========================================================================================
- // CLASS FW_CTextWriter
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::FW_CTextWriter
- //----------------------------------------------------------------------------------------
-
- FW_CTextWriter::FW_CTextWriter(FW_Byte *chunk1Start,
- FW_Byte *chunk1Limit) :
- fStart(chunk1Start),
- fNext(chunk1Start),
- fLimit(chunk1Limit),
- fBufferSum(0),
- fBytesPerChar(sizeof(FW_Char))
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::~FW_CTextWriter
- //----------------------------------------------------------------------------------------
-
- FW_CTextWriter::~FW_CTextWriter()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::BytesToChars
- //----------------------------------------------------------------------------------------
-
- FW_CharacterCount FW_CTextWriter::BytesToChars(const FW_ByteCount bytes)
- {
- return bytes/fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::CharactersInBlock
- //----------------------------------------------------------------------------------------
-
- FW_CharacterCount FW_CTextWriter::CharactersInBlock(const FW_Byte* last,
- const FW_Byte* first)
- {
- return (last-first)/fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::FlushAndUpdateText
- //----------------------------------------------------------------------------------------
- void FW_CTextWriter::FlushAndUpdateText()
- {
- FlushBuffer(FALSE); // flush only what's left in the buffer
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::FlushBuffer
- //----------------------------------------------------------------------------------------
- void FW_CTextWriter::FlushBuffer(FW_Boolean flushAll)
- {
- FW_ByteCount bytesToFlush;
- if (flushAll)
- bytesToFlush = fLimit - fStart;
- else
- bytesToFlush = fNext - fStart;
-
- DoFlushBuffer(bytesToFlush);
- fBufferSum += bytesToFlush;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::PutCharacterAndAdvance
- //----------------------------------------------------------------------------------------
-
- void FW_CTextWriter::PutCharacterAndAdvance(FW_LChar character, FW_ByteCount bytesInChar)
- {
- if (fNext >= fLimit)
- FlushAndGetNextBuffer();
-
- if (bytesInChar == 0)
- bytesInChar = fBytesPerChar;
-
- if (bytesInChar == 1)
- *((FW_Char*)fNext) = character;
- else if (bytesInChar == 2)
- *((FW_WChar*)fNext) = character;
- else
- *((FW_LChar*)fNext) = character;
-
- fNext += bytesInChar;
- }
-
- //----------------------------------------------------------------------------------------
- void FW_CTextWriter::PutCharacterAndAdvance(FW_Char character)
- {
- if (fNext >= fLimit)
- FlushAndGetNextBuffer();
-
- *((FW_Char*)fNext) = character;
- fNext += 1;
- }
-
- //========================================================================================
- // CLASS FW_CMemoryReader
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryReader::FW_CMemoryReader
- //----------------------------------------------------------------------------------------
-
- FW_CMemoryReader::FW_CMemoryReader( const FW_Byte* buffer,
- FW_ByteCount bytes) :
- FW_CTextReader(buffer, buffer+bytes, bytes)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryReader::FW_CMemoryReader
- //----------------------------------------------------------------------------------------
-
- FW_CMemoryReader::FW_CMemoryReader( const FW_Char* buffer,
- FW_CharacterCount characters,
- FW_ByteCount bytesPerChar) :
- FW_CTextReader((FW_Byte*) buffer, ((FW_Byte*) buffer)+(characters*bytesPerChar), characters*bytesPerChar)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryReader::~FW_CMemoryReader
- //----------------------------------------------------------------------------------------
-
- FW_CMemoryReader::~FW_CMemoryReader()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryReader::DoGetNextBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CMemoryReader::DoGetNextBuffer()
- {
- FW_ASSERT(FALSE);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryReader::DoGetPreviousBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CMemoryReader::DoGetPreviousBuffer()
- {
- FW_ASSERT(FALSE);
- }
-
- //========================================================================================
- // CLASS FW_CMemoryWriter
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryWriter::FW_CMemoryWriter
- //----------------------------------------------------------------------------------------
-
- FW_CMemoryWriter::FW_CMemoryWriter(FW_Byte* buffer, FW_ByteCount capacity) :
- FW_CTextWriter(buffer, buffer+capacity)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryWriter::~FW_CMemoryWriter
- //----------------------------------------------------------------------------------------
-
- FW_CMemoryWriter::~FW_CMemoryWriter()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryWriter::DoFlushBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CMemoryWriter::DoFlushBuffer(FW_ByteCount bytesToFlush) // Override
- {
- FW_UNUSED(bytesToFlush);
- // Do nothing
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMemoryWriter::DoGetNextBuffer
- //----------------------------------------------------------------------------------------
-
- void FW_CMemoryWriter::DoGetNextBuffer() // Override
- {
- FW_ASSERT(FALSE); // Overfilled capacity of buffer!
- }
-
-