9#include "../../Constants.h"
11#include "../parse_error.h"
13#include "../invalid_odb_error.h"
15#include "../../enums.h"
16#include "../OdbFile.h"
19#include "../../Text/Utf8Sanitizer.h"
21namespace Odb::Lib::FileModel::Design
23 MatrixFile::~MatrixFile()
25 m_layerRecords.clear();
26 m_stepRecords.clear();
29 const MatrixFile::LayerRecord::Vector& MatrixFile::GetLayerRecords()
const
31 return m_layerRecords;
34 const MatrixFile::StepRecord::Vector& MatrixFile::GetStepRecords()
const
39 bool MatrixFile::Parse(std::filesystem::path path)
41 std::ifstream matrixFile;
47 if (!OdbFile::Parse(path))
return false;
49 auto matrixFilePath = path /
"matrix";
50 if (!std::filesystem::exists(matrixFilePath))
52 auto message =
"matrix/matrix file does not exist: [" + matrixFilePath.string() +
"]";
53 throw invalid_odb_error(message.c_str());
56 matrixFile.open(matrixFilePath, std::ios::in);
57 if (!matrixFile.is_open())
59 auto message =
"unable to open matrix/matrix file: [" + matrixFilePath.string() +
"]";
60 throw invalid_odb_error(message.c_str());
63 std::shared_ptr<StepRecord> pCurrentStepRecord;
64 std::shared_ptr<LayerRecord> pCurrentLayerRecord;
65 bool openBraceFound =
false;
67 while (std::getline(matrixFile, line))
71 Utils::str_trim(line);
74 std::stringstream lineStream(line);
75 if (line.find(Constants::COMMENT_TOKEN) == 0)
79 else if (line.find(StepRecord::RECORD_TOKEN) == 0)
82 if (!(lineStream >> token))
84 throw_parse_error(m_path, line, token, lineNumber);
88 if (token != StepRecord::RECORD_TOKEN || pCurrentStepRecord !=
nullptr)
90 throw_parse_error(m_path, line, token, lineNumber);
94 pCurrentStepRecord = std::make_shared<StepRecord>();
96 if (lineStream >> token)
99 if (token == Constants::ARRAY_RECORD_OPEN_TOKEN)
101 openBraceFound =
true;
105 else if (line.find(LayerRecord::RECORD_TOKEN) == 0)
108 if (!(lineStream >> token))
110 throw_parse_error(m_path, line, token, lineNumber);
114 if (token != LayerRecord::RECORD_TOKEN || pCurrentLayerRecord !=
nullptr)
116 throw_parse_error(m_path, line, token, lineNumber);
120 pCurrentLayerRecord = std::make_shared<LayerRecord>();
122 if (lineStream >> token)
125 if (token == Constants::ARRAY_RECORD_OPEN_TOKEN)
127 openBraceFound =
true;
131 else if (line.find(Constants::ARRAY_RECORD_OPEN_TOKEN) == 0)
137 if (pCurrentStepRecord ==
nullptr && pCurrentLayerRecord ==
nullptr)
139 throw_parse_error(m_path, line,
"", lineNumber);
145 throw_parse_error(m_path, line,
"", lineNumber);
148 openBraceFound =
true;
156 else if (line.find(Constants::ARRAY_RECORD_CLOSE_TOKEN) == 0)
158 if (pCurrentStepRecord !=
nullptr && openBraceFound)
160 m_stepRecords.push_back(pCurrentStepRecord);
161 pCurrentStepRecord.reset();
162 openBraceFound =
false;
164 else if (pCurrentLayerRecord !=
nullptr && openBraceFound)
166 m_layerRecords.push_back(pCurrentLayerRecord);
167 pCurrentLayerRecord.reset();
168 openBraceFound =
false;
173 throw_parse_error(m_path, line,
"", lineNumber);
179 std::string attribute;
182 if (!std::getline(lineStream, attribute,
'='))
184 throw_parse_error(m_path, line, attribute, lineNumber);
187 if (std::getline(lineStream, value))
189 Utils::str_trim(attribute);
190 Utils::str_trim(value);
192 if (pCurrentStepRecord !=
nullptr && openBraceFound)
194 if (attribute == StepRecord::COLUMN_KEY || attribute ==
"col")
196 pCurrentStepRecord->column = std::stoi(value);
198 else if (attribute == StepRecord::NAME_KEY || attribute ==
"name")
200 pCurrentStepRecord->name = value;
202 else if (attribute == StepRecord::ID_KEY || attribute ==
"id")
204 pCurrentStepRecord->id =
static_cast<unsigned int>(std::stoul(value));
208 throw_parse_error(m_path, line, attribute, lineNumber);
211 else if (pCurrentLayerRecord !=
nullptr && openBraceFound)
213 if (attribute ==
"ROW" || attribute ==
"row")
215 pCurrentLayerRecord->row = std::stoi(value);
217 else if (attribute ==
"NAME" || attribute ==
"name")
219 pCurrentLayerRecord->name = value;
221 else if (attribute ==
"ID" || attribute ==
"id")
223 pCurrentLayerRecord->id = (
unsigned int)std::stoul(value);
225 else if (attribute ==
"TYPE" || attribute ==
"type")
227 if (LayerRecord::typeMap.contains(value))
229 pCurrentLayerRecord->type = LayerRecord::typeMap.getValue(value);
233 throw_parse_error(m_path, line, attribute, lineNumber);
236 else if (attribute == LayerRecord::CONTEXT_KEY || attribute ==
"context")
238 if (LayerRecord::contextMap.contains(value))
240 pCurrentLayerRecord->context = LayerRecord::contextMap.getValue(value);
244 throw_parse_error(m_path, line, attribute, lineNumber);
247 else if (attribute ==
"OLD_NAME" || attribute ==
"old_name")
249 pCurrentLayerRecord->oldName = value;
251 else if (attribute == LayerRecord::POLARITY_KEY || attribute ==
"polarity")
253 if (LayerRecord::polarityMap.contains(value))
255 pCurrentLayerRecord->polarity = LayerRecord::polarityMap.getValue(value);
259 throw_parse_error(m_path, line, attribute, lineNumber);
262 else if (attribute == LayerRecord::DIELECTRIC_TYPE_KEY || attribute ==
"dielectric_type")
264 if (LayerRecord::dielectricTypeMap.contains(value))
266 pCurrentLayerRecord->dielectricType = LayerRecord::dielectricTypeMap.getValue(value);
270 throw_parse_error(m_path, line, attribute, lineNumber);
273 else if (attribute ==
"DIELECTRIC_NAME" || attribute ==
"dielectric_name")
275 pCurrentLayerRecord->dielectricName = value;
277 else if (attribute == LayerRecord::FORM_KEY || attribute ==
"form")
279 if (LayerRecord::formMap.contains(value))
281 pCurrentLayerRecord->form = LayerRecord::formMap.getValue(value);
285 throw_parse_error(m_path, line, attribute, lineNumber);
288 else if (attribute ==
"CU_TOP" || attribute ==
"cu_top")
290 pCurrentLayerRecord->cuTop = std::stoul(value);
292 else if (attribute ==
"CU_TOP" || attribute ==
"cu_top")
294 pCurrentLayerRecord->cuTop = std::stoul(value);
296 else if (attribute ==
"CU_BOTTOM" || attribute ==
"cu_bottom")
298 pCurrentLayerRecord->cuBottom = std::stoul(value);
300 else if (attribute ==
"REF" || attribute ==
"ref")
302 pCurrentLayerRecord->ref = std::stoul(value);
304 else if (attribute ==
"START_NAME" || attribute ==
"start_name")
306 pCurrentLayerRecord->startName = value;
308 else if (attribute ==
"END_NAME" || attribute ==
"end_name")
310 pCurrentLayerRecord->endName = value;
312 else if (attribute ==
"ADD_TYPE" || attribute ==
"add_type")
314 pCurrentLayerRecord->addType = value;
316 else if (attribute ==
"COLOR" || attribute ==
"color")
318 if (!pCurrentLayerRecord->color.from_string(value))
return false;
322 throw_parse_error(m_path, line, attribute, lineNumber);
329 throw_parse_error(m_path, line, attribute, lineNumber);
332 else if (!attributeValueIsOptional(attribute))
334 logwarn(
"matrix/matrix file: no value for non-optional attribute: " + attribute);
342 catch (parse_error& pe)
344 auto m = pe.toString(
"Parse Error:");
350 catch (invalid_odb_error& ioe)
352 parse_info pi(m_path, line, lineNumber);
353 const auto m = pi.toString();
354 logexception_msg(ioe, m);
363 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile> Odb::Lib::FileModel::Design::MatrixFile::to_protobuf()
const
365 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile> pMatrixFileMessage(
new Odb::Lib::Protobuf::MatrixFile);
366 for (
const auto& stepRecord : m_stepRecords)
368 auto pStepRecordMessage = pMatrixFileMessage->add_steps();
369 pStepRecordMessage->CopyFrom(*stepRecord->to_protobuf());
371 for (
const auto& layerRecord : m_layerRecords)
373 auto pLayerRecordMessage = pMatrixFileMessage->add_layers();
374 pLayerRecordMessage->CopyFrom(*layerRecord->to_protobuf());
376 return pMatrixFileMessage;
380 void Odb::Lib::FileModel::Design::MatrixFile::from_protobuf(
const Odb::Lib::Protobuf::MatrixFile& message)
382 for (
const auto& stepRecord : message.steps())
384 auto pStepRecord = std::make_shared<StepRecord>();
385 pStepRecord->from_protobuf(stepRecord);
386 m_stepRecords.push_back(pStepRecord);
388 for (
const auto& layerRecord : message.layers())
390 auto pLayerRecord = std::make_shared<LayerRecord>();
391 pLayerRecord->from_protobuf(layerRecord);
392 m_layerRecords.push_back(pLayerRecord);
396 bool MatrixFile::Save(std::ostream& os)
398 for (
const auto& stepRecord : m_stepRecords)
400 os << StepRecord::RECORD_TOKEN <<
" " << Constants::ARRAY_RECORD_OPEN_TOKEN << std::endl;
402 os <<
'\t' << StepRecord::COLUMN_KEY <<
"=" << stepRecord->column << std::endl;
403 os <<
'\t' << StepRecord::NAME_KEY <<
"=" << stepRecord->name << std::endl;
404 os <<
'\t' << StepRecord::ID_KEY <<
"=" << stepRecord->id << std::endl;
406 os << Constants::ARRAY_RECORD_CLOSE_TOKEN << std::endl;
410 for (
const auto& layerRecord : m_layerRecords)
412 os << LayerRecord::RECORD_TOKEN <<
" " << Constants::ARRAY_RECORD_OPEN_TOKEN << std::endl;
414 os <<
'\t' << LayerRecord::ROW_KEY <<
"=" << layerRecord->row << std::endl;
415 os <<
'\t' << LayerRecord::CONTEXT_KEY <<
"=" << LayerRecord::contextMap.getValue(layerRecord->context) << std::endl;
416 os <<
'\t' << LayerRecord::TYPE_KEY <<
"=" << LayerRecord::typeMap.getValue(layerRecord->type) << std::endl;
417 os <<
'\t' << LayerRecord::NAME_KEY <<
"=" << layerRecord->name << std::endl;
418 os <<
'\t' << LayerRecord::POLARITY_KEY <<
"=" << LayerRecord::polarityMap.getValue(layerRecord->polarity) << std::endl;
419 os <<
'\t' << LayerRecord::FORM_KEY <<
"=" << LayerRecord::formMap.getValue(layerRecord->form) << std::endl;
420 os <<
'\t' << LayerRecord::DIELECTRIC_TYPE_KEY <<
"=" << LayerRecord::dielectricTypeMap.getValue(layerRecord->dielectricType) << std::endl;
421 os <<
'\t' << LayerRecord::DIELECTRIC_NAME_KEY <<
"=" << layerRecord->dielectricName << std::endl;
422 os <<
'\t' << LayerRecord::CU_TOP_KEY <<
"=";
423 if (layerRecord->cuTop != (
unsigned int)-1)
425 os << layerRecord->cuTop;
428 os <<
'\t' << LayerRecord::CU_BOTTOM_KEY <<
"=";
429 if (layerRecord->cuBottom != (
unsigned int)-1)
431 os << layerRecord->cuBottom;
434 os <<
'\t' << LayerRecord::REF_KEY <<
"=";
435 if (layerRecord->ref != (
unsigned int)-1)
437 os << layerRecord->ref;
440 os <<
'\t' << LayerRecord::START_NAME_KEY <<
"=" << layerRecord->startName << std::endl;
441 os <<
'\t' << LayerRecord::END_NAME_KEY <<
"=" << layerRecord->endName << std::endl;
442 os <<
'\t' << LayerRecord::OLD_NAME_KEY <<
"=" << layerRecord->oldName << std::endl;
443 os <<
'\t' << LayerRecord::ADD_TYPE_KEY <<
"=" << layerRecord->addType << std::endl;
444 os <<
'\t' << LayerRecord::COLOR_KEY <<
"=" << layerRecord->color.to_string() << std::endl;
445 os <<
'\t' << LayerRecord::ID_KEY <<
"=" << layerRecord->id << std::endl;
447 os << Constants::ARRAY_RECORD_CLOSE_TOKEN << std::endl;
454 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile::StepRecord> Odb::Lib::FileModel::Design::MatrixFile::StepRecord::to_protobuf()
const
456 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile::StepRecord> pStepRecordMessage(
new Odb::Lib::Protobuf::MatrixFile::StepRecord);
457 pStepRecordMessage->set_column(column);
458 pStepRecordMessage->set_name(Odb::Lib::Text::ToUtf8(name));
459 pStepRecordMessage->set_id(
id);
460 return pStepRecordMessage;
463 void Odb::Lib::FileModel::Design::MatrixFile::StepRecord::from_protobuf(
const Odb::Lib::Protobuf::MatrixFile::StepRecord& message)
465 column = message.column();
466 name = message.name();
470 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile::LayerRecord> Odb::Lib::FileModel::Design::MatrixFile::LayerRecord::to_protobuf()
const
472 std::unique_ptr<Odb::Lib::Protobuf::MatrixFile::LayerRecord> pLayerRecordMessage(
new Odb::Lib::Protobuf::MatrixFile::LayerRecord);
473 pLayerRecordMessage->set_addtype(Odb::Lib::Text::ToUtf8(addType));
474 pLayerRecordMessage->set_context(
static_cast<Odb::Lib::Protobuf::MatrixFile::LayerRecord::Context
>(context));
475 pLayerRecordMessage->set_cubottom(cuBottom);
476 pLayerRecordMessage->set_cutop(cuTop);
477 pLayerRecordMessage->set_dielectricname(Odb::Lib::Text::ToUtf8(dielectricName));
478 pLayerRecordMessage->set_dielectrictype(
static_cast<Odb::Lib::Protobuf::MatrixFile::LayerRecord::DielectricType
>(dielectricType));
479 pLayerRecordMessage->set_endname(Odb::Lib::Text::ToUtf8(endName));
480 pLayerRecordMessage->set_form(
static_cast<Odb::Lib::Protobuf::MatrixFile::LayerRecord::Form
>(form));
481 pLayerRecordMessage->set_id(
id);
482 pLayerRecordMessage->set_name(Odb::Lib::Text::ToUtf8(name));
483 pLayerRecordMessage->set_oldname(Odb::Lib::Text::ToUtf8(oldName));
484 pLayerRecordMessage->set_polarity(
static_cast<Odb::Lib::Protobuf::Polarity
>(polarity));
485 pLayerRecordMessage->set_ref(ref);
486 pLayerRecordMessage->set_row(row);
487 pLayerRecordMessage->set_startname(Odb::Lib::Text::ToUtf8(startName));
488 pLayerRecordMessage->set_type(
static_cast<Odb::Lib::Protobuf::MatrixFile::LayerRecord::Type
>(type));
489 pLayerRecordMessage->mutable_color()->set_red(color.red);
490 pLayerRecordMessage->mutable_color()->set_green(color.green);
491 pLayerRecordMessage->mutable_color()->set_blue(color.blue);
492 pLayerRecordMessage->mutable_color()->set_nopreference(color.noPreference);
495 return pLayerRecordMessage;
498 void Odb::Lib::FileModel::Design::MatrixFile::LayerRecord::from_protobuf(
const Odb::Lib::Protobuf::MatrixFile::LayerRecord& message)
500 addType = message.addtype();
501 context =
static_cast<Context
>(message.context());
502 cuBottom = message.cubottom();
503 cuTop = message.cutop();
504 dielectricName = message.dielectricname();
505 dielectricType =
static_cast<DielectricType
>(message.dielectrictype());
506 endName = message.endname();
507 form =
static_cast<Form
>(message.form());
509 name = message.name();
510 oldName = message.oldname();
511 polarity =
static_cast<Polarity
>(message.polarity());
514 startName = message.startname();
515 type =
static_cast<Type
>(message.type());
516 color.red = message.color().red();
517 color.green = message.color().green();
518 color.blue = message.color().blue();
519 color.noPreference = message.color().nopreference();