OdbDesignLib
OdbDesign ODB++ Parsing Library
StepHdrFile.cpp
1 #include "StepHdrFile.h"
2 #include "../invalid_odb_error.h"
3 #include "str_utils.h"
4 #include "../../Constants.h"
5 #include "../parse_error.h"
6 #include <Logger.h>
7 
8 namespace Odb::Lib::FileModel::Design
9 {
10  StepHdrFile::~StepHdrFile()
11  {
12  m_stepRepeatRecords.clear();
13  }
14 
15  bool StepHdrFile::Parse(std::filesystem::path path)
16  {
17  std::ifstream stepHdrFile;
18  int lineNumber = 0;
19  std::string line;
20 
21  try
22  {
23  if (!OdbFile::Parse(path)) return false;
24 
25  auto stepHdrFilePath = path / "stephdr";
26  if (!std::filesystem::exists(stepHdrFilePath))
27  {
28  auto message = "stephdr file does not exist: [" + stepHdrFilePath.string() + "]";
29  throw invalid_odb_error(message.c_str());
30  }
31 
32  stepHdrFile.open(stepHdrFilePath, std::ios::in);
33  if (!stepHdrFile.is_open())
34  {
35  auto message = "unable to open stephdr file: [" + stepHdrFilePath.string() + "]";
36  throw invalid_odb_error(message.c_str());
37  }
38 
39  m_path = stepHdrFilePath;
40 
41  std::shared_ptr<StepRepeatRecord> pCurrentStepRepeatRecord;
42  bool openBraceFound = false;
43 
44  while (std::getline(stepHdrFile, line))
45  {
46  lineNumber++;
47  // trim whitespace from beginning and end of line
48  Utils::str_trim(line);
49  if (!line.empty())
50  {
51  std::stringstream lineStream(line);
52  if (line.find(Constants::COMMENT_TOKEN) == 0)
53  {
54  // comment line
55  }
56  else if (line.find(StepRepeatRecord::ARRAY_HEADER_TOKEN) == 0)
57  {
58  std::string token;
59  if (!(lineStream >> token))
60  {
61  throw_parse_error(m_path, line, token, lineNumber);
62  }
63 
64  if (token != StepRepeatRecord::ARRAY_HEADER_TOKEN)
65  {
66  throw_parse_error(m_path, line, token, lineNumber);
67  }
68 
69  if (lineStream >> token)
70  {
71  // open brace is at the end on the same line as the step array record open token
72  if (token == Constants::ARRAY_RECORD_OPEN_TOKEN)
73  {
74  openBraceFound = true;
75 
76  // TODO: finish any existing previous step record
77  // (same code as finding a close brace on an empty line)
78 
79  // open a new STEP-REPEAT array record
80  pCurrentStepRepeatRecord = std::make_shared<StepRepeatRecord>();
81  }
82  }
83  }
84  else if (line.find(Constants::ARRAY_RECORD_OPEN_TOKEN) == 0)
85  {
86  // TODO: how to determine if you are opening a step or layer array record?
87  // (maybe a boolean flag? stepArrayOpen = true/false)
88  // no current opening of a layer or step array record found yet
89  if (pCurrentStepRepeatRecord == nullptr)
90  {
91  throw_parse_error(m_path, line, "", lineNumber);
92  }
93 
94  // found another open brace while still parsing after the previous record's open brace
95  if (openBraceFound)
96  {
97  throw_parse_error(m_path, line, "", lineNumber);
98  }
99 
100  openBraceFound = true;
101 
102  // TODO: finish any existing previous layer or step record
103  // (same code as finding a close brace on an empty line)
104 
105  // open a new LAYER array record
106  //pCurrentLayerRecord = std::make_shared<LayerRecord>();
107  }
108  else if (line.find(Constants::ARRAY_RECORD_CLOSE_TOKEN) == 0)
109  {
110  if (pCurrentStepRepeatRecord != nullptr && openBraceFound)
111  {
112  m_stepRepeatRecords.push_back(pCurrentStepRepeatRecord);
113  pCurrentStepRepeatRecord.reset();
114  openBraceFound = false;
115  }
116  else
117  {
118  // found a close brace but aren't currently parsing a step or layer array record
119  throw_parse_error(m_path, line, "", lineNumber);
120  }
121  }
122  else
123  {
124  // it should be a name-value pair line (i.e. element of a step or layer array)
125  std::string attribute;
126  std::string value;
127 
128  if (!std::getline(lineStream, attribute, '='))
129  {
130  throw_parse_error(m_path, line, attribute, lineNumber);
131  }
132 
133  if (std::getline(lineStream, value))
134  {
135  Utils::str_trim(attribute);
136  Utils::str_trim(value);
137 
138  if (pCurrentStepRepeatRecord != nullptr && openBraceFound)
139  {
140  if (attribute == "NAME" || attribute == "name")
141  {
142  pCurrentStepRepeatRecord->name = value;
143  }
144  else if (attribute == "X" || attribute == "x")
145  {
146  pCurrentStepRepeatRecord->x = std::stof(value);
147  }
148  else if (attribute == "Y" || attribute == "y")
149  {
150  pCurrentStepRepeatRecord->y = std::stof(value);
151  }
152  else if (attribute == "DX" || attribute == "dx")
153  {
154  pCurrentStepRepeatRecord->dx = std::stof(value);
155  }
156  else if (attribute == "DY" || attribute == "dy")
157  {
158  pCurrentStepRepeatRecord->dy = std::stof(value);
159  }
160  else if (attribute == "NX" || attribute == "nx")
161  {
162  pCurrentStepRepeatRecord->nx = std::stoi(value);
163  }
164  else if (attribute == "NY" || attribute == "ny")
165  {
166  pCurrentStepRepeatRecord->ny = std::stoi(value);
167  }
168  else if (attribute == "ANGLE" || attribute == "angle")
169  {
170  pCurrentStepRepeatRecord->angle = std::stof(value);
171  }
172  else if (attribute == "FLIP" || attribute == "flip")
173  {
174  if (value == "YES" || value == "yes")
175  {
176  pCurrentStepRepeatRecord->flip = true;
177  }
178  else if (value == "NO" || value == "no")
179  {
180  pCurrentStepRepeatRecord->flip = false;
181  }
182  else
183  {
184  throw_parse_error(m_path, line, attribute, lineNumber);
185  }
186  }
187  else if (attribute == "MIRROR" || attribute == "mirror")
188  {
189  if (value == "YES" || value == "yes")
190  {
191  pCurrentStepRepeatRecord->mirror = true;
192  }
193  else if (value == "NO" || value == "no")
194  {
195  pCurrentStepRepeatRecord->mirror = false;
196  }
197  else
198  {
199  throw_parse_error(m_path, line, attribute, lineNumber);
200  }
201  }
202  else
203  {
204  throw_parse_error(m_path, line, attribute, lineNumber);
205  }
206  }
207  else
208  {
209  if (attribute == "X_DATUM" || attribute == "x_datum")
210  {
211  xDatum = std::stof(value);
212  }
213  else if (attribute == "Y_DATUM" || attribute == "y_datum")
214  {
215  yDatum = stof(value);
216  }
217  else if (attribute == "ID" || attribute == "id")
218  {
219  id = (unsigned int)std::stoul(value);
220  }
221  else if (attribute == "X_ORIGIN" || attribute == "x_origin")
222  {
223  xOrigin = std::stof(value);
224  }
225  else if (attribute == "Y_ORIGIN" || attribute == "y_origin")
226  {
227  yOrigin = std::stof(value);
228  }
229  else if (attribute == "TOP_ACTIVE" || attribute == "top_active")
230  {
231  topActive = std::stof(value);
232  }
233  else if (attribute == "BOTTOM_ACTIVE" || attribute == "bottom_active")
234  {
235  bottomActive = std::stof(value);
236  }
237  else if (attribute == "RIGHT_ACTIVE" || attribute == "right_active")
238  {
239  rightActive = std::stof(value);
240  }
241  else if (attribute == "LEFT_ACTIVE" || attribute == "left_active")
242  {
243  leftActive = std::stof(value);
244  }
245  else if (attribute == "AFFECTING_BOM" || attribute == "affecting_bom")
246  {
247  affectingBom = value;
248  }
249  else if (attribute == "AFFECTING_BOM_CHANGED" || attribute == "affecting_bom_changed")
250  {
251  affectingBomChanged = std::stoi(value);
252  }
253  else if (attribute == "UNITS" || attribute == "units")
254  {
255  m_units = value;
256  }
257  else if (attribute.find("ONLINE_") == 0)
258  {
259  m_onlineValues[attribute] = value;
260  }
261  else
262  {
263  throw_parse_error(m_path, line, attribute, lineNumber);
264  }
265  }
266  }
267  //else if (!attributeValueIsOptional(attribute))
268  //{
269  // logwarn("matrix/matrix file: no value for non-optional attribute: " + attribute);
270  //}
271  }
272  }
273  }
274 
275  stepHdrFile.close();
276  }
277  catch (parse_error& pe)
278  {
279  auto m = pe.toString("Parse Error:");
280  logerror(m);
281  // cleanup file
282  stepHdrFile.close();
283  throw pe;
284  }
285  catch (invalid_odb_error& ioe)
286  {
287  parse_info pi(m_path, line, lineNumber);
288  const auto m = pi.toString();
289  logexception_msg(ioe, m);
290  // cleanup file
291  stepHdrFile.close();
292  throw ioe;
293  }
294 
295  return true;
296  }
297 
298  std::unique_ptr<Odb::Lib::Protobuf::StepHdrFile> StepHdrFile::to_protobuf() const
299  {
300  auto message = std::make_unique<Odb::Lib::Protobuf::StepHdrFile>();
301  message->set_xdatum(xDatum);
302  message->set_ydatum(yDatum);
303  message->set_id(id);
304  message->set_xorigin(xOrigin);
305  message->set_yorigin(yOrigin);
306  message->set_topactive(topActive);
307  message->set_bottomactive(bottomActive);
308  message->set_leftactive(leftActive);
309  message->set_rightactive(rightActive);
310  message->set_affectingbom(affectingBom);
311  message->set_affectingbomchanged(affectingBomChanged);
312 
313  for (const auto& stepRepeatRecord : m_stepRepeatRecords)
314  {
315  auto stepRepeatRecordPtr = message->add_steprepeatrecords();
316  stepRepeatRecordPtr->CopyFrom(*stepRepeatRecord->to_protobuf());
317  }
318 
319  for (const auto& kvOnlineValue : m_onlineValues)
320  {
321  (*message->mutable_onlinevalues())[kvOnlineValue.first] = kvOnlineValue.second;
322  }
323 
324  return message;
325  }
326 
327  void StepHdrFile::from_protobuf(const Odb::Lib::Protobuf::StepHdrFile& message)
328  {
329  xDatum = message.xdatum();
330  yDatum = message.ydatum();
331  id = message.id();
332  xOrigin = message.xorigin();
333  yOrigin = message.yorigin();
334  topActive = message.topactive();
335  bottomActive = message.bottomactive();
336  leftActive = message.leftactive();
337  rightActive = message.rightactive();
338  affectingBom = message.affectingbom();
339  affectingBomChanged = message.affectingbomchanged();
340 
341  for (const auto& stepRepeatRecord : message.steprepeatrecords())
342  {
343  auto stepRepeatRecordPtr = std::make_unique<StepRepeatRecord>();
344  stepRepeatRecordPtr->from_protobuf(stepRepeatRecord);
345  m_stepRepeatRecords.push_back(std::move(stepRepeatRecordPtr));
346  }
347 
348  for (const auto& kvOnlineValue : message.onlinevalues())
349  {
350  m_onlineValues[kvOnlineValue.first] = kvOnlineValue.second;
351  }
352  }
353 
354  bool StepHdrFile::Save(std::ostream& os)
355  {
356  return true;
357  }
358 
359  std::unique_ptr<Odb::Lib::Protobuf::StepHdrFile::StepRepeatRecord> StepHdrFile::StepRepeatRecord::to_protobuf() const
360  {
361  auto message = std::make_unique<Odb::Lib::Protobuf::StepHdrFile::StepRepeatRecord>();
362  message->set_name(name);
363  message->set_x(x);
364  message->set_y(y);
365  message->set_dx(dx);
366  message->set_dy(dy);
367  message->set_nx(nx);
368  message->set_ny(ny);
369  message->set_angle(angle);
370  message->set_flip(flip);
371  message->set_mirror(mirror);
372  return message;
373  }
374 
375  void StepHdrFile::StepRepeatRecord::from_protobuf(const Odb::Lib::Protobuf::StepHdrFile::StepRepeatRecord& message)
376  {
377  name = message.name();
378  x = message.x();
379  y = message.y();
380  dx = message.dx();
381  dy = message.dy();
382  nx = message.nx();
383  ny = message.ny();
384  flip = message.flip();
385  mirror = message.mirror();
386  angle = message.angle();
387  }
388 }