1 #include "ComponentsFile.h"
5 #include "ArchiveExtractor.h"
6 #include "../parse_error.h"
10 #include "../invalid_odb_error.h"
13 using namespace std::filesystem;
16 namespace Odb::Lib::FileModel::Design
18 ComponentsFile::ComponentsFile()
19 : m_id((unsigned int)-1)
20 , m_side(BoardSide::BsNone)
24 ComponentsFile::~ComponentsFile()
26 m_attributeNames.clear();
27 m_attributeTextValues.clear();
28 m_componentRecords.clear();
29 m_componentRecordsByName.clear();
30 m_bomDescriptionRecordsByCpn.clear();
33 std::string ComponentsFile::GetUnits()
const
38 BoardSide ComponentsFile::GetSide()
const
43 std::filesystem::path ComponentsFile::GetPath()
48 std::filesystem::path ComponentsFile::GetDirectory()
53 std::string ComponentsFile::GetLayerName()
const
58 const ComponentsFile::ComponentRecord::Vector& ComponentsFile::GetComponentRecords()
const
60 return m_componentRecords;
63 const ComponentsFile::ComponentRecord::StringMap& ComponentsFile::GetComponentRecordsByName()
const
65 return m_componentRecordsByName;
68 const std::vector<std::string>& ComponentsFile::GetAttributeNames()
const
70 return m_attributeNames;
73 const std::vector<std::string>& ComponentsFile::GetAttributeTextValues()
const
75 return m_attributeTextValues;
78 const ComponentsFile::BomDescriptionRecord::StringMap& ComponentsFile::GetBomDescriptionRecordsByCpn()
const
80 return m_bomDescriptionRecordsByCpn;
83 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile> ComponentsFile::to_protobuf()
const
85 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile> pComponentsFileMessage(
new Odb::Lib::Protobuf::ComponentsFile);
86 pComponentsFileMessage->set_units(m_units);
87 pComponentsFileMessage->set_id(m_id);
88 pComponentsFileMessage->set_side(
static_cast<Odb::Lib::Protobuf::BoardSide
>(m_side));
89 pComponentsFileMessage->set_layername(m_layerName);
90 pComponentsFileMessage->set_path(m_path.string());
91 pComponentsFileMessage->set_directory(m_directory.string());
93 for (
const auto& attributeName : m_attributeNames)
95 pComponentsFileMessage->add_attributenames(attributeName);
98 for (
const auto& attributeTextValue : m_attributeTextValues)
100 pComponentsFileMessage->add_attributetextvalues(attributeTextValue);
103 for (
const auto& pComponentRecord : m_componentRecords)
105 auto pComponentRecordMessage = pComponentRecord->to_protobuf();
106 pComponentsFileMessage->add_componentrecords()->CopyFrom(*pComponentRecordMessage);
109 for (
const auto& kvBomDescriptionRecord : m_bomDescriptionRecordsByCpn)
111 auto pBomDescriptionRecordMessage = kvBomDescriptionRecord.second->to_protobuf();
112 (*pComponentsFileMessage->mutable_bomdescriptionrecordsbycpn())[kvBomDescriptionRecord.first] = *pBomDescriptionRecordMessage;
115 return pComponentsFileMessage;
118 void ComponentsFile::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile& message)
120 m_units = message.units();
122 m_side =
static_cast<BoardSide
>(message.side());
123 m_layerName = message.layername();
124 m_path = message.path();
125 m_directory = message.directory();
127 for (
const auto& attributeName : message.attributenames())
129 m_attributeNames.push_back(attributeName);
132 for (
const auto& attributeTextValue : message.attributetextvalues())
134 m_attributeTextValues.push_back(attributeTextValue);
137 for (
const auto& componentRecordMessage : message.componentrecords())
139 auto pComponentRecord = std::make_shared<ComponentRecord>();
140 pComponentRecord->from_protobuf(componentRecordMessage);
141 m_componentRecords.push_back(pComponentRecord);
144 for (
const auto& kvBomDescriptionRecord : message.bomdescriptionrecordsbycpn())
146 auto pBomDescriptionRecord = std::make_shared<BomDescriptionRecord>();
147 pBomDescriptionRecord->from_protobuf(kvBomDescriptionRecord.second);
148 m_bomDescriptionRecordsByCpn[kvBomDescriptionRecord.first] = pBomDescriptionRecord;
152 bool ComponentsFile::Save(std::ostream& os)
157 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord> ComponentsFile::BomDescriptionRecord::to_protobuf()
const
159 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord> pBomDescriptionRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord);
160 pBomDescriptionRecordMessage->set_cpn(cpn);
161 pBomDescriptionRecordMessage->set_pkg(pkg);
162 pBomDescriptionRecordMessage->set_ipn(ipn);
163 for (
const auto& description : descriptions)
165 pBomDescriptionRecordMessage->add_descriptions()->assign(description);
167 pBomDescriptionRecordMessage->set_vpl_vnd(vpl_vnd);
168 pBomDescriptionRecordMessage->set_vpl_mpn(vpl_mpn);
169 pBomDescriptionRecordMessage->set_vnd(vnd);
170 pBomDescriptionRecordMessage->set_mpn(mpn);
171 return pBomDescriptionRecordMessage;
174 void ComponentsFile::BomDescriptionRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord& message)
179 for (
const auto& description : message.descriptions())
181 descriptions.push_back(description);
183 vpl_vnd = message.vpl_vnd();
184 vpl_mpn = message.vpl_mpn();
189 ComponentsFile::ComponentRecord::~ComponentRecord()
191 m_toeprintRecords.clear();
192 m_propertyRecords.clear();
195 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord> ComponentsFile::ComponentRecord::to_protobuf()
const
197 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord> pComponentRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::ComponentRecord);
198 pComponentRecordMessage->set_pkgref(pkgRef);
199 pComponentRecordMessage->set_locationx(locationX);
200 pComponentRecordMessage->set_locationy(locationY);
201 pComponentRecordMessage->set_rotation(rotation);
202 pComponentRecordMessage->set_mirror(mirror);
203 pComponentRecordMessage->set_compname(compName);
204 pComponentRecordMessage->set_partname(partName);
206 pComponentRecordMessage->set_index(index);
208 for (
const auto& pPropertyRecord : m_propertyRecords)
210 auto pPropertyRecordMessage = pPropertyRecord->to_protobuf();
211 pComponentRecordMessage->add_propertyrecords()->CopyFrom(*pPropertyRecordMessage);
214 for (
const auto& pToeprintRecord : m_toeprintRecords)
216 auto pToeprintRecordMessage = pToeprintRecord->to_protobuf();
217 pComponentRecordMessage->add_toeprintrecords()->CopyFrom(*pToeprintRecordMessage);
220 for (
const auto& kvAttributeAssignment : m_attributeLookupTable)
222 (*pComponentRecordMessage->mutable_attributelookuptable())[kvAttributeAssignment.first] = kvAttributeAssignment.second;
225 return pComponentRecordMessage;
228 void ComponentsFile::ComponentRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::ComponentRecord& message)
230 pkgRef = message.pkgref();
231 locationX = message.locationx();
232 locationY = message.locationy();
233 rotation = message.rotation();
234 mirror = message.mirror();
235 compName = message.compname();
236 partName = message.partname();
238 index = message.index();
240 for (
const auto& propertyRecordMessage : message.propertyrecords())
242 auto pPropertyRecord = std::make_shared<PropertyRecord>();
243 pPropertyRecord->from_protobuf(propertyRecordMessage);
244 m_propertyRecords.push_back(pPropertyRecord);
247 for (
const auto& toeprintRecordMessage : message.toeprintrecords())
249 auto pToeprintRecord = std::make_shared<ToeprintRecord>();
250 pToeprintRecord->from_protobuf(toeprintRecordMessage);
251 m_toeprintRecords.push_back(pToeprintRecord);
254 for (
const auto& kvAttributeAssignment : message.attributelookuptable())
256 m_attributeLookupTable[kvAttributeAssignment.first] = kvAttributeAssignment.second;
260 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord> ComponentsFile::ComponentRecord::ToeprintRecord::to_protobuf()
const
262 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord> pToeprintRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord);
263 pToeprintRecordMessage->set_pinnumber(pinNumber);
264 pToeprintRecordMessage->set_locationx(locationX);
265 pToeprintRecordMessage->set_locationy(locationY);
266 pToeprintRecordMessage->set_rotation(rotation);
267 pToeprintRecordMessage->set_mirror(mirror);
268 pToeprintRecordMessage->set_netnumber(netNumber);
269 pToeprintRecordMessage->set_subnetnumber(subnetNumber);
270 pToeprintRecordMessage->set_name(name);
271 return pToeprintRecordMessage;
274 void ComponentsFile::ComponentRecord::ToeprintRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord& message)
276 pinNumber = message.pinnumber();
277 locationX = message.locationx();
278 locationY = message.locationy();
279 rotation = message.rotation();
280 mirror = message.mirror();
281 netNumber = message.netnumber();
282 subnetNumber = message.subnetnumber();
283 name = message.name();
286 bool ComponentsFile::Parse(std::filesystem::path directory)
288 std::ifstream componentsFile;
294 m_directory = directory;
296 m_layerName = m_directory.filename().string();
297 if (m_layerName == TOP_COMPONENTS_LAYER_NAME ||
298 m_layerName == BOTTOM_COMPONENTS_LAYER_NAME)
300 m_side = m_layerName == TOP_COMPONENTS_LAYER_NAME ?
310 loginfo(
"checking for extraction...");
312 std::filesystem::path componentsFilePath;
313 for (
const std::string componentsFilename : COMPONENTS_FILENAMES)
315 loginfo(
"trying components file: [" + componentsFilename +
"]...");
317 componentsFilePath = Utils::ArchiveExtractor::getUncompressedFilePath(m_directory, componentsFilename);
318 if (exists(componentsFilePath) && is_regular_file(componentsFilePath))
320 loginfo(
"found components file: [" + componentsFilePath.string() +
"]");
325 m_path = componentsFilePath;
327 loginfo(
"any extraction complete, parsing data...");
329 if (!std::filesystem::exists(m_path))
331 auto message =
"components file does not exist: [" + m_path.string() +
"]";
332 throw invalid_odb_error(message.c_str());
334 else if (!std::filesystem::is_regular_file(m_path))
336 auto message =
"components is not a file: [" + m_path.string() +
"]";
337 throw invalid_odb_error(message.c_str());
340 componentsFile.open(m_path.string(), std::ios::in);
341 if (!componentsFile.is_open())
343 auto message =
"unable to open components file: [" + m_path.string() +
"]";
344 throw invalid_odb_error(message.c_str());
347 std::shared_ptr<ComponentRecord> pCurrentComponentRecord;
348 std::shared_ptr<BomDescriptionRecord> pCurrentBomDescriptionRecord;
350 while (std::getline(componentsFile, line))
355 Utils::str_trim(line);
358 std::stringstream lineStream(line);
361 if (line.find(COMMENT_TOKEN) == 0)
365 else if (line.find(UNITS_TOKEN) == 0)
369 if (!std::getline(lineStream, token,
'='))
371 throw_parse_error(m_path, line, token, lineNumber);
373 else if (!std::getline(lineStream, token,
'='))
375 throw_parse_error(m_path, line, token, lineNumber);
380 else if (line.find(ID_TOKEN) == 0)
383 if (!std::getline(lineStream, token,
'='))
385 throw_parse_error(m_path, line, token, lineNumber);
387 else if (!std::getline(lineStream, token,
'='))
389 throw_parse_error(m_path, line, token, lineNumber);
391 m_id = std::stoul(token);
393 else if (line.find(ATTRIBUTE_NAME_TOKEN) == 0)
398 if (!std::getline(lineStream, token,
' '))
400 throw_parse_error(m_path, line, token, lineNumber);
402 else if (!std::getline(lineStream, token,
' '))
404 throw_parse_error(m_path, line, token, lineNumber);
406 m_attributeNames.push_back(token);
408 else if (line.find(ATTRIBUTE_VALUE_TOKEN) == 0)
412 if (!std::getline(lineStream, token,
' '))
414 throw_parse_error(m_path, line, token, lineNumber);
416 else if (!std::getline(lineStream, token,
' '))
418 throw_parse_error(m_path, line, token, lineNumber);
420 m_attributeTextValues.push_back(token);
422 else if (line.find(ComponentRecord::RECORD_TOKEN) == 0)
428 if (token != ComponentRecord::RECORD_TOKEN)
430 throw_parse_error(m_path, line, token, lineNumber);
433 if (pCurrentBomDescriptionRecord !=
nullptr)
436 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
437 pCurrentBomDescriptionRecord.reset();
441 if (pCurrentComponentRecord !=
nullptr)
444 m_componentRecords.push_back(pCurrentComponentRecord);
445 pCurrentComponentRecord.reset();
449 pCurrentComponentRecord = std::make_shared<ComponentRecord>();
451 lineStream >> pCurrentComponentRecord->pkgRef;
452 lineStream >> pCurrentComponentRecord->locationX;
453 lineStream >> pCurrentComponentRecord->locationY;
454 lineStream >> pCurrentComponentRecord->rotation;
457 lineStream >> mirror;
458 pCurrentComponentRecord->mirror = (mirror ==
'M');
460 lineStream >> pCurrentComponentRecord->compName;
461 lineStream >> pCurrentComponentRecord->partName;
464 if (m_componentRecords.size() > UINT_MAX)
466 throw_parse_error(m_path, line, token, lineNumber);
469 pCurrentComponentRecord->index =
static_cast<unsigned int>(m_componentRecords.size());
471 std::string attrIdString;
472 lineStream >> attrIdString;
474 if (!pCurrentComponentRecord->ParseAttributeLookupTable(attrIdString))
476 throw_parse_error(m_path, line, token, lineNumber);
479 else if (line.find(PropertyRecord::RECORD_TOKEN) == 0)
483 if (!(lineStream >> token))
485 throw_parse_error(m_path, line, token, lineNumber);
488 if (token != PropertyRecord::RECORD_TOKEN)
490 throw_parse_error(m_path, line, token, lineNumber);
493 auto pPropertyRecord = std::make_shared<PropertyRecord>();
495 if (!(lineStream >> pPropertyRecord->name))
497 throw_parse_error(m_path, line, token, lineNumber);
500 if (!(lineStream >> token))
502 throw_parse_error(m_path, line, token, lineNumber);
511 if (!(lineStream >> token))
513 throw_parse_error(m_path, line, token, lineNumber);
517 if (token.size() > 0 && token[0] ==
'\'')
523 if (token.size() > 0 && token[token.size() - 1] ==
'\'')
526 token.erase(token.size() - 1);
529 Utils::str_trim(token);
532 pPropertyRecord->value = token;
535 while (lineStream >> f)
537 pPropertyRecord->floatValues.push_back(f);
540 pCurrentComponentRecord->m_propertyRecords.push_back(pPropertyRecord);
542 else if (line.find(ComponentRecord::ToeprintRecord::RECORD_TOKEN) == 0)
547 if (token != ComponentRecord::ToeprintRecord::RECORD_TOKEN)
549 throw_parse_error(m_path, line, token, lineNumber);
552 auto pToeprintRecord = std::make_shared<ComponentRecord::ToeprintRecord>();
553 lineStream >> pToeprintRecord->pinNumber;
554 lineStream >> pToeprintRecord->locationX;
555 lineStream >> pToeprintRecord->locationY;
556 lineStream >> pToeprintRecord->rotation;
559 lineStream >> mirror;
560 pToeprintRecord->mirror = (mirror ==
'M' || mirror ==
'm');
562 lineStream >> pToeprintRecord->netNumber;
563 if (pToeprintRecord->netNumber == (
unsigned int)-1)
566 parse_info pi(m_path, line, lineNumber);
567 logdebug(pi.toString(
"Component Toeprint record with netNumber = -1"));
569 if (!m_allowToepintNetNumbersOfNegative1)
571 throw_parse_error(m_path, line, token, lineNumber);
575 lineStream >> pToeprintRecord->subnetNumber;
576 if (pToeprintRecord->subnetNumber == (
unsigned int)-1)
579 parse_info pi(m_path, line, lineNumber);
580 logdebug(pi.toString(
"Component Toeprint record with subnetNumber = -1"));
582 if (!m_allowToepintNetNumbersOfNegative1)
584 throw_parse_error(m_path, line, token, lineNumber);
588 lineStream >> pToeprintRecord->name;
590 pCurrentComponentRecord->m_toeprintRecords.push_back(pToeprintRecord);
592 else if (line.find(ComponentsFile::BomDescriptionRecord::CPN_RECORD_TOKEN) == 0)
598 if (token != ComponentsFile::BomDescriptionRecord::CPN_RECORD_TOKEN)
600 throw_parse_error(m_path, line, token, lineNumber);
603 if (pCurrentBomDescriptionRecord !=
nullptr)
605 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
606 pCurrentBomDescriptionRecord.reset();
609 pCurrentBomDescriptionRecord = std::make_shared<ComponentsFile::BomDescriptionRecord>();
611 else if (line.find(ComponentsFile::BomDescriptionRecord::IPN_RECORD_TOKEN) == 0)
615 if (token != ComponentsFile::BomDescriptionRecord::IPN_RECORD_TOKEN)
617 throw_parse_error(m_path, line, token, lineNumber);
620 if (pCurrentBomDescriptionRecord ==
nullptr)
622 throw_parse_error(m_path, line, token, lineNumber);
625 if (!(lineStream >> pCurrentBomDescriptionRecord->ipn))
631 else if (line.find(ComponentsFile::BomDescriptionRecord::DSC_RECORD_TOKEN) == 0)
635 if (token != ComponentsFile::BomDescriptionRecord::DSC_RECORD_TOKEN)
637 throw_parse_error(m_path, line, token, lineNumber);
640 if (pCurrentBomDescriptionRecord ==
nullptr)
642 throw_parse_error(m_path, line, token, lineNumber);
645 std::string description;
647 if (!(lineStream >> description))
653 pCurrentBomDescriptionRecord->descriptions.push_back(description);
655 else if (line.find(ComponentsFile::BomDescriptionRecord::VPL_VND_RECORD_TOKEN) == 0)
659 if (token != ComponentsFile::BomDescriptionRecord::VPL_VND_RECORD_TOKEN)
661 throw_parse_error(m_path, line, token, lineNumber);
664 if (pCurrentBomDescriptionRecord ==
nullptr)
666 throw_parse_error(m_path, line, token, lineNumber);
669 if (!(lineStream >> pCurrentBomDescriptionRecord->vpl_vnd))
671 throw_parse_error(m_path, line, token, lineNumber);
674 else if (line.find(ComponentsFile::BomDescriptionRecord::VPL_MPN_RECORD_TOKEN) == 0)
678 if (token != ComponentsFile::BomDescriptionRecord::VPL_MPN_RECORD_TOKEN)
680 throw_parse_error(m_path, line, token, lineNumber);
683 if (pCurrentBomDescriptionRecord ==
nullptr)
685 throw_parse_error(m_path, line, token, lineNumber);
688 if (!(lineStream >> pCurrentBomDescriptionRecord->vpl_mpn))
690 throw_parse_error(m_path, line, token, lineNumber);
693 else if (line.find(ComponentsFile::BomDescriptionRecord::VND_RECORD_TOKEN) == 0)
697 if (token != ComponentsFile::BomDescriptionRecord::VND_RECORD_TOKEN)
699 throw_parse_error(m_path, line, token, lineNumber);
702 if (pCurrentBomDescriptionRecord ==
nullptr)
704 throw_parse_error(m_path, line, token, lineNumber);
707 if (!(lineStream >> pCurrentBomDescriptionRecord->vnd))
709 throw_parse_error(m_path, line, token, lineNumber);
712 else if (line.find(ComponentsFile::BomDescriptionRecord::MPN_RECORD_TOKEN) == 0)
716 if (token != ComponentsFile::BomDescriptionRecord::MPN_RECORD_TOKEN)
718 throw_parse_error(m_path, line, token, lineNumber);
721 if (pCurrentBomDescriptionRecord ==
nullptr)
723 throw_parse_error(m_path, line, token, lineNumber);
726 if (!(lineStream >> pCurrentBomDescriptionRecord->mpn))
728 throw_parse_error(m_path, line, token, lineNumber);
738 if (pCurrentBomDescriptionRecord !=
nullptr)
741 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
742 pCurrentBomDescriptionRecord.reset();
746 if (pCurrentComponentRecord !=
nullptr)
749 m_componentRecords.push_back(pCurrentComponentRecord);
750 pCurrentComponentRecord.reset();
753 componentsFile.close();
755 catch (parse_error& pe)
757 auto m = pe.toString(
"Parse Error:");
759 componentsFile.close();
762 catch (std::exception& e)
764 parse_info pi(m_path, line, lineNumber);
765 const auto m = pi.toString();
766 logexception_msg(e, m);
767 componentsFile.close();