36namespace fs = std::filesystem;
39fs::path
ExportOdb(
const BOARD& aBoard,
const fs::path& aDir,
const std::string& aUnits,
40 const std::string& aSigfig,
REPORTER* aReporter )
42 fs::create_directories( aDir );
49 std::map<std::string, UTF8> props;
50 props[
"units"] = aUnits;
51 props[
"sigfig"] = aSigfig;
53 odbExporter.
SaveBoard( wxString::FromUTF8( aDir.string() ),
const_cast<BOARD&
>( aBoard ), &props );
59std::vector<std::string>
ReadLines(
const fs::path& aFile )
61 std::vector<std::string> lines;
62 std::ifstream stream( aFile );
65 while( std::getline( stream, line ) )
66 lines.push_back( line );
74 static std::vector<std::unique_ptr<KI_TEST::SCOPED_TEMP_DIR>> dirs;
75 dirs.emplace_back( std::make_unique<KI_TEST::SCOPED_TEMP_DIR>( wxS(
"odb_attributes" ) ) );
86 for(
const PAD*
pad : footprint->Pads() )
88 if(
pad->GetProperty() == aProperty &&
pad->IsOnLayer( aLayer ) )
99 for(
const std::string& line :
ReadLines( aFile ) )
101 if( line.rfind(
"@", 0 ) == 0 )
103 size_t space = line.find(
' ' );
105 if( space != std::string::npos )
106 m_names.emplace( line.substr( space + 1 ), line.substr( 1, space - 1 ) );
108 else if( line.rfind(
"CMP ", 0 ) == 0
109 || ( line.size() > 2 && line[1] ==
' '
110 && ( line[0] ==
'P' || line[0] ==
'L' || line[0] ==
'A' || line[0] ==
'S' ) ) )
120 static const std::map<std::string, std::vector<std::string>> options = {
121 {
".pad_usage", {
"toeprint",
"via",
"g_fiducial",
"l_fiducial",
"tooling_hole",
"bond_finger" } },
122 {
".drill", {
"plated",
"non_plated",
"via" } },
123 {
".plated_type", {
"standard",
"press_fit" } },
124 {
".via_type", {
"drilled",
"laser",
"photo" } },
125 {
".comp_mount_type", {
"other",
"smd",
"tht",
"pressfit" } }
128 auto found = options.find( aName );
130 if( found == options.end() )
133 const auto& values = found->second;
134 auto option = std::find( values.begin(), values.end(), aOption );
136 if( option == values.end() )
164 for(
const std::string& record :
m_records )
166 size_t start = record.find(
';' );
168 if( start == std::string::npos )
171 std::stringstream attributes( record.substr( start + 1 ) );
172 std::string attribute;
174 while( std::getline( attributes, attribute,
',' ) )
176 if( attribute ==
name->second + ( aValue.empty() ?
"" :
"=" + aValue ) )
194 FILE_LINE_READER reader( wxString::FromUTF8( ( aRoot /
"matrix" /
"matrix" ).
string() ) );
196 while(
const char* line = reader.
ReadLine() )
198 wxString
text = wxString::FromUTF8( line ).Strip( wxString::both );
200 if(
text.EndsWith( wxS(
"{" ) ) )
202 block =
text.BeforeLast(
'{' ).Strip( wxString::both );
207 if(
text == wxS(
"}" ) )
209 if( block == wxS(
"LAYER" ) )
216 wxString key =
text.BeforeFirst(
'=' ).Strip( wxString::both );
217 wxString value =
text.AfterFirst(
'=' ).Strip( wxString::both );
219 if( block == wxS(
"STEP" ) && key == wxS(
"NAME" ) && stepName.IsEmpty() )
223 else if( block == wxS(
"LAYER" ) )
225 if( key == wxS(
"ROW" ) )
226 row.
m_row = wxAtoi( value );
227 else if( key == wxS(
"CONTEXT" ) )
229 else if( key == wxS(
"TYPE" ) )
231 else if( key == wxS(
"NAME" ) )
233 else if( key == wxS(
"POLARITY" ) )
235 else if( key == wxS(
"START_NAME" ) )
237 else if( key == wxS(
"END_NAME" ) )
239 else if( key == wxS(
"ADD_TYPE" ) )
241 else if( key == wxS(
"ID" ) )
243 else if( key == wxS(
"REF" ) )
245 else if( key == wxS(
"CU_TOP" ) )
247 else if( key == wxS(
"CU_BOTTOM" ) )
249 else if( key == wxS(
"DIELECTRIC_TYPE" ) )
256 for(
const fs::directory_entry& entry : fs::directory_iterator( aRoot /
"steps", ec ) )
258 if( entry.is_directory() && wxString::FromUTF8( entry.path().filename().string() ).IsSameAs( stepName,
false ) )
266 fs::path layersRoot =
m_stepDir /
"layers";
267 fs::path layerDir = layersRoot / aLayer.Lower().ToStdString();
270 for(
const fs::directory_entry& entry : fs::directory_iterator( layersRoot, ec ) )
272 if( entry.is_directory() && wxString::FromUTF8( entry.path().filename().string() ).IsSameAs( aLayer,
false ) )
273 layerDir = entry.path();
276 return wxString::FromUTF8( ( layerDir / aFile.ToStdString() ).string() );
Information pertinent to a Pcbnew printed circuit board.
const FOOTPRINTS & Footprints() const
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
virtual void SetReporter(REPORTER *aReporter)
Set an optional reporter for warnings/errors.
std::vector< ODB_MATRIX_ROW > m_matrix
std::filesystem::path m_stepDir
wxString LayerFile(const wxString &aLayer, const wxString &aFile) const
Path of a file in a layer directory, matched to the directory name without regard to case.
ODB_PRODUCT(const std::filesystem::path &aRoot)
std::map< std::string, std::string > m_names
std::vector< std::string > m_records
size_t CountRecordsWithInteger(const std::string &aName, int aValue) const
size_t CountRecordsWithOption(const std::string &aName, const std::string &aOption) const
OdbFeatureFile(const std::filesystem::path &aFile)
size_t CountRecordsWithValue(const std::string &aName, const std::string &aValue) const
size_t CountRecordsWithFlag(const std::string &aName) const
void SaveBoard(const wxString &aFileName, BOARD &aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
A pure virtual class used to derive REPORTER objects from.
PCB_LAYER_ID
A quick note on layer IDs:
size_t CountPads(const BOARD &aBoard, PAD_PROP aProperty, PCB_LAYER_ID aLayer)
fs::path ExportOdb(const BOARD &aBoard, const fs::path &aDir, const std::string &aUnits, const std::string &aSigfig, REPORTER *aReporter)
std::vector< std::string > ReadLines(const fs::path &aFile)
const KI_TEST::SCOPED_TEMP_DIR & TempDir()
std::vector< std::string > ReadLines(const std::filesystem::path &aFile)
Read a text file into one string per line, with no trailing newline characters.
PAD_PROP
The set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
One LAYER block of matrix/matrix.
wxString m_dielectricType