30#include <wx/filename.h>
43 const uint64_t FNV_PRIME = 0x00000100000001B3ULL;
44 const uint64_t FNV_OFFSET = 0xcbf29ce484222325ULL;
47 uint64_t hash1 = FNV_OFFSET;
48 uint64_t hash2 = FNV_OFFSET;
51 std::string salt1 =
"PADS1:" + aIdentifier;
55 hash1 ^=
static_cast<uint8_t
>( c );
60 std::string salt2 =
"PADS2:" + aIdentifier;
64 hash2 ^=
static_cast<uint8_t
>( c );
70 std::ostringstream ss;
71 ss << std::hex << std::setfill(
'0' );
74 ss << std::setw( 8 ) << ( hash1 >> 32 );
78 ss << std::setw( 4 ) << ( ( hash1 >> 16 ) & 0xFFFF );
82 uint16_t version = ( ( hash1 & 0xFFFF ) & 0x0FFF ) | 0x4000;
83 ss << std::setw( 4 ) << version;
87 uint16_t variant = ( ( hash2 >> 48 ) & 0x3FFF ) | 0x8000;
88 ss << std::setw( 4 ) << variant;
92 ss << std::setw( 12 ) << ( hash2 & 0xFFFFFFFFFFFFULL );
94 return KIID( ss.str() );
100 std::ifstream file( aFilePath.fn_str() );
102 if( !file.is_open() )
107 if( !std::getline( file, line ) )
113 if( line.rfind(
"*PADS-POWERPCB", 0 ) == 0
114 || line.rfind(
"!PADS-POWERPCB", 0 ) == 0 )
119 if( line.rfind(
"*PADS2000", 0 ) == 0
120 || line.rfind(
"!PADS2000", 0 ) == 0 )
128 if( line.rfind(
"*PADS-POWERLOGIC", 0 ) == 0
129 || line.rfind(
"!PADS-POWERLOGIC", 0 ) == 0 )
132 if( line.rfind(
"*PADS-LOGIC", 0 ) == 0
133 || line.rfind(
"!PADS-LOGIC", 0 ) == 0 )
144 wxFileName sourceFn( aFilePath );
146 if( !sourceFn.IsOk() || !sourceFn.FileExists() )
156 result.pcbFile = aFilePath;
158 result.schematicFile = aFilePath;
160 wxString sourceDir = sourceFn.GetPath();
161 wxString sourceBase = sourceFn.GetName();
164 wxDir dir( sourceDir );
166 if( !dir.IsOpened() )
170 static const std::vector<wxString> extensions = { wxS(
"asc" ), wxS(
"ASC" ), wxS(
"txt" ),
174 bool cont = dir.GetFirst( &filename );
178 wxFileName candidateFn( sourceDir, filename );
179 wxString candidatePath = candidateFn.GetFullPath();
182 if( candidatePath == aFilePath )
184 cont = dir.GetNext( &filename );
189 wxString ext = candidateFn.GetExt().Lower();
190 bool validExt =
false;
192 for(
const wxString& validExtension : extensions )
194 if( ext == validExtension.Lower() )
203 cont = dir.GetNext( &filename );
208 bool matchingBase = ( candidateFn.GetName() == sourceBase );
216 if( matchingBase ||
result.schematicFile.IsEmpty() )
218 result.schematicFile = candidatePath;
223 cont = dir.GetNext( &filename );
232 if( matchingBase ||
result.pcbFile.IsEmpty() )
234 result.pcbFile = candidatePath;
239 cont = dir.GetNext( &filename );
245 cont = dir.GetNext( &filename );
251int ParseInt(
const std::string& aStr,
int aDefault,
const std::string& aContext )
255 return std::stoi( aStr );
257 catch(
const std::exception& )
259 if( !aContext.empty() )
261 wxLogTrace( wxT(
"PADS" ), wxT(
"Parse error in %s: '%s' is not a valid integer" ),
262 wxString::FromUTF8( aContext ), wxString::FromUTF8( aStr ) );
270double ParseDouble(
const std::string& aStr,
double aDefault,
const std::string& aContext )
274 return std::stod( aStr );
276 catch(
const std::exception& )
278 if( !aContext.empty() )
280 wxLogTrace( wxT(
"PADS" ), wxT(
"Parse error in %s: '%s' is not a valid number" ),
281 wxString::FromUTF8( aContext ), wxString::FromUTF8( aStr ) );
291 if( aNetName.empty() )
294 if( aNetName[0] ==
'/' )
295 return wxT(
"~{" ) + wxString::FromUTF8( aNetName.substr( 1 ) ) + wxT(
"}" );
297 return wxString::FromUTF8( aNetName );
308 wxString
result = wxString::FromUTF8( aText.data(), aText.size() );
312 wxCSConv cp1252( wxFONTENCODING_CP1252 );
313 result = wxString( aText.data(), cp1252, aText.size() );
317 result = wxString( aText.data(), wxConvISO8859_1, aText.size() );
326 int8_t s =
static_cast<int8_t
>( aPadsStyle & 0xFF );
348 if( aJustification >= 8 )
351 hCode = aJustification - 8;
353 else if( aJustification >= 2 )
356 hCode = aJustification - 2;
361 hCode = aJustification;
PADS_FILE_TYPE
Types of PADS files that can be detected.
@ PCB_ASCII
PADS PowerPCB ASCII (.asc)
@ SCHEMATIC_ASCII
PADS Logic ASCII (.asc or .txt)
void DecodeJustification(int aJustification, GR_TEXT_H_ALIGN_T &aHJustify, GR_TEXT_V_ALIGN_T &aVJustify)
Decode a PADS text justification code into KiCad horizontal and vertical alignment.
RELATED_FILES FindRelatedPadsFiles(const wxString &aFilePath)
Find related PADS project files from a given source file.
int ParseInt(const std::string &aStr, int aDefault, const std::string &aContext)
Parse integer from string with error context.
wxString ConvertText(const std::string &aText)
Decode text from a PADS file, which uses an 8-bit codepage rather than UTF-8.
PADS_FILE_TYPE DetectPadsFileType(const wxString &aFilePath)
Detect the type of a PADS file by examining its header.
wxString ConvertInvertedNetName(const std::string &aNetName)
Convert a PADS net name to KiCad format, handling inverted signal notation.
LINE_STYLE PadsLineStyleToKiCad(int aPadsStyle)
Convert a PADS line style integer to a KiCad LINE_STYLE enum value.
KIID GenerateDeterministicUuid(const std::string &aIdentifier)
Generate a deterministic KIID from a PADS component identifier.
double ParseDouble(const std::string &aStr, double aDefault, const std::string &aContext)
Parse double from string with error context.
Common utilities and types for parsing PADS file formats.
LINE_STYLE
Dashed line types.
wxString result
Test unit parsing edge cases and error handling.
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.