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