27#include <wx/filename.h>
28#include <wx/translation.h>
39 FILE* fp = wxFopen( aFileName, wxT(
"rb" ) );
44 fseek( fp, 0, SEEK_END );
45 long len = ftell( fp );
55 static constexpr long MAX_FILE_SIZE = 1L << 30;
57 if( len > MAX_FILE_SIZE )
60 THROW_IO_ERRORF(
_(
"DipTrace file '%s' is too large (%ld bytes)." ), aFileName, len );
66 m_data.resize(
static_cast<size_t>( len ) );
74 fseek( fp, 0, SEEK_SET );
76 size_t bytesRead = fread(
m_data.data(), 1,
m_data.size(), fp );
79 if( bytesRead !=
m_data.size() )
94 if( aOffset >
m_data.size() )
132 int raw = (
static_cast<int>( p[0] ) << 16 )
133 | (
static_cast<int>( p[1] ) << 8 )
134 | (
static_cast<int>( p[2] ) );
146 unsigned int raw = (
static_cast<unsigned int>( p[0] ) << 24 )
147 | (
static_cast<unsigned int>( p[1] ) << 16 )
148 | (
static_cast<unsigned int>( p[2] ) << 8 )
149 | (
static_cast<unsigned int>( p[3] ) );
154 return static_cast<int>(
static_cast<int64_t
>( raw ) -
INT4_BIAS );
199 THROW_IO_ERRORF(
_(
"Unexpected end of file at offset 0x%06zX: need 3 bytes for int3, have %zu remaining." ),
205 int raw = (
static_cast<int>( p[0] ) << 16 )
206 | (
static_cast<int>( p[1] ) << 8 )
207 | (
static_cast<int>( p[2] ) );
216 THROW_IO_ERRORF(
_(
"Unexpected end of file at offset 0x%06zX: need 4 bytes for int4, have %zu remaining." ),
222 unsigned int raw = (
static_cast<unsigned int>( p[0] ) << 24 )
223 | (
static_cast<unsigned int>( p[1] ) << 16 )
224 | (
static_cast<unsigned int>( p[2] ) << 8 )
225 | (
static_cast<unsigned int>( p[3] ) );
228 return static_cast<int>(
static_cast<int64_t
>( raw ) -
INT4_BIAS );
246 return static_cast<int>(
static_cast<int64_t
>( aDipTraceCoord ) * 100 / 3 );
260 size_t aStart,
size_t aEnd )
const
262 if( aEnd == 0 || aEnd >
m_data.size() )
265 if( aStart >= aEnd || aPatternLen == 0 || aPatternLen > ( aEnd - aStart ) )
266 return std::string::npos;
268 auto it = std::search(
m_data.begin() + aStart,
271 aPattern + aPatternLen );
273 if( it ==
m_data.begin() + aEnd )
274 return std::string::npos;
276 return static_cast<size_t>( it -
m_data.begin() );
283 return std::string::npos;
287 wxMBConvUTF16BE conv;
291 size_t charCount = aStr.length();
292 std::vector<uint8_t> encoded( charCount * 2 );
294 for(
size_t i = 0; i < charCount; i++ )
297 encoded[i * 2] =
static_cast<uint8_t
>( ( ch >> 8 ) & 0xFF );
298 encoded[i * 2 + 1] =
static_cast<uint8_t
>( ch & 0xFF );
302 size_t matchPos =
FindPattern( encoded.data(), encoded.size(), aStart, aEnd );
304 if( matchPos == std::string::npos )
305 return std::string::npos;
309 return std::string::npos;
354 if( asciiOk && !utf16Ok )
356 else if( utf16Ok && !asciiOk )
370 int charCount = (
static_cast<int>( p[0] ) << 8 ) |
static_cast<int>( p[1] );
379 size_t byteCount =
static_cast<size_t>( charCount ) * 2;
385 wxMBConvUTF16BE conv;
404 size_t count =
static_cast<size_t>( byteCount );
409 wxString
result = wxString::From8BitData(
424 int charCount = (
static_cast<int>( p[0] ) << 8 ) |
static_cast<int>( p[1] );
429 aResult = wxString();
433 if( charCount < 0 || charCount > 500 )
439 size_t byteCount =
static_cast<size_t>( charCount ) * 2;
447 wxMBConvUTF16BE conv;
448 wxString candidate = wxString(
reinterpret_cast<const char*
>( &
m_data[
m_offset] ),
471 int byteCount = (
static_cast<int>( p[0] ) << 16 )
472 | (
static_cast<int>( p[1] ) << 8 )
473 | (
static_cast<int>( p[2] ) );
479 aResult = wxString();
483 if( byteCount < 0 || byteCount > 500 )
489 size_t count =
static_cast<size_t>( byteCount );
497 wxString candidate = wxString::From8BitData(
514 for(
size_t i = 0; i < aStr.length(); i++ )
518 if( ch ==
'\r' || ch ==
'\n' || ch ==
'\t' )
533 THROW_IO_ERRORF(
_(
"Unexpected end of file at offset 0x%06zX: need %zu bytes, have %zu remaining." ),
bool TryReadStringUTF16(wxString &aResult)
Attempt to read a UTF-16-BE string with validation.
size_t FindString(const wxString &aStr, size_t aStart, size_t aEnd) const
Search for a UTF-16-BE encoded string in the file data, including its two-byte length prefix.
int PeekInt3() const
Peek at the next 3-byte biased integer without advancing the position.
wxString ReadStringASCII()
Read a v37 legacy ASCII string: int3(byte_count) + raw ASCII bytes.
bool TryReadStringASCII(wxString &aResult)
Attempt to read a legacy ASCII string with validation.
void ReadBytes(uint8_t *aDst, size_t aCount)
Read a block of raw bytes into the caller's buffer.
int m_version
DipTrace format version.
void Skip(size_t aBytes)
Advance the read position by the given number of bytes.
uint8_t ReadByte()
Read a single unsigned byte and advance the position by 1.
size_t m_offset
Current read position (byte offset).
uint8_t PeekByte() const
Peek at the next byte without advancing the position.
void ThrowEOFError(size_t aBytesNeeded) const
Throw IO_ERROR with a message indicating a read past end of file.
void DetectStringEncoding(size_t aProbeOffset)
Detect the string encoding from the bytes at aProbeOffset, which must sit at the start of a non-empty...
STRING_ENCODING m_stringEncoding
Explicit string encoding override.
static bool IsPrintableString(const wxString &aStr)
Verify that all characters in aStr are printable or common whitespace (space, tab,...
void ReadColor(uint8_t &r, uint8_t &g, uint8_t &b)
Read a 3-byte RGB color value.
int ReadInt4()
Read a 4-byte big-endian biased integer (bias 1,000,000,000) and advance the position by 4.
int ReadInt3()
Read a 3-byte big-endian biased integer (bias 1,000,000) and advance the position by 3.
static int DipTraceToKiCadNm(int aDipTraceCoord)
Convert a DipTrace coordinate value (10 nm units) to KiCad nanometers.
size_t FindPattern(const uint8_t *aPattern, size_t aPatternLen, size_t aStart, size_t aEnd) const
Search for a byte pattern in the file data.
void SetOffset(size_t aOffset)
Set the read position to an absolute byte offset.
bool TryReadString(wxString &aResult)
Attempt to read a string at the current position.
wxString ReadStringUTF16()
Read a v39+ UTF-16-BE string: uint16-BE char count + UTF-16-BE data.
BINARY_READER(const wxString &aFileName)
Construct a reader by loading the given file into memory.
int PeekInt4() const
Peek at the next 4-byte biased integer without advancing the position.
static double DipTraceToMM(int aDipTraceCoord)
Convert a DipTrace coordinate value (10 nm units) to millimeters.
wxString ReadString()
Read a string using the configured encoding.
std::vector< uint8_t > m_data
Entire file contents loaded into memory.
#define THROW_IO_ERRORF(msg,...)
constexpr double DIPTRACE_COORD_TO_MM
DipTrace uses 762 units per mil (30 000 units per mm).
constexpr int MAX_STRING_CHARS
Maximum sane string length (in characters) accepted by the reader.
constexpr int INT4_BIAS
Bias value added to stored 4-byte unsigned integers.
constexpr int LEGACY_STRING_VERSION
Format version at or below which strings use the legacy ASCII encoding (int3 byte-count + raw ASCII b...
constexpr int INT3_BIAS
Bias value added to stored 3-byte unsigned integers.
wxString result
Test unit parsing edge cases and error handling.