1 #include "ComponentsFile.h"
2 #include "ComponentsFile.h"
3 #include "ComponentsFile.h"
4 #include "ComponentsFile.h"
5 #include "ComponentsFile.h"
6 #include "ComponentsFile.h"
7 #include "ComponentsFile.h"
11 #include "ArchiveExtractor.h"
12 #include "../parse_error.h"
15 #include "str_utils.h"
16 #include "../invalid_odb_error.h"
19 using namespace std::filesystem;
22 namespace Odb::Lib::FileModel::Design
24 ComponentsFile::ComponentsFile()
25 : m_id((unsigned int)-1)
26 , m_side(BoardSide::BsNone)
30 ComponentsFile::~ComponentsFile()
32 m_attributeNames.clear();
33 m_attributeTextValues.clear();
34 m_componentRecords.clear();
35 m_componentRecordsByName.clear();
36 m_bomDescriptionRecordsByCpn.clear();
39 std::string ComponentsFile::GetUnits()
const
44 BoardSide ComponentsFile::GetSide()
const
49 std::filesystem::path ComponentsFile::GetPath()
54 std::filesystem::path ComponentsFile::GetDirectory()
59 std::string ComponentsFile::GetLayerName()
const
64 const ComponentsFile::ComponentRecord::Vector& ComponentsFile::GetComponentRecords()
const
66 return m_componentRecords;
69 const ComponentsFile::ComponentRecord::StringMap& ComponentsFile::GetComponentRecordsByName()
const
71 return m_componentRecordsByName;
74 const std::vector<std::string>& ComponentsFile::GetAttributeNames()
const
76 return m_attributeNames;
79 const std::vector<std::string>& ComponentsFile::GetAttributeTextValues()
const
81 return m_attributeTextValues;
84 const ComponentsFile::BomDescriptionRecord::StringMap& ComponentsFile::GetBomDescriptionRecordsByCpn()
const
86 return m_bomDescriptionRecordsByCpn;
89 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile> ComponentsFile::to_protobuf()
const
91 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile> pComponentsFileMessage(
new Odb::Lib::Protobuf::ComponentsFile);
92 pComponentsFileMessage->set_units(m_units);
93 pComponentsFileMessage->set_id(m_id);
94 pComponentsFileMessage->set_side(
static_cast<Odb::Lib::Protobuf::BoardSide
>(m_side));
95 pComponentsFileMessage->set_layername(m_layerName);
96 pComponentsFileMessage->set_path(m_path.string());
97 pComponentsFileMessage->set_directory(m_directory.string());
99 for (
const auto& attributeName : m_attributeNames)
101 pComponentsFileMessage->add_attributenames(attributeName);
104 for (
const auto& attributeTextValue : m_attributeTextValues)
106 pComponentsFileMessage->add_attributetextvalues(attributeTextValue);
109 for (
const auto& pComponentRecord : m_componentRecords)
111 auto pComponentRecordMessage = pComponentRecord->to_protobuf();
112 pComponentsFileMessage->add_componentrecords()->CopyFrom(*pComponentRecordMessage);
115 for (
const auto& kvBomDescriptionRecord : m_bomDescriptionRecordsByCpn)
117 auto pBomDescriptionRecordMessage = kvBomDescriptionRecord.second->to_protobuf();
118 (*pComponentsFileMessage->mutable_bomdescriptionrecordsbycpn())[kvBomDescriptionRecord.first] = *pBomDescriptionRecordMessage;
121 return pComponentsFileMessage;
124 void ComponentsFile::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile& message)
126 m_units = message.units();
128 m_side =
static_cast<BoardSide
>(message.side());
129 m_layerName = message.layername();
130 m_path = message.path();
131 m_directory = message.directory();
133 for (
const auto& attributeName : message.attributenames())
135 m_attributeNames.push_back(attributeName);
138 for (
const auto& attributeTextValue : message.attributetextvalues())
140 m_attributeTextValues.push_back(attributeTextValue);
143 for (
const auto& componentRecordMessage : message.componentrecords())
145 auto pComponentRecord = std::make_shared<ComponentRecord>();
146 pComponentRecord->from_protobuf(componentRecordMessage);
147 m_componentRecords.push_back(pComponentRecord);
150 for (
const auto& kvBomDescriptionRecord : message.bomdescriptionrecordsbycpn())
152 auto pBomDescriptionRecord = std::make_shared<BomDescriptionRecord>();
153 pBomDescriptionRecord->from_protobuf(kvBomDescriptionRecord.second);
154 m_bomDescriptionRecordsByCpn[kvBomDescriptionRecord.first] = pBomDescriptionRecord;
158 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord> ComponentsFile::BomDescriptionRecord::to_protobuf()
const
160 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord> pBomDescriptionRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord);
161 pBomDescriptionRecordMessage->set_cpn(cpn);
162 pBomDescriptionRecordMessage->set_pkg(pkg);
163 pBomDescriptionRecordMessage->set_ipn(ipn);
164 for (
const auto& description : descriptions)
166 pBomDescriptionRecordMessage->add_descriptions()->assign(description);
168 pBomDescriptionRecordMessage->set_vpl_vnd(vpl_vnd);
169 pBomDescriptionRecordMessage->set_vpl_mpn(vpl_mpn);
170 pBomDescriptionRecordMessage->set_vnd(vnd);
171 pBomDescriptionRecordMessage->set_mpn(mpn);
172 return pBomDescriptionRecordMessage;
175 void ComponentsFile::BomDescriptionRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::BomDescriptionRecord& message)
180 for (
const auto& description : message.descriptions())
182 descriptions.push_back(description);
184 vpl_vnd = message.vpl_vnd();
185 vpl_mpn = message.vpl_mpn();
190 ComponentsFile::ComponentRecord::~ComponentRecord()
192 m_toeprintRecords.clear();
193 m_propertyRecords.clear();
196 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord> ComponentsFile::ComponentRecord::to_protobuf()
const
198 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord> pComponentRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::ComponentRecord);
199 pComponentRecordMessage->set_pkgref(pkgRef);
200 pComponentRecordMessage->set_locationx(locationX);
201 pComponentRecordMessage->set_locationy(locationY);
202 pComponentRecordMessage->set_rotation(rotation);
203 pComponentRecordMessage->set_mirror(mirror);
204 pComponentRecordMessage->set_compname(compName);
205 pComponentRecordMessage->set_partname(partName);
207 pComponentRecordMessage->set_index(index);
209 for (
const auto& pPropertyRecord : m_propertyRecords)
211 auto pPropertyRecordMessage = pPropertyRecord->to_protobuf();
212 pComponentRecordMessage->add_propertyrecords()->CopyFrom(*pPropertyRecordMessage);
215 for (
const auto& pToeprintRecord : m_toeprintRecords)
217 auto pToeprintRecordMessage = pToeprintRecord->to_protobuf();
218 pComponentRecordMessage->add_toeprintrecords()->CopyFrom(*pToeprintRecordMessage);
221 for (
const auto& kvAttributeAssignment : m_attributeLookupTable)
223 (*pComponentRecordMessage->mutable_attributelookuptable())[kvAttributeAssignment.first] = kvAttributeAssignment.second;
226 return pComponentRecordMessage;
229 void ComponentsFile::ComponentRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::ComponentRecord& message)
231 pkgRef = message.pkgref();
232 locationX = message.locationx();
233 locationY = message.locationy();
234 rotation = message.rotation();
235 mirror = message.mirror();
236 compName = message.compname();
237 partName = message.partname();
239 index = message.index();
241 for (
const auto& propertyRecordMessage : message.propertyrecords())
243 auto pPropertyRecord = std::make_shared<PropertyRecord>();
244 pPropertyRecord->from_protobuf(propertyRecordMessage);
245 m_propertyRecords.push_back(pPropertyRecord);
248 for (
const auto& toeprintRecordMessage : message.toeprintrecords())
250 auto pToeprintRecord = std::make_shared<ToeprintRecord>();
251 pToeprintRecord->from_protobuf(toeprintRecordMessage);
252 m_toeprintRecords.push_back(pToeprintRecord);
255 for (
const auto& kvAttributeAssignment : message.attributelookuptable())
257 m_attributeLookupTable[kvAttributeAssignment.first] = kvAttributeAssignment.second;
261 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord> ComponentsFile::ComponentRecord::ToeprintRecord::to_protobuf()
const
263 std::unique_ptr<Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord> pToeprintRecordMessage(
new Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord);
264 pToeprintRecordMessage->set_pinnumber(pinNumber);
265 pToeprintRecordMessage->set_locationx(locationX);
266 pToeprintRecordMessage->set_locationy(locationY);
267 pToeprintRecordMessage->set_rotation(rotation);
268 pToeprintRecordMessage->set_mirror(mirror);
269 pToeprintRecordMessage->set_netnumber(netNumber);
270 pToeprintRecordMessage->set_subnetnumber(subnetNumber);
271 pToeprintRecordMessage->set_name(name);
272 return pToeprintRecordMessage;
275 void ComponentsFile::ComponentRecord::ToeprintRecord::from_protobuf(
const Odb::Lib::Protobuf::ComponentsFile::ComponentRecord::ToeprintRecord& message)
277 pinNumber = message.pinnumber();
278 locationX = message.locationx();
279 locationY = message.locationy();
280 rotation = message.rotation();
281 mirror = message.mirror();
282 netNumber = message.netnumber();
283 subnetNumber = message.subnetnumber();
284 name = message.name();
287 bool ComponentsFile::Parse(std::filesystem::path directory)
289 std::ifstream componentsFile;
295 m_directory = directory;
297 m_layerName = m_directory.filename().string();
298 if (m_layerName == TOP_COMPONENTS_LAYER_NAME ||
299 m_layerName == BOTTOM_COMPONENTS_LAYER_NAME)
301 m_side = m_layerName == TOP_COMPONENTS_LAYER_NAME ?
311 loginfo(
"checking for extraction...");
313 std::filesystem::path componentsFilePath;
314 for (
const std::string componentsFilename : COMPONENTS_FILENAMES)
316 loginfo(
"trying components file: [" + componentsFilename +
"]...");
318 componentsFilePath = Utils::ArchiveExtractor::getUncompressedFilePath(m_directory, componentsFilename);
319 if (exists(componentsFilePath) && is_regular_file(componentsFilePath))
321 loginfo(
"found components file: [" + componentsFilePath.string() +
"]");
326 m_path = componentsFilePath;
328 loginfo(
"any extraction complete, parsing data...");
330 if (!std::filesystem::exists(m_path))
332 auto message =
"components file does not exist: [" + m_path.string() +
"]";
333 throw invalid_odb_error(message.c_str());
335 else if (!std::filesystem::is_regular_file(m_path))
337 auto message =
"components is not a file: [" + m_path.string() +
"]";
338 throw invalid_odb_error(message.c_str());
341 componentsFile.open(m_path.string(), std::ios::in);
342 if (!componentsFile.is_open())
344 auto message =
"unable to open components file: [" + m_path.string() +
"]";
345 throw invalid_odb_error(message.c_str());
348 std::shared_ptr<ComponentRecord> pCurrentComponentRecord;
349 std::shared_ptr<BomDescriptionRecord> pCurrentBomDescriptionRecord;
351 while (std::getline(componentsFile, line))
356 Utils::str_trim(line);
359 std::stringstream lineStream(line);
362 if (line.find(COMMENT_TOKEN) == 0)
366 else if (line.find(UNITS_TOKEN) == 0)
370 if (!std::getline(lineStream, token,
'='))
372 throw_parse_error(m_path, line, token, lineNumber);
374 else if (!std::getline(lineStream, token,
'='))
376 throw_parse_error(m_path, line, token, lineNumber);
381 else if (line.find(ID_TOKEN) == 0)
384 if (!std::getline(lineStream, token,
'='))
386 throw_parse_error(m_path, line, token, lineNumber);
388 else if (!std::getline(lineStream, token,
'='))
390 throw_parse_error(m_path, line, token, lineNumber);
392 m_id = std::stoul(token);
394 else if (line.find(ATTRIBUTE_NAME_TOKEN) == 0)
399 if (!std::getline(lineStream, token,
' '))
401 throw_parse_error(m_path, line, token, lineNumber);
403 else if (!std::getline(lineStream, token,
' '))
405 throw_parse_error(m_path, line, token, lineNumber);
407 m_attributeNames.push_back(token);
409 else if (line.find(ATTRIBUTE_VALUE_TOKEN) == 0)
413 if (!std::getline(lineStream, token,
' '))
415 throw_parse_error(m_path, line, token, lineNumber);
417 else if (!std::getline(lineStream, token,
' '))
419 throw_parse_error(m_path, line, token, lineNumber);
421 m_attributeTextValues.push_back(token);
423 else if (line.find(ComponentRecord::RECORD_TOKEN) == 0)
429 if (token != ComponentRecord::RECORD_TOKEN)
431 throw_parse_error(m_path, line, token, lineNumber);
434 if (pCurrentBomDescriptionRecord !=
nullptr)
437 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
438 pCurrentBomDescriptionRecord.reset();
442 if (pCurrentComponentRecord !=
nullptr)
445 m_componentRecords.push_back(pCurrentComponentRecord);
446 pCurrentComponentRecord.reset();
450 pCurrentComponentRecord = std::make_shared<ComponentRecord>();
452 lineStream >> pCurrentComponentRecord->pkgRef;
453 lineStream >> pCurrentComponentRecord->locationX;
454 lineStream >> pCurrentComponentRecord->locationY;
455 lineStream >> pCurrentComponentRecord->rotation;
458 lineStream >> mirror;
459 pCurrentComponentRecord->mirror = (mirror ==
'M');
461 lineStream >> pCurrentComponentRecord->compName;
462 lineStream >> pCurrentComponentRecord->partName;
465 if (m_componentRecords.size() > UINT_MAX)
467 throw_parse_error(m_path, line, token, lineNumber);
470 pCurrentComponentRecord->index =
static_cast<unsigned int>(m_componentRecords.size());
472 std::string attrIdString;
473 lineStream >> attrIdString;
475 if (!pCurrentComponentRecord->ParseAttributeLookupTable(attrIdString))
477 throw_parse_error(m_path, line, token, lineNumber);
480 else if (line.find(PropertyRecord::RECORD_TOKEN) == 0)
484 if (!(lineStream >> token))
486 throw_parse_error(m_path, line, token, lineNumber);
489 if (token != PropertyRecord::RECORD_TOKEN)
491 throw_parse_error(m_path, line, token, lineNumber);
494 auto pPropertyRecord = std::make_shared<PropertyRecord>();
496 if (!(lineStream >> pPropertyRecord->name))
498 throw_parse_error(m_path, line, token, lineNumber);
501 if (!(lineStream >> token))
503 throw_parse_error(m_path, line, token, lineNumber);
512 if (!(lineStream >> token))
514 throw_parse_error(m_path, line, token, lineNumber);
518 if (token.size() > 0 && token[0] ==
'\'')
524 if (token.size() > 0 && token[token.size() - 1] ==
'\'')
527 token.erase(token.size() - 1);
530 Utils::str_trim(token);
533 pPropertyRecord->value = token;
536 while (lineStream >> f)
538 pPropertyRecord->floatValues.push_back(f);
541 pCurrentComponentRecord->m_propertyRecords.push_back(pPropertyRecord);
543 else if (line.find(ComponentRecord::ToeprintRecord::RECORD_TOKEN) == 0)
548 if (token != ComponentRecord::ToeprintRecord::RECORD_TOKEN)
550 throw_parse_error(m_path, line, token, lineNumber);
553 auto pToeprintRecord = std::make_shared<ComponentRecord::ToeprintRecord>();
554 lineStream >> pToeprintRecord->pinNumber;
555 lineStream >> pToeprintRecord->locationX;
556 lineStream >> pToeprintRecord->locationY;
557 lineStream >> pToeprintRecord->rotation;
560 lineStream >> mirror;
561 pToeprintRecord->mirror = (mirror ==
'M' || mirror ==
'm');
563 lineStream >> pToeprintRecord->netNumber;
564 if (pToeprintRecord->netNumber == (
unsigned int)-1)
567 parse_info pi(m_path, line, lineNumber);
568 logdebug(pi.toString(
"Component Toeprint record with netNumber = -1"));
570 if (!m_allowToepintNetNumbersOfNegative1)
572 throw_parse_error(m_path, line, token, lineNumber);
576 lineStream >> pToeprintRecord->subnetNumber;
577 if (pToeprintRecord->subnetNumber == (
unsigned int)-1)
580 parse_info pi(m_path, line, lineNumber);
581 logdebug(pi.toString(
"Component Toeprint record with subnetNumber = -1"));
583 if (!m_allowToepintNetNumbersOfNegative1)
585 throw_parse_error(m_path, line, token, lineNumber);
589 lineStream >> pToeprintRecord->name;
591 pCurrentComponentRecord->m_toeprintRecords.push_back(pToeprintRecord);
593 else if (line.find(ComponentsFile::BomDescriptionRecord::CPN_RECORD_TOKEN) == 0)
599 if (token != ComponentsFile::BomDescriptionRecord::CPN_RECORD_TOKEN)
601 throw_parse_error(m_path, line, token, lineNumber);
604 if (pCurrentBomDescriptionRecord !=
nullptr)
606 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
607 pCurrentBomDescriptionRecord.reset();
610 pCurrentBomDescriptionRecord = std::make_shared<ComponentsFile::BomDescriptionRecord>();
612 else if (line.find(ComponentsFile::BomDescriptionRecord::IPN_RECORD_TOKEN) == 0)
616 if (token != ComponentsFile::BomDescriptionRecord::IPN_RECORD_TOKEN)
618 throw_parse_error(m_path, line, token, lineNumber);
621 if (pCurrentBomDescriptionRecord ==
nullptr)
623 throw_parse_error(m_path, line, token, lineNumber);
626 if (!(lineStream >> pCurrentBomDescriptionRecord->ipn))
632 else if (line.find(ComponentsFile::BomDescriptionRecord::DSC_RECORD_TOKEN) == 0)
636 if (token != ComponentsFile::BomDescriptionRecord::DSC_RECORD_TOKEN)
638 throw_parse_error(m_path, line, token, lineNumber);
641 if (pCurrentBomDescriptionRecord ==
nullptr)
643 throw_parse_error(m_path, line, token, lineNumber);
646 std::string description;
648 if (!(lineStream >> description))
654 pCurrentBomDescriptionRecord->descriptions.push_back(description);
656 else if (line.find(ComponentsFile::BomDescriptionRecord::VPL_VND_RECORD_TOKEN) == 0)
660 if (token != ComponentsFile::BomDescriptionRecord::VPL_VND_RECORD_TOKEN)
662 throw_parse_error(m_path, line, token, lineNumber);
665 if (pCurrentBomDescriptionRecord ==
nullptr)
667 throw_parse_error(m_path, line, token, lineNumber);
670 if (!(lineStream >> pCurrentBomDescriptionRecord->vpl_vnd))
672 throw_parse_error(m_path, line, token, lineNumber);
675 else if (line.find(ComponentsFile::BomDescriptionRecord::VPL_MPN_RECORD_TOKEN) == 0)
679 if (token != ComponentsFile::BomDescriptionRecord::VPL_MPN_RECORD_TOKEN)
681 throw_parse_error(m_path, line, token, lineNumber);
684 if (pCurrentBomDescriptionRecord ==
nullptr)
686 throw_parse_error(m_path, line, token, lineNumber);
689 if (!(lineStream >> pCurrentBomDescriptionRecord->vpl_mpn))
691 throw_parse_error(m_path, line, token, lineNumber);
694 else if (line.find(ComponentsFile::BomDescriptionRecord::VND_RECORD_TOKEN) == 0)
698 if (token != ComponentsFile::BomDescriptionRecord::VND_RECORD_TOKEN)
700 throw_parse_error(m_path, line, token, lineNumber);
703 if (pCurrentBomDescriptionRecord ==
nullptr)
705 throw_parse_error(m_path, line, token, lineNumber);
708 if (!(lineStream >> pCurrentBomDescriptionRecord->vnd))
710 throw_parse_error(m_path, line, token, lineNumber);
713 else if (line.find(ComponentsFile::BomDescriptionRecord::MPN_RECORD_TOKEN) == 0)
717 if (token != ComponentsFile::BomDescriptionRecord::MPN_RECORD_TOKEN)
719 throw_parse_error(m_path, line, token, lineNumber);
722 if (pCurrentBomDescriptionRecord ==
nullptr)
724 throw_parse_error(m_path, line, token, lineNumber);
727 if (!(lineStream >> pCurrentBomDescriptionRecord->mpn))
729 throw_parse_error(m_path, line, token, lineNumber);
739 if (pCurrentBomDescriptionRecord !=
nullptr)
742 m_bomDescriptionRecordsByCpn[pCurrentBomDescriptionRecord->cpn] = pCurrentBomDescriptionRecord;
743 pCurrentBomDescriptionRecord.reset();
747 if (pCurrentComponentRecord !=
nullptr)
750 m_componentRecords.push_back(pCurrentComponentRecord);
751 pCurrentComponentRecord.reset();
754 componentsFile.close();
756 catch (parse_error& pe)
758 auto m = pe.toString(
"Parse Error:");
760 componentsFile.close();
763 catch (std::exception& e)
765 parse_info pi(m_path, line, lineNumber);
766 const auto m = pi.toString();
767 logexception_msg(e, m);
768 componentsFile.close();