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