OdbDesignLib
OdbDesign ODB++ Parsing Library
 
Loading...
Searching...
No Matches
AttrListFile.cpp
1//
2// Created by nmill on 10/13/2023.
3//
4
5#include "AttrListFile.h"
6#include <string>
7#include <fstream>
8#include "../parse_error.h"
9#include "../invalid_odb_error.h"
10#include "Logger.h"
11#include "str_utils.h"
12#include "../../Constants.h"
13#include <ArchiveExtractor.h>
14
15namespace Odb::Lib::FileModel::Design
16{
17 AttrListFile::AttrListFile()
18 : m_directory("")
19 , m_path("")
20 , m_units("")
21 {
22 }
23
24 std::string AttrListFile::GetUnits() const
25 {
26 return m_units;
27 }
28
29 const AttrListFile::AttributeMap& AttrListFile::GetAttributes() const
30 {
31 return m_attributesByName;
32 }
33
34 bool Lib::FileModel::Design::AttrListFile::Parse(std::filesystem::path directory)
35 {
36 std::ifstream attrListFile;
37 int lineNumber = 0;
38 std::string line;
39
40 try
41 {
42 m_directory = directory;
43
44 loginfo("checking for extraction...");
45
46 std::filesystem::path attrListFilePath;
47 for (const std::string attrListFilename : ATTRLIST_FILENAMES)
48 {
49 loginfo("trying attrlist file: [" + attrListFilename + "]...");
50
51 attrListFilePath = Utils::ArchiveExtractor::getUncompressedFilePath(m_directory, attrListFilename);
52 if (exists(attrListFilePath) && is_regular_file(attrListFilePath))
53 {
54 loginfo("found attrlist file: [" + attrListFilePath.string() + "]");
55 break;
56 }
57 }
58
59 m_path = attrListFilePath;
60
61 loginfo("any extraction complete, parsing data...");
62
63 if (!std::filesystem::exists(m_path))
64 {
65 auto message = "attrlist file does not exist: [" + m_directory.string() + "]";
66 logwarn(message);
67 return true;
68 //throw invalid_odb_error(message.c_str());
69 }
70 else if (!std::filesystem::is_regular_file(m_path))
71 {
72 auto message = "attrlist is not a file: [" + m_path.string() + "]";
73 throw invalid_odb_error(message.c_str());
74 }
75
76 attrListFile.open(m_path.string(), std::ios::in);
77 if (!attrListFile.is_open())
78 {
79 auto message = "unable to open attrlist file: [" + m_path.string() + "]";
80 throw invalid_odb_error(message.c_str());
81 }
82
83 while (std::getline(attrListFile, line))
84 {
85 lineNumber++;
86
87 // trim whitespace from beginning and end of line
88 Utils::str_trim(line);
89 if (!line.empty())
90 {
91 std::stringstream lineStream(line);
92 //char firstChar = line[0];
93
94 if (line.find(Constants::COMMENT_TOKEN) == 0)
95 {
96 // comment line
97 }
98 else if (line.find(Constants::UNITS_TOKEN) == 0)
99 {
100 // units line
101 std::string token;
102 if (!std::getline(lineStream, token, '='))
103 {
104 throw_parse_error(m_path, line, token, lineNumber);
105 }
106 else if (!std::getline(lineStream, token, '='))
107 {
108 throw_parse_error(m_path, line, token, lineNumber);
109 }
110
111 m_units = token;
112 }
113 else
114 {
115 // attribute line
116 std::string attribute;
117 std::string value;
118
119 if (!std::getline(lineStream, attribute, '='))
120 {
121 throw_parse_error(m_path, line, "", lineNumber);
122 }
123
124 if (!std::getline(lineStream, value))
125 {
126 if (!attributeValueIsOptional(attribute))
127 {
128 logwarn("attrlist file: no value for non-optional attribute: " + attribute);
129 }
130
131 }
132
133 Utils::str_trim(attribute);
134 Utils::str_trim(value);
135
136 m_attributesByName[attribute] = value;
137 }
138 }
139 }
140
141 attrListFile.close();
142 }
143 catch (parse_error& pe)
144 {
145 auto m = pe.toString("Parse Error:");
146 logerror(m);
147 attrListFile.close();
148 throw pe;
149 }
150 catch (std::exception& e)
151 {
152 parse_info pi(m_path, line, lineNumber);
153 const auto m = pi.toString();
154 logexception_msg(e, m);
155 attrListFile.close();
156 throw e;
157 }
158
159 return true;
160 }
161
162 std::unique_ptr<Odb::Lib::Protobuf::AttrListFile> Lib::FileModel::Design::AttrListFile::to_protobuf() const
163 {
164 auto message = std::make_unique<Odb::Lib::Protobuf::AttrListFile>();
165
166 message->set_directory(m_directory.string());
167 message->set_path(m_path.string());
168 message->set_units(m_units);
169
170 for (const auto& kvAttribute : m_attributesByName)
171 {
172 (*message->mutable_attributesbyname())[kvAttribute.first] = kvAttribute.second;
173 }
174
175 return message;
176
177 }
178
179 void Lib::FileModel::Design::AttrListFile::from_protobuf(const Odb::Lib::Protobuf::AttrListFile& message)
180 {
181 m_directory = message.directory();
182 m_path = message.path();
183 m_units = message.units();
184
185 for (const auto& kvAttribute : message.attributesbyname())
186 {
187 m_attributesByName[kvAttribute.first] = kvAttribute.second;
188 }
189 }
190
191 bool Lib::FileModel::Design::AttrListFile::attributeValueIsOptional(const std::string& attributeName) const
192 {
193 //for (const auto& optionalAttribute : OPTIONAL_ATTRIBUTES)
194 //{
195 // if (attributeName == optionalAttribute)
196 // {
197 // return true;
198 // }
199 //}
200 //return false;
201
202 // all atrributes are "optional", i.e. value is not required
203 return true;
204 }
205
206 bool AttrListFile::Save(std::ostream& os)
207 {
208 os << Constants::UNITS_TOKEN << " = " << m_units << std::endl;
209 for (const auto& kvAttribute : m_attributesByName)
210 {
211 os << kvAttribute.first << " = " << kvAttribute.second << std::endl;
212 }
213
214 return true;
215 }
216} // namespace Odb::Lib::FileModel::Design