29#include <wx/strconv.h>
32static wxString
hexOf(
const uint8_t* aBytes,
size_t aCount )
36 for(
size_t i = 0; i < aCount; i++ )
37 out += wxString::Format( wxS(
"%02x" ), aBytes[i] );
44 m_data( static_cast<const uint8_t*>( aData ) ),
64 THROW_IO_ERRORF( wxS(
"OrCAD %s: nested deeper than %d levels" ), aWhat, MAX_NESTING );
98 THROW_IO_ERRORF( wxS(
"OrCAD stream: read of %zu bytes past end at 0x%zx (stream size 0x%zx)" ),
125 return static_cast<int16_t
>(
ReadU16() );
143 return static_cast<int32_t
>(
ReadU32() );
153 THROW_IO_ERRORF( wxS(
"OrCAD stream: string of length %u at 0x%zx exceeds stream" ), len, lenPos );
155 std::string s(
reinterpret_cast<const char*
>(
m_data +
m_offset ), len );
159 THROW_IO_ERRORF( wxS(
"OrCAD stream: string at 0x%zx missing NUL terminator" ), lenPos );
176 size_t end =
static_cast<const uint8_t*
>( nul ) -
m_data;
196 THROW_IO_ERRORF( wxS(
"OrCAD stream: skip of %zu bytes past end at 0x%zx (stream size 0x%zx)" ),
209 THROW_IO_ERRORF( wxS(
"OrCAD stream: seek past end to 0x%zx (stream size 0x%zx)" ), aOffset,
m_size );
233 return memcmp(
m_data + pos, aBytes, aCount ) == 0;
246 std::vector<uint8_t> got =
ReadBytes( aCount );
248 if( memcmp( got.data(), aBytes, aCount ) != 0 )
250 THROW_IO_ERRORF( wxS(
"OrCAD stream: expected %s got %s at 0x%zx (%s)" ),
251 hexOf( aBytes, aCount ),
252 hexOf( got.data(), aCount ),
261 Expect( &aValue, 1, aWhat );
285 return wxEmptyString;
287 wxString converted( aText.c_str(), wxCSConv( wxFONTENCODING_CP1252 ) );
289 if( converted.IsEmpty() )
290 converted = wxString::From8BitData( aText.c_str(), aText.size() );
293 converted.Replace( wxS(
"\r\n" ), wxS(
"\n" ) );
294 converted.Replace( wxS(
"\r" ), wxS(
"\n" ) );
302 return aChar >=
'A' && aChar <= 'Z' ? static_cast<char>( aChar -
'A' +
'a' ) : aChar;
308 std::string out( aText );
309 std::transform( out.begin(), out.end(), out.begin(),
orcadFold );
316 return aLeft.size() == aRight.size()
317 && std::equal( aLeft.begin(), aLeft.end(), aRight.begin(),
320 return orcadFold( a ) == orcadFold( b );
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 char orcadFold(char aChar)
static wxString hexOf(const uint8_t *aBytes, size_t aCount)
std::string OrcadLower(std::string_view aText)
Fold ASCII letters only.
wxString FromOrcadString(const std::string &aText)
Use an 8-bit fallback if Windows-1252 decoding fails.
bool OrcadIEquals(std::string_view aLeft, std::string_view aRight)
Case-insensitive comparison with the folding of OrcadLower.