25#include <wx/filename.h>
35 if( !wxGetEnv( wxT(
"KICAD_DRC_BENCH_CORPUS" ), &root ) || root.IsEmpty() )
38 return wxFileName::DirExists( root );
46 if( !wxGetEnv( wxT(
"KICAD_DRC_BENCH_CORPUS" ), &root ) )
56 if( aRelative.IsEmpty() )
59 wxFileName fn( aRelative );
62 return fn.GetFullPath();
64 wxFileName resolved( aRoot, wxEmptyString );
65 resolved.SetFullName( wxEmptyString );
67 wxFileName joined( aRoot + wxFileName::GetPathSeparator() + aRelative );
68 joined.MakeAbsolute();
70 return joined.GetFullPath();
74bool CORPUS::Load( std::vector<CORPUS_ENTRY>& aEntries, wxString& aError )
82 wxString root =
Root();
83 wxFileName manifest( root, wxT(
"corpus.json" ) );
85 if( !manifest.Exists() )
87 aError = wxString::Format( wxT(
"corpus.json not found in %s" ), root );
91 std::ifstream in( manifest.GetFullPath().fn_str() );
95 aError = wxString::Format( wxT(
"cannot open %s" ), manifest.GetFullPath() );
99 std::stringstream buffer;
100 buffer << in.rdbuf();
106 doc = nlohmann::json::parse( buffer.str() );
108 catch(
const std::exception& e )
110 aError = wxString::Format( wxT(
"corpus.json parse error: %s" ), e.what() );
114 if( !doc.is_array() )
116 aError = wxT(
"corpus.json must be a JSON array of entries" );
120 for(
const nlohmann::json& node : doc )
122 if( !node.is_object() || !node.contains(
"board" ) )
127 auto getString = [&](
const char* aKey ) -> wxString
129 if( node.contains( aKey ) && node[aKey].is_string() )
130 return wxString::FromUTF8( node[aKey].get<std::string>().c_str() );
132 return wxEmptyString;
137 entry.
tier = getString(
"tier" );
138 entry.
source = getString(
"source" );
139 entry.
notes = getString(
"notes" );
141 if( node.contains(
"quick" ) && node[
"quick"].is_boolean() )
142 entry.
quick = node[
"quick"].get<
bool>();
144 aEntries.push_back( entry );
203 static const std::vector<DRC_CONSTRAINT_T> types = {
235 static const std::vector<wxString> names = {
236 wxT(
"intersectsCourtyard" ), wxT(
"intersectsFrontCourtyard" ),
237 wxT(
"intersectsBackCourtyard" ), wxT(
"insideCourtyard" ),
238 wxT(
"insideFrontCourtyard" ), wxT(
"insideBackCourtyard" ),
239 wxT(
"intersectsArea" ), wxT(
"enclosedByArea" ),
240 wxT(
"insideArea" ), wxT(
"getField" ),
241 wxT(
"hasNetclass" ), wxT(
"hasExactNetclass" ),
242 wxT(
"hasComponentClass" ), wxT(
"memberOf" ),
243 wxT(
"memberOfSheet" ), wxT(
"memberOfSheetOrChildren" ),
244 wxT(
"memberOfFootprint" ), wxT(
"memberOfGroup" ),
245 wxT(
"fromTo" ), wxT(
"inDiffPair" ),
246 wxT(
"isCoupledDiffPair" ), wxT(
"inNetChain" ),
247 wxT(
"inNetChainClass" ), wxT(
"hasNetChain" ),
248 wxT(
"existsOnLayer" ), wxT(
"isPlated" ),
249 wxT(
"isMicroVia" ), wxT(
"isBlindVia" ),
250 wxT(
"isBuriedVia" ), wxT(
"isBlindBuriedVia" )
259 std::vector<wxString> found;
265 size_t searchFrom = 0;
269 size_t pos = aRulesText.find(
name, searchFrom );
271 if( pos == wxString::npos )
274 size_t after = pos +
name.length();
276 while( after < aRulesText.length() && wxIsspace( aRulesText[after] ) )
279 if( after < aRulesText.length() && aRulesText[after] ==
'(' )
281 found.push_back(
name );
285 searchFrom = pos + 1;
static bool Load(std::vector< CORPUS_ENTRY > &aEntries, wxString &aError)
Parse <root>/corpus.json into resolved entries.
static bool IsConfigured()
True when KICAD_DRC_BENCH_CORPUS is set and names an existing directory.
static wxString Root()
The resolved corpus root, or an empty string when unconfigured.
const char * ConstraintTypeName(DRC_CONSTRAINT_T aType)
Human-readable token for a DRC_CONSTRAINT_T, matching the .kicad_dru keyword where one exists.
std::vector< wxString > ScanPredicatesInRules(const wxString &aRulesText)
Scan raw .kicad_dru text for occurrences of each registered predicate name.
const std::vector< wxString > & AllPredicateNames()
Every pcbexpr predicate registered in pcbexpr_functions.cpp, used for textual coverage scans.
static wxString resolveAgainstRoot(const wxString &aRoot, const wxString &aRelative)
Resolve a manifest-relative path against the corpus root and return an absolute path.
const std::vector< DRC_CONSTRAINT_T > & AllConstraintTypes()
Every DRC_CONSTRAINT_T the engine can carry rules for, in enum order, excluding NULL_CONSTRAINT.
@ ANNULAR_WIDTH_CONSTRAINT
@ BRIDGED_MASK_CONSTRAINT
@ COURTYARD_CLEARANCE_CONSTRAINT
@ VIA_DIAMETER_CONSTRAINT
@ ZONE_CONNECTION_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ NET_CHAIN_LENGTH_CONSTRAINT
@ VIA_DANGLING_CONSTRAINT
@ SOLDER_MASK_SLIVER_CONSTRAINT
@ NET_CHAIN_STUB_LENGTH_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ NET_CHAIN_RETURN_PATH_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
@ SOLDER_MASK_EXPANSION_CONSTRAINT
@ DIFF_PAIR_INTRA_SKEW_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
One board+rules pairing from the out-of-tree corpus manifest.
wxString tier
Free-form tier tag from the manifest (A/B/C).
wxString board
Absolute path to the .kicad_pcb.
wxString rules
Absolute path to the .kicad_dru, or empty for none.
wxString source
Provenance string for traceability.
wxString notes
Free-form annotation.
bool quick
Part of the fast iteration set selected by –quick.