16 #include <initializer_list>
28 template <
typename Keys>
29 std::vector<std::string> sortKeys(std::initializer_list<Keys> keys) {
31 std::vector<std::string> sorted;
32 sorted.reserve(
size(keys));
35 auto const byOpeningLength = [](
auto const&
a,
auto const& b)
37 std::size_t
const al =
a.length(), bl = b.length();
38 return (al != bl)? (al > bl): (
a < b);
40 std::sort(sorted.begin(), sorted.end(), byOpeningLength);
61 : fPTK{ std::move(parserParams) }
62 , fFmt{ std::move(formatParams) }
63 , fKeys{ sortKeys({ fFmt.newKey, fFmt.addKey }) }
74 unsigned int iSrcLine = 0U;
77 auto [ line, nMultiLines ] = fPTK.readMultiline(
s);
78 iSrcLine += nMultiLines;
80 if (line.empty())
continue;
82 std::vector<std::string_view> tokens = fPTK.splitWords(line);
84 fPTK.removeCommentLine(tokens);
85 if (tokens.empty())
continue;
87 keyType
const kType = highlightSeparator(tokens);
88 if (kType == keyType::unsupported) {
89 auto iKey = fKeys.cbegin(), kend = fKeys.cend();
90 std::string l {
"'" + *iKey +
"'" };
91 while (++iKey != kend) l +=
", '" + *iKey +
"'";
93 { iSrcLine - nMultiLines + 1, line,
"no key separator (" + l +
")" };
95 assert(tokens.size() >= 2U);
97 std::vector<std::string> words
98 = fPTK.removeEscapes(fPTK.removeQuotations(tokens));
100 auto iWord = words.begin();
101 ParsedData_t::Item& item = data.makeOrFetchItem(std::move(*iWord));
102 std::advance(iWord, 2);
105 case keyType::create:
110 (std::move_iterator{ iWord }, std::move_iterator{ words.end() });
113 throw ParserError{ iSrcLine - nMultiLines + 1, line,
114 "LOGIC ERROR: '" + std::string{ tokens[1] }
115 +
"' should have been a key separator"
128 (std::string
const&
s)
const -> ParsedData_t
129 {
return parse(std::istringstream{
s }); }
134 (std::vector<std::string_view>& tokens)
const -> keyType
140 if (tokens.empty())
return keyType::unsupported;
145 std::string_view
const firstKey
146 = fPTK.findFirstUnquoted(tokens.front(), fKeys);
148 if (!firstKey.empty()) {
149 auto const [ pre, sep, post ] = fPTK.splitOn(tokens.front(), firstKey);
152 tokens.front() = sep;
153 if (!post.empty()) tokens.insert(std::next(tokens.begin()), post);
154 tokens.insert(tokens.begin(), pre);
155 return keySepType(sep);
161 if (tokens.size() < 2U)
162 return keyType::unsupported;
164 for (std::string
const& sep: fKeys) {
166 if (tokens[1].compare(0, sep.length(), sep) != 0)
continue;
172 if (!tokens[1].
empty()) {
173 std::string_view firstValue = tokens[1];
174 firstValue.remove_prefix(sep.length());
175 tokens.insert(std::next(tokens.begin(), 2), firstValue);
176 tokens[1].remove_suffix(firstValue.length());
179 return keySepType(sep);
185 return keyType::unsupported;
191 template <
typename Key>
195 if (key == fFmt.newKey)
return keyType::create;
196 if (key == fFmt.addKey)
return keyType::add;
197 return keyType::unsupported;
203 (
unsigned int iLine, std::string
const& line, std::string
const&
msg)
206 +
" ('" + line +
"'): " + msg
Simple parser for "key: value" text.
std::size_t size(FixedBins< T, C > const &) noexcept
KeyValueParser(FormatParams_t formatParams=DefaultFormatParameters, icarus::ParsingToolkit::Params_t parserParams=icarus::ParsingToolkit::DefaultParameters)
Creates a parser with the specified parsing parameters.
keyType keySepType(Key const &key) const
Returns the type of key.
static const FormatParams_t DefaultFormatParameters
keyType highlightSeparator(std::vector< std::string_view > &tokens) const
Modifies tokens placing the key/value separator in its own token.
auto end(FixedBins< T, C > const &) noexcept
auto begin(FixedBins< T, C > const &) noexcept
std::string to_string(WindowPattern const &pattern)
then echo File list $list not found else cat $list while read file do echo $file sed s
ParsedData_t parse(std::istream &stream) const
Parses the stream and returns a data structure with the content.
ParserError(unsigned int iLine, std::string const &line, std::string const &msg)
bool empty(FixedBins< T, C > const &) noexcept