36 : std::runtime_error(msg +
" at line " + std::to_string(
line)), offset_(
offset), line_(
line) {}
37 std::size_t
offset()
const {
return offset_; }
38 int line()
const {
return line_; }
54 const std::string&
text()
const {
return text_; }
58 const Node& n = nodes_[list];
62 const Node& n = nodes_[list];
76 const Node& n = nodes_[id];
77 return std::string_view(text_).substr(n.
begin, n.
end - n.
begin);
85 std::optional<std::int64_t>
nm_at(
NodeId list, std::size_t i)
const;
99 bool modified()
const {
return !edits_.empty(); }
102 void save(
const std::string& path)
const;
109 std::uint32_t begin, end;
115 std::vector<Node> nodes_;
116 std::vector<NodeId> kids_;
118 std::vector<Edit> edits_;
119 mutable std::vector<std::uint32_t> line_starts_;
123std::string
quote(std::string_view s);
129std::optional<std::int64_t>
parse_mm(std::string_view s);
std::string str_at(NodeId list, std::size_t i) const
Value of the i-th child atom of list (i counts the head as 0).
std::span< const NodeId > children(NodeId list) const
-— navigation -—
std::string write() const
Text after applying all edits.
static Document parse(std::string text)
Parses text. Throws ParseError on malformed input. The document owns a copy of the text.
void replace(NodeId id, std::string new_text)
-— edits (applied by write()) -— Replaces the node's text.
std::string_view indent_of(std::size_t offset) const
The indentation (tabs/spaces) at the start of the line containing offset.
void save(const std::string &path) const
std::string str(NodeId atom) const
Atom value: symbols as-is, strings unescaped.
NodeId find(NodeId list, std::string_view name) const
First child list whose head is name, or kNoNode.
const Node & node(NodeId id) const
NodeId child(NodeId list, std::size_t i) const
std::string_view raw(NodeId id) const
-— atoms -— Raw source text of a node (for strings, including quotes).
std::optional< double > number_at(NodeId list, std::size_t i) const
std::optional< std::int64_t > nm_at(NodeId list, std::size_t i) const
Parses a decimal millimetre value to integer nanometres exactly (no binary floating point).
const std::string & text() const
void append_child(NodeId list, std::string_view text)
Inserts text as new children at the end of list, each on its own line, indented one level deeper than...
std::vector< NodeId > find_all(NodeId list, std::string_view name) const
All child lists whose head is name.
std::size_t node_count() const
bool is_list(NodeId id) const
static Document load(const std::string &path)
int line_of(std::size_t offset) const
1-based line number of a byte offset (for error messages).
std::string_view head(NodeId list) const
First token of a list, e.g. "segment" for (segment ...). Empty for atoms or empty lists.
void remove(NodeId id)
Removes the node together with its leading whitespace on the same line and the line break,...
ParseError(const std::string &msg, std::size_t offset, int line)
std::size_t offset() const
std::string format_mm(std::int64_t nm)
Formats nanometres as a KiCad millimetre number: shortest exact decimal, no trailing zeros ("0....
std::string quote(std::string_view s)
Escapes a string for KiCad s-expressions and adds quotes.
std::optional< std::int64_t > parse_mm(std::string_view s)
Parses a decimal millimetre string to nanometres exactly; rounds half away from zero beyond 6 decimal...
std::uint32_t child_count
std::uint32_t end
one past ')' / last char / closing quote
std::uint32_t first_child
index into Document::kids_ (lists only)
std::uint32_t begin
byte offset of '(' / first char of the atom / opening quote