102 while (std::getline(stream, line))
105 if (line ==
"COLUMNS")
110 std::string nextLine;
111 if (!parseColumns(stream, nextLine))
116 if (!nextLine.empty())
118 std::string afterBlock;
119 if (!parseVersionDef(stream, nextLine, afterBlock))
122 while (!afterBlock.empty())
125 if (!parseVersionDef(stream, afterBlock, next))
132 while (std::getline(stream, line))
139 if (!parseVersionDef(stream, line, next))
142 while (!next.empty())
144 std::string afterBlock;
145 if (!parseVersionDef(stream, next, afterBlock))
159 while (std::getline(stream, line))
168 if (line.starts_with(
"BUILD") || line.starts_with(
"LAYOUT"))
176 auto commentPos = line.find(
"//");
177 if (commentPos != std::string::npos)
189 auto angleBracketStart = line.find(
'<');
190 auto angleBracketEnd = line.find(
'>');
192 if (angleBracketStart != std::string::npos && angleBracketEnd != std::string::npos
193 && angleBracketEnd > angleBracketStart)
196 std::string foreignRef = line.substr(angleBracketStart + 1, angleBracketEnd - angleBracketStart - 1);
198 auto colonPos = foreignRef.find(
"::");
199 if (colonPos != std::string::npos)
201 col.
foreignDb = foreignRef.substr(0, colonPos);
202 col.
foreignCol = foreignRef.substr(colonPos + 2);
205 std::string remainder =
trimWhitespace(line.substr(angleBracketEnd + 1));
206 col.
name = remainder;
211 auto spacePos = line.find(
' ');
212 if (spacePos == std::string::npos)
215 col.
type = line.substr(0, spacePos);
220 if (!col.
name.empty() && col.
name.back() ==
'?')
226 m_columns.push_back(col);
237 auto processHeaderLine = [&](
const std::string& line)
239 if (line.starts_with(
"LAYOUT "))
243 for (
auto& h : hashes)
246 else if (line.starts_with(
"BUILD "))
254 for (
auto& token : buildList)
260 auto dashPos = token.find(
'-');
261 if (dashPos != std::string::npos)
273 else if (line.starts_with(
"COMMENT "))
280 processHeaderLine(firstLine);
283 bool inHeader =
true;
285 while (std::getline(stream, line))
298 if (inHeader && (line.starts_with(
"BUILD ") || line.starts_with(
"LAYOUT ") || line.starts_with(
"COMMENT ")))
300 processHeaderLine(line);
310 auto commentPos = line.find(
"//");
311 if (commentPos != std::string::npos)
321 if (line.starts_with(
"$"))
323 auto endAnnotation = line.find(
'$', 1);
324 if (endAnnotation != std::string::npos)
326 std::string annotations = line.substr(1, endAnnotation - 1);
328 for (
const auto& p : parts)
333 else if (trimmed ==
"relation")
335 else if (trimmed ==
"noninline")
344 std::string fieldStr = line;
347 auto bracketStart = fieldStr.find(
'[');
348 auto bracketEnd = fieldStr.find(
']');
349 if (bracketStart != std::string::npos && bracketEnd != std::string::npos)
351 std::string arraySizeStr = fieldStr.substr(bracketStart + 1, bracketEnd - bracketStart - 1);
352 field.
arraySize =
static_cast<unsigned int>(std::stoul(arraySizeStr));
353 fieldStr = fieldStr.substr(0, bracketStart);
357 auto angleStart = fieldStr.find(
'<');
358 auto angleEnd = fieldStr.find(
'>');
359 if (angleStart != std::string::npos && angleEnd != std::string::npos)
361 field.
sizeStr = fieldStr.substr(angleStart + 1, angleEnd - angleStart - 1);
362 fieldStr = fieldStr.substr(0, angleStart);
366 verDef.
fields.push_back(field);
370 m_versions.push_back(verDef);