OdbDesignLib
OdbDesign ODB++ Parsing Library
StandardFontsFile.cpp
1 #include "StandardFontsFile.h"
2 #include "Logger.h"
3 #include <fstream>
4 #include "str_utils.h"
5 #include "../../Constants.h"
6 #include "../parse_error.h"
7 #include "../invalid_odb_error.h"
8 #include "../../ProtoBuf/enums.pb.h"
9 
10 
11 namespace Odb::Lib::FileModel::Design
12 {
13  StandardFontsFile::~StandardFontsFile()
14  {
15  m_characterBlocks.clear();
16  }
17 
18  bool StandardFontsFile::Parse(std::filesystem::path path)
19  {
20  std::ifstream standardFile;
21  int lineNumber = 0;
22  std::string line;
23 
24  try
25  {
26  if (!OdbFile::Parse(path)) return false;
27 
28  auto fontsStandardFile = path / "standard";
29  if (!std::filesystem::exists(fontsStandardFile))
30  {
31  auto message = "fonts/standard file does not exist: [" + fontsStandardFile.string() + "]";
32  throw invalid_odb_error(message.c_str());
33  }
34 
35  standardFile.open(fontsStandardFile, std::ios::in);
36  if (!standardFile.is_open())
37  {
38  auto message = "unable to open fonts/standard file: [" + fontsStandardFile.string() + "]";
39  throw invalid_odb_error(message.c_str());
40  }
41 
42  std::shared_ptr<CharacterBlock> pCurrentCharacterBlock;
43  std::shared_ptr<CharacterBlock::LineRecord> pCurrentLineRecord;
44  bool beginTokenFound = false;
45 
46  while (std::getline(standardFile, line))
47  {
48  lineNumber++;
49 
50  // trim whitespace from beginning and end of line
51  Utils::str_trim(line);
52  if (!line.empty())
53  {
54  std::stringstream lineStream(line);
55  if (line.find(Constants::COMMENT_TOKEN) == 0)
56  {
57  // comment line
58  }
59  else if (line.find("XSIZE") == 0)
60  {
61  std::string token;
62  if (!(lineStream >> token))
63  {
64  throw_parse_error(m_path, line, token, lineNumber);
65  }
66 
67  if (token != "XSIZE")
68  {
69  throw_parse_error(m_path, line, token, lineNumber);
70  }
71 
72  if (!(lineStream >> token))
73  {
74  throw_parse_error(m_path, line, token, lineNumber);
75  }
76 
77  m_xSize = std::stof(token);
78  }
79  else if (line.find("YSIZE") == 0)
80  {
81  std::string token;
82  if (!(lineStream >> token))
83  {
84  throw_parse_error(m_path, line, token, lineNumber);
85  }
86 
87  if (token != "YSIZE")
88  {
89  throw_parse_error(m_path, line, token, lineNumber);
90  }
91 
92  if (!(lineStream >> token))
93  {
94  throw_parse_error(m_path, line, token, lineNumber);
95  }
96 
97  m_ySize = std::stof(token);
98  }
99  else if (line.find("OFFSET") == 0)
100  {
101  std::string token;
102  if (!(lineStream >> token))
103  {
104  throw_parse_error(m_path, line, token, lineNumber);
105  }
106 
107  if (token != "OFFSET")
108  {
109  throw_parse_error(m_path, line, token, lineNumber);
110  }
111 
112  if (!(lineStream >> token))
113  {
114  throw_parse_error(m_path, line, token, lineNumber);
115  }
116 
117  m_offset = std::stof(token);
118  }
119  else if (line.find(CharacterBlock::BEGIN_TOKEN) == 0)
120  {
121  pCurrentCharacterBlock = std::make_shared<CharacterBlock>();
122  beginTokenFound = true;
123 
124  std::string token;
125  if (!(lineStream >> token))
126  {
127  throw_parse_error(m_path, line, token, lineNumber);
128  }
129 
130  if (token != CharacterBlock::BEGIN_TOKEN)
131  {
132  throw_parse_error(m_path, line, token, lineNumber);
133  }
134 
135  if (!(lineStream >> token))
136  {
137  throw_parse_error(m_path, line, token, lineNumber);
138  }
139 
140  Utils::str_trim(token);
141  if (token.length() != 1)
142  {
143  throw_parse_error(m_path, line, token, lineNumber);
144  }
145 
146  pCurrentCharacterBlock->character = token[0];
147  }
148  else if (line.find(CharacterBlock::END_TOKEN) == 0)
149  {
150  if (pCurrentCharacterBlock != nullptr && beginTokenFound)
151  {
152  m_characterBlocks.push_back(pCurrentCharacterBlock);
153  beginTokenFound = false;
154  pCurrentCharacterBlock.reset();
155  }
156  else
157  {
158  throw_parse_error(m_path, line, "", lineNumber);
159  }
160  }
161  else if (line.find(CharacterBlock::LineRecord::RECORD_TOKEN) == 0)
162  {
163  std::string token;
164  if (!(lineStream >> token))
165  {
166  throw_parse_error(m_path, line, token, lineNumber);
167  }
168 
169  if (token != CharacterBlock::LineRecord::RECORD_TOKEN)
170  {
171  throw_parse_error(m_path, line, token, lineNumber);
172  }
173 
174  if (pCurrentCharacterBlock == nullptr || !beginTokenFound)
175  {
176  throw_parse_error(m_path, line, token, lineNumber);
177  }
178 
179  auto pLineRecord = std::make_shared<CharacterBlock::LineRecord>();
180 
181  if (!(lineStream >> token))
182  {
183  throw_parse_error(m_path, line, token, lineNumber);
184  }
185  pLineRecord->xStart = std::stof(token);
186 
187  if (!(lineStream >> token))
188  {
189  throw_parse_error(m_path, line, token, lineNumber);
190  }
191  pLineRecord->yStart = std::stof(token);
192 
193  if (!(lineStream >> token))
194  {
195  throw_parse_error(m_path, line, token, lineNumber);
196  }
197  pLineRecord->xEnd = std::stof(token);
198 
199  if (!(lineStream >> token))
200  {
201  throw_parse_error(m_path, line, token, lineNumber);
202  }
203  pLineRecord->yEnd = std::stof(token);
204 
205  // polarity
206  if (!(lineStream >> token))
207  {
208  throw_parse_error(m_path, line, token, lineNumber);
209  }
210  Utils::str_trim(token);
211 
212  if (token.length() != 1)
213  {
214  throw_parse_error(m_path, line, token, lineNumber);
215  }
216 
217  switch (token[0])
218  {
219  case 'P': pLineRecord->polarity = Polarity::Positive; break;
220  case 'N': pLineRecord->polarity = Polarity::Negative; break;
221  default: throw_parse_error(m_path, line, token, lineNumber);
222  }
223 
224  // shape
225  if (!(lineStream >> token))
226  {
227  throw_parse_error(m_path, line, token, lineNumber);
228  }
229  Utils::str_trim(token);
230 
231  if (token.length() != 1)
232  {
233  throw_parse_error(m_path, line, token, lineNumber);
234  }
235 
236  switch (token[0])
237  {
238  case 'R': pLineRecord->shape = LineShape::Round; break;
239  case 'S': pLineRecord->shape = LineShape::Square; break;
240  default: throw_parse_error(m_path, line, token, lineNumber);
241  }
242 
243  // width
244  if (!(lineStream >> token))
245  {
246  throw_parse_error(m_path, line, token, lineNumber);
247  }
248  pLineRecord->width = std::stof(token);
249 
250  pCurrentCharacterBlock->m_lineRecords.push_back(pLineRecord);
251  }
252  else
253  {
254  logwarn("unrecognized line: " + line);
255  throw_parse_error(m_path, line, "", lineNumber);
256  }
257  }
258  }
259 
260  standardFile.close();
261  }
262  catch (parse_error& pe)
263  {
264  auto m = pe.toString("Parse Error:");
265  logerror(m);
266  // cleanup file
267  standardFile.close();
268  throw pe;
269  }
270  catch (invalid_odb_error& ioe)
271  {
272  parse_info pi(m_path, line, lineNumber);
273  const auto m = pi.toString();
274  logexception_msg(ioe, m);
275  // cleanup file
276  standardFile.close();
277  throw ioe;
278  }
279 
280  return true;
281  }
282 
283  std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile> StandardFontsFile::to_protobuf() const
284  {
285  auto pStandardFontsFileMessage = std::make_unique<Odb::Lib::Protobuf::StandardFontsFile>();
286  pStandardFontsFileMessage->set_xsize(m_xSize);
287  pStandardFontsFileMessage->set_ysize(m_ySize);
288  pStandardFontsFileMessage->set_offset(m_offset);
289  for (const auto& characterBlock : m_characterBlocks)
290  {
291  pStandardFontsFileMessage->add_m_characterblocks()->CopyFrom(*characterBlock->to_protobuf());
292  }
293  return pStandardFontsFileMessage;
294  }
295 
296  void StandardFontsFile::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile& message)
297  {
298  m_xSize = message.xsize();
299  m_ySize = message.ysize();
300  m_offset = message.offset();
301  for (const auto& characterBlockMessage : message.m_characterblocks())
302  {
303  auto pCharacterBlock = std::make_shared<CharacterBlock>();
304  pCharacterBlock->from_protobuf(characterBlockMessage);
305  m_characterBlocks.push_back(pCharacterBlock);
306  }
307  }
308 
309  bool StandardFontsFile::Save(std::ostream& os)
310  {
311  return true;
312  }
313 
314  StandardFontsFile::CharacterBlock::~CharacterBlock()
315  {
316  m_lineRecords.clear();
317  }
318 
319  std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock> StandardFontsFile::CharacterBlock::to_protobuf() const
320  {
321  std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock> pCharacterBlockMessage(new Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock);
322  pCharacterBlockMessage->set_character(std::string(1, character));
323  for (const auto& lineRecord : m_lineRecords)
324  {
325  pCharacterBlockMessage->add_m_linerecords()->CopyFrom(*lineRecord->to_protobuf());
326  }
327  return pCharacterBlockMessage;
328  }
329 
330  void StandardFontsFile::CharacterBlock::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock& message)
331  {
332  if (! message.character().empty()) character = message.character()[0];
333 
334  for (const auto& lineRecordMessage : message.m_linerecords())
335  {
336  auto pLineRecord = std::make_shared<LineRecord>();
337  pLineRecord->from_protobuf(lineRecordMessage);
338  m_lineRecords.push_back(pLineRecord);
339  }
340  }
341 
342  std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord> StandardFontsFile::CharacterBlock::LineRecord::to_protobuf() const
343  {
344  std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord> pLineRecordMessage(new Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord);
345  pLineRecordMessage->set_xstart(xStart);
346  pLineRecordMessage->set_ystart(yStart);
347  pLineRecordMessage->set_xend(xEnd);
348  pLineRecordMessage->set_yend(yEnd);
349  pLineRecordMessage->set_polarity(static_cast<Odb::Lib::Protobuf::Polarity>(polarity));
350  pLineRecordMessage->set_shape(static_cast<Odb::Lib::Protobuf::LineShape>(shape));
351  pLineRecordMessage->set_width(width);
352  return pLineRecordMessage;
353  }
354 
355  void StandardFontsFile::CharacterBlock::LineRecord::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord& message)
356  {
357  xStart = message.xstart();
358  yStart = message.ystart();
359  xEnd = message.xend();
360  yEnd = message.yend();
361  polarity = static_cast<Odb::Lib::Polarity>(message.polarity());
362  shape = static_cast<LineShape>(message.shape());
363  width = message.width();
364  }
365 
366 }