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 ) ),
63 THROW_IO_ERRORF( wxS(
"OrCAD %s: nested deeper than %d levels" ), aWhat, MAX_NESTING );
97 THROW_IO_ERRORF( wxS(
"OrCAD stream: read of %zu bytes past end at 0x%zx (stream size 0x%zx)" ),
114 return static_cast<int8_t
>(
ReadU8() );
130 return static_cast<int16_t
>(
ReadU16() );
148 return static_cast<int32_t
>(
ReadU32() );
158 THROW_IO_ERRORF( wxS(
"OrCAD stream: string of length %u at 0x%zx exceeds stream" ), len, lenPos );
160 std::string s(
reinterpret_cast<const char*
>(
m_data +
m_offset ), len );
164 THROW_IO_ERRORF( wxS(
"OrCAD stream: string at 0x%zx missing NUL terminator" ), lenPos );
181 size_t end =
static_cast<const uint8_t*
>( nul ) -
m_data;
201 THROW_IO_ERRORF( wxS(
"OrCAD stream: skip of %zu bytes past end at 0x%zx (stream size 0x%zx)" ),
214 THROW_IO_ERRORF( wxS(
"OrCAD stream: seek past end to 0x%zx (stream size 0x%zx)" ), aOffset,
m_size );
238 return memcmp(
m_data + pos, aBytes, aCount ) == 0;
251 std::vector<uint8_t> got =
ReadBytes( aCount );
253 if( memcmp( got.data(), aBytes, aCount ) != 0 )
255 THROW_IO_ERRORF( wxS(
"OrCAD stream: expected %s got %s at 0x%zx (%s)" ),
256 hexOf( aBytes, aCount ),
257 hexOf( got.data(), aCount ),
266 Expect( &aValue, 1, aWhat );
290 return wxEmptyString;
292 wxString converted( aText.c_str(), wxCSConv( wxFONTENCODING_CP1252 ) );
294 if( converted.IsEmpty() )
295 converted = wxString::From8BitData( aText.c_str(), aText.size() );
298 converted.Replace( wxS(
"\r\n" ), wxS(
"\n" ) );
299 converted.Replace( wxS(
"\r" ), wxS(
"\n" ) );
LIMIT_GUARD(ORCAD_STREAM &aStream, size_t aEnd)
NEST_GUARD(ORCAD_STREAM &aStream, const wxString &aWhat)
static constexpr int MAX_NESTING
Nesting limit of the recursive readers; real files stay far below it.
void ExpectPreamble(const wxString &aWhat)
Consume the 4 preamble bytes; throws IO_ERROR naming aWhat when absent.
int PeekU8(size_t aAhead=0) const
– non-throwing lookahead ---------------------------------------------------—
void SkipOptionalPreambleBlock()
Legacy primitives have no trailing preamble.
bool AtPreamble(size_t aAhead=0) const
True when the 4 preamble bytes FF E4 5C 39 sit at cursor + aAhead.
uint8_t ReadU8()
– scalars (little-endian, bounds-checked, throw IO_ERROR on overrun) ----—
std::vector< uint8_t > ReadBytes(size_t aCount)
– buffers / cursor ---------------------------------------------------------—
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()
– strings ----------------------------------------------------------------—
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()
Consumes the NUL; throws IO_ERROR if no terminator remains.
bool PeekMatches(const uint8_t *aBytes, size_t aCount, size_t aAhead=0) const
Returns false if fewer than aCount bytes remain; does not advance the cursor.
void Seek(size_t aOffset)
Set the absolute cursor position; throws IO_ERROR when aOffset exceeds Size().
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)
– validated reads ------------------------------------------------------------—
#define THROW_IO_ERRORF(msg,...)
static wxString hexOf(const uint8_t *aBytes, size_t aCount)
wxString FromOrcadString(const std::string &aText)
Use an 8-bit fallback if Windows-1252 decoding fails.