7#include "../parse_error.h"
8#include "../invalid_odb_error.h"
11#include "../../Constants.h"
12#include <ArchiveExtractor.h>
13#include "../../Text/Utf8Sanitizer.h"
15namespace Odb::Lib::FileModel::Design
17 ToolsFile::ToolsFile()
26 ToolsFile::~ToolsFile()
31 std::string ToolsFile::GetUnits()
const
36 double ToolsFile::GetThickness()
const
41 std::string ToolsFile::GetUserParams()
const
46 const ToolsFile::ToolsMap& ToolsFile::GetTools()
const
51 bool Lib::FileModel::Design::ToolsFile::Parse(std::filesystem::path directory)
53 std::ifstream toolsFile;
59 m_directory = directory;
61 loginfo(
"checking for extraction...");
63 std::filesystem::path toolsFilePath;
64 for (
const std::string toolsFilename : TOOLS_FILENAMES)
66 loginfo(
"trying tools file: [" + toolsFilename +
"]...");
68 toolsFilePath = Utils::ArchiveExtractor::getUncompressedFilePath(m_directory, toolsFilename);
69 if (exists(toolsFilePath) && is_regular_file(toolsFilePath))
71 loginfo(
"found tools file: [" + toolsFilePath.string() +
"]");
76 m_path = toolsFilePath;
78 loginfo(
"any extraction complete, parsing data...");
80 if (!std::filesystem::exists(m_path))
82 auto message =
"tools file does not exist: [" + m_directory.string() +
"]";
87 else if (!std::filesystem::is_regular_file(m_path))
89 auto message =
"tools is not a file: [" + m_path.string() +
"]";
90 throw invalid_odb_error(message.c_str());
93 toolsFile.open(m_path.string(), std::ios::in);
94 if (!toolsFile.is_open())
96 auto message =
"unable to open tools file: [" + m_path.string() +
"]";
97 throw invalid_odb_error(message.c_str());
100 std::shared_ptr<ToolsRecord> pCurrentToolsRecord;
101 bool openBraceFound =
false;
103 while (std::getline(toolsFile, line))
108 Utils::str_trim(line);
111 std::stringstream lineStream(line);
114 if (line.find(Constants::COMMENT_TOKEN) == 0)
118 else if (line.find(ToolsFile::UNITS_TOKEN) == 0)
122 if (!std::getline(lineStream, token,
'='))
124 throw_parse_error(m_path, line, token, lineNumber);
129 else if (line.find(ToolsFile::THICKNESS_TOKEN) == 0)
133 if (!std::getline(lineStream, value,
'='))
135 throw_parse_error(m_path, line, value, lineNumber);
138 if (std::getline(lineStream, value))
140 Utils::str_trim(value);
141 m_thickness = std::stod(value);
150 else if (line.find(ToolsFile::USER_PARAMS_TOKEN) == 0)
154 if (!std::getline(lineStream, value,
'='))
156 throw_parse_error(m_path, line, value, lineNumber);
159 if (std::getline(lineStream, value))
161 Utils::str_trim(value);
162 m_user_params = value;
165 else if (line.find(ToolsRecord::RECORD_TOKEN) == 0)
168 if (!(lineStream >> token))
170 throw_parse_error(m_path, line, token, lineNumber);
173 if (token != ToolsRecord::RECORD_TOKEN || pCurrentToolsRecord !=
nullptr)
175 throw_parse_error(m_path, line, token, lineNumber);
179 pCurrentToolsRecord = std::make_shared<ToolsRecord>();
181 if (lineStream >> token)
184 if (token == Constants::ARRAY_RECORD_OPEN_TOKEN)
186 openBraceFound =
true;
190 else if (line.find(Constants::ARRAY_RECORD_OPEN_TOKEN) == 0)
193 if (pCurrentToolsRecord ==
nullptr)
195 throw_parse_error(m_path, line,
"", lineNumber);
201 throw_parse_error(m_path, line,
"", lineNumber);
204 openBraceFound =
true;
206 else if (line.find(Constants::ARRAY_RECORD_CLOSE_TOKEN) == 0)
208 if (pCurrentToolsRecord !=
nullptr && openBraceFound && pCurrentToolsRecord->toolNum != 0)
210 m_toolsByNum[pCurrentToolsRecord->toolNum] = pCurrentToolsRecord;
211 pCurrentToolsRecord.reset();
212 openBraceFound =
false;
217 throw_parse_error(m_path, line,
"", lineNumber);
222 std::string attribute;
225 if (!std::getline(lineStream, attribute,
'='))
227 throw_parse_error(m_path, line,
"", lineNumber);
230 if (std::getline(lineStream, value))
232 Utils::str_trim(attribute);
233 Utils::str_trim(value);
235 if (pCurrentToolsRecord !=
nullptr && openBraceFound)
237 if (attribute == ToolsRecord::NUM_KEY || attribute ==
"num")
239 pCurrentToolsRecord->toolNum = std::stoi(value);
241 else if (attribute == ToolsRecord::TYPE_KEY || attribute ==
"type")
243 if (ToolsRecord::typeMap.contains(value))
245 pCurrentToolsRecord->type = ToolsRecord::typeMap.getValue(value);
249 throw_parse_error(m_path, line, attribute, lineNumber);
252 else if (attribute == ToolsRecord::TYPE2_KEY || attribute ==
"type2")
254 if (ToolsRecord::type2Map.contains(value))
256 auto type = pCurrentToolsRecord->type;
257 auto type2 = ToolsRecord::type2Map.getValue(value);
259 if (type2 != ToolsRecord::Type2::Standard)
261 bool invalid =
false;
264 case ToolsRecord::Type2::PressFit:
265 invalid = (type != ToolsRecord::Type::Plated);
268 case ToolsRecord::Type2::Photo:
269 case ToolsRecord::Type2::Laser:
270 invalid = (type != ToolsRecord::Type::Via);
275 throw_parse_error(m_path, line, attribute, lineNumber);
278 pCurrentToolsRecord->type2 = type2;
282 pCurrentToolsRecord->type2 = ToolsRecord::Type2::Standard;
285 else if (attribute == ToolsRecord::MIN_TOL_KEY || attribute ==
"min_tol")
287 pCurrentToolsRecord->minTOL = std::stod(value);
289 else if (attribute == ToolsRecord::MAX_TOL_KEY || attribute ==
"max_tol")
291 pCurrentToolsRecord->maxTOL = std::stod(value);
293 else if (attribute == ToolsRecord::BIT_KEY || attribute ==
"bit")
295 pCurrentToolsRecord->drillBit = value;
297 else if (attribute == ToolsRecord::FINISH_SIZE_KEY || attribute ==
"finish_size")
299 pCurrentToolsRecord->finishSize = std::stod(value);
301 else if (attribute == ToolsRecord::DRILL_SIZE_KEY || attribute ==
"drill_size")
303 pCurrentToolsRecord->drillSize = std::stod(value);
307 throw_parse_error(m_path, line, attribute, lineNumber);
314 throw_parse_error(m_path, line, attribute, lineNumber);
325 catch (parse_error& pe)
327 auto m = pe.toString(
"Parse Error:");
332 catch (std::exception& e)
334 parse_info pi(m_path, line, lineNumber);
335 const auto m = pi.toString();
336 logexception_msg(e, m);
344 bool ToolsFile::Save(std::ostream& os)
346 os << Constants::UNITS_TOKEN <<
" = " << m_units << std::endl;
347 os << ToolsFile::THICKNESS_TOKEN <<
" = " << std::to_string(m_thickness) << std::endl;
348 os << ToolsFile::USER_PARAMS_TOKEN <<
" = " << m_user_params << std::endl;
350 for (
const auto& [toolNum, tool_info] : m_toolsByNum)
352 os << ToolsRecord::RECORD_TOKEN <<
" " << Constants::ARRAY_RECORD_OPEN_TOKEN << std::endl;
354 os <<
'\t' << ToolsRecord::NUM_KEY <<
"=" << toolNum << std::endl;
355 os <<
'\t' << ToolsRecord::TYPE_KEY <<
"=" << ToolsRecord::typeMap.getValue(tool_info->type) << std::endl;
356 os <<
'\t' << ToolsRecord::TYPE2_KEY <<
"=" << ToolsRecord::type2Map.getValue(tool_info->type2) << std::endl;
357 os <<
'\t' << ToolsRecord::MIN_TOL_KEY <<
"=" << tool_info->minTOL << std::endl;
358 os <<
'\t' << ToolsRecord::MAX_TOL_KEY <<
"=" << tool_info->maxTOL << std::endl;
359 os <<
'\t' << ToolsRecord::BIT_KEY <<
"=" << tool_info->drillBit << std::endl;
360 os <<
'\t' << ToolsRecord::FINISH_SIZE_KEY <<
"=" << tool_info->finishSize << std::endl;
361 os <<
'\t' << ToolsRecord::DRILL_SIZE_KEY <<
"=" << tool_info->drillSize << std::endl;
363 os << Constants::ARRAY_RECORD_CLOSE_TOKEN << std::endl;
370 std::unique_ptr<Odb::Lib::Protobuf::ToolsFile::ToolsRecord>Odb::Lib::FileModel::Design::ToolsFile::ToolsRecord::to_protobuf()
const
372 std::unique_ptr<Odb::Lib::Protobuf::ToolsFile::ToolsRecord> pToolsRecordMessage(
new Odb::Lib::Protobuf::ToolsFile::ToolsRecord);
373 pToolsRecordMessage->set_tool_num(toolNum);
374 pToolsRecordMessage->set_type(
static_cast<Odb::Lib::Protobuf::ToolsFile::ToolsRecord::Type
>(type));
375 pToolsRecordMessage->set_type2(
static_cast<Odb::Lib::Protobuf::ToolsFile::ToolsRecord::Type2
>(type2));
376 pToolsRecordMessage->set_min_tol(minTOL);
377 pToolsRecordMessage->set_max_tol(maxTOL);
378 pToolsRecordMessage->set_drill_bit(Odb::Lib::Text::ToUtf8(drillBit));
379 pToolsRecordMessage->set_finish_size(finishSize);
380 pToolsRecordMessage->set_drill_size(drillSize);
382 return pToolsRecordMessage;
385 void Odb::Lib::FileModel::Design::ToolsFile::ToolsRecord::from_protobuf(
const Odb::Lib::Protobuf::ToolsFile::ToolsRecord& message)
387 toolNum = message.tool_num();
388 type =
static_cast<Type
>(message.type());
389 type2 =
static_cast<Type2
>(message.type2());
390 minTOL = message.min_tol();
391 maxTOL = message.max_tol();
392 drillBit = message.drill_bit();
393 finishSize = message.finish_size();
394 drillSize = message.drill_size();
397 std::unique_ptr<Odb::Lib::Protobuf::ToolsFile> Lib::FileModel::Design::ToolsFile::to_protobuf()
const
399 auto message = std::make_unique<Odb::Lib::Protobuf::ToolsFile>();
401 message->set_directory(Odb::Lib::Text::ToUtf8(m_directory.string()));
402 message->set_path(Odb::Lib::Text::ToUtf8(m_path.string()));
403 message->set_units(Odb::Lib::Text::ToUtf8(m_units));
405 message->set_thickness(m_thickness);
406 message->set_user_params(Odb::Lib::Text::ToUtf8(m_user_params));
408 auto* tools_map = message->mutable_tools();
409 for (
const auto& [toolNum, toolsRecord] : m_toolsByNum)
411 auto& recordMsg = (*tools_map)[toolNum];
412 recordMsg.CopyFrom(*toolsRecord->to_protobuf());
418 void Lib::FileModel::Design::ToolsFile::from_protobuf(
const Odb::Lib::Protobuf::ToolsFile& message)
420 m_directory = message.directory();
421 m_path = message.path();
423 m_units = message.units();
424 m_thickness = message.thickness();
425 m_user_params = message.user_params();
427 for (
const auto& [toolNum, toolsRecord] : message.tools())
429 auto ptoolsRecord = std::make_shared<ToolsRecord>();
430 ptoolsRecord->from_protobuf(toolsRecord);
431 m_toolsByNum.emplace(toolNum, ptoolsRecord);