28#include <wx/strconv.h>
31static wxString
hexOf(
const uint8_t* aBytes,
size_t aCount )
35 for(
size_t i = 0; i < aCount; i++ )
36 out += wxString::Format( wxS(
"%02x" ), aBytes[i] );
43 m_data( static_cast<const uint8_t*>( aData ) ),
60 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: read of %zu bytes past end at 0x%zx "
61 "(stream size 0x%zx)" ),
76 return static_cast<int8_t
>(
ReadU8() );
92 return static_cast<int16_t
>(
ReadU16() );
110 return static_cast<int32_t
>(
ReadU32() );
121 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: string of length %u at 0x%zx "
126 std::string s(
reinterpret_cast<const char*
>(
m_data +
m_offset ), len );
131 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: string at 0x%zx missing NUL "
150 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: unterminated string at 0x%zx" ),
154 size_t end =
static_cast<const uint8_t*
>( nul ) -
m_data;
174 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: skip of %zu bytes past end at 0x%zx "
175 "(stream size 0x%zx)" ),
201 return memcmp(
m_data + pos, aBytes, aCount ) == 0;
213 if( aAbsoluteOffset >
m_size || 4 >
m_size - aAbsoluteOffset )
225 for(
size_t pos = aFrom; pos + 4 <=
m_size; pos++ )
238 std::vector<uint8_t> got =
ReadBytes( aCount );
240 if( memcmp( got.data(), aBytes, aCount ) != 0 )
242 THROW_IO_ERROR( wxString::Format( wxS(
"OrCAD stream: expected %s got %s at 0x%zx (%s)" ),
243 hexOf( aBytes, aCount ),
hexOf( got.data(), aCount ),
251 Expect( &aValue, 1, aWhat );
275 return wxEmptyString;
277 wxString converted( aText.c_str(), wxCSConv( wxFONTENCODING_CP1252 ) );
279 if( converted.IsEmpty() )
280 converted = wxString::From8BitData( aText.c_str(), aText.size() );
283 converted.Replace( wxS(
"\r\n" ), wxS(
"\n" ) );
284 converted.Replace( wxS(
"\r" ), wxS(
"\n" ) );
void ExpectPreamble(const wxString &aWhat)
Consume the 4 preamble bytes; throws IO_ERROR naming aWhat when absent.
int PeekU8(size_t aAhead=0) const
Peek one byte at cursor + aAhead without advancing.
size_t FindPreamble(size_t aFrom) const
Find the next preamble at or after the given absolute offset.
void SkipOptionalPreambleBlock()
If the preamble sits at the cursor, consume it plus its u32 trailLen and the trailLen trailing bytes;...
bool AtPreamble(size_t aAhead=0) const
True when the 4 preamble bytes FF E4 5C 39 sit at cursor + aAhead.
static constexpr size_t npos
Returned by FindPreamble() when no further preamble exists.
bool HasPreambleAt(size_t aAbsoluteOffset) const
True when the preamble sits at the given absolute offset (false if out of range).
std::vector< uint8_t > ReadBytes(size_t aCount)
Read exactly aCount bytes; throws IO_ERROR on overrun.
void Skip(size_t aCount)
Advance the cursor; throws IO_ERROR when aCount exceeds the remaining bytes.
static constexpr uint8_t PREAMBLE[4]
Magic preceding every framed structure body: FF E4 5C 39.
std::string ReadLzt()
Read a length-prefixed zero-terminated string: u16 length, length content bytes, then a mandatory 0x0...
ORCAD_STREAM(const void *aData, size_t aLength)
void requireBytes(size_t aCount) const
Throw IO_ERROR unless aCount bytes remain at the cursor.
std::string ReadZt()
Read a bare zero-terminated string (no length prefix); consumes the NUL.
bool PeekMatches(const uint8_t *aBytes, size_t aCount, size_t aAhead=0) const
Compare aCount bytes at cursor + aAhead against aBytes without advancing.
void ExpectByte(uint8_t aValue, const wxString &aWhat)
Consume one byte and require the given value.
void Expect(const uint8_t *aBytes, size_t aCount, const wxString &aWhat)
Consume aCount bytes and require them to equal aBytes; throws IO_ERROR naming aWhat and showing expec...
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
wxString FromOrcadString(const std::string &aText)
Decode raw stream bytes (Windows-1252) into a wxString for UI/UX use.
static wxString hexOf(const uint8_t *aBytes, size_t aCount)