Skip to content

Commit 46ade2d

Browse files
authored
Implement Symbol class on top of Python C API for maximum performance (#691)
1 parent 26c362b commit 46ade2d

7 files changed

Lines changed: 1323 additions & 304 deletions

File tree

‎lib/c-api/include/clingo/core.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,13 @@ CLINGO_VISIBILITY_DEFAULT bool clingo_string_builder_copy(clingo_string_builder_
268268
//! @param[in] bld the builder
269269
CLINGO_VISIBILITY_DEFAULT void clingo_string_builder_free(clingo_string_builder_t const *bld);
270270

271+
//! Append the given string to the content of the builder.
272+
//!
273+
//! @param[in] bld the builder
274+
//! @param[in] str the string to append
275+
//! @param[in] n the size of the string to append
276+
CLINGO_VISIBILITY_DEFAULT bool clingo_string_builder_append(clingo_string_builder_t *bld, char const *str, size_t n);
277+
271278
//! Get the (zero-terminated) string in the builder.
272279
//!
273280
//! @param[in] bld the builder

‎lib/c-api/src/core.cc‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ extern "C" auto clingo_string_builder_copy(clingo_string_builder_t const *src, c
200200
CLINGO_CATCH;
201201
}
202202

203+
extern "C" auto clingo_string_builder_append(clingo_string_builder_t *bld, char const *str, size_t n) -> bool {
204+
CLINGO_TRY {
205+
*cpp_cast(bld) << std::string_view{str, n};
206+
}
207+
CLINGO_CATCH;
208+
}
209+
203210
extern "C" void clingo_string_builder_free(clingo_string_builder_t const *bld) {
204211
// NOLINTNEXTLINE
205212
delete cpp_cast(bld);

‎lib/python-api/src/solve.cc‎

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ namespace PyClingo {
1313

1414
namespace {
1515

16-
auto symbol_callback(clingo_symbol_t const *symbols, size_t size, void *data) -> bool {
17-
auto *res = static_cast<SymbolVec *>(data);
18-
CLINGO_TRY {
19-
// NOLINTNEXTLINE
20-
res->assign(cpp_cast(symbols), cpp_cast(symbols) + size);
21-
}
22-
CLINGO_CATCH;
23-
}
24-
2516
class ModelIterator {
2617
public:
2718
using iterator_category = std::forward_iterator_tag;
@@ -84,8 +75,7 @@ auto SolveControl::add_nogood(MixedLitSpan const &lits) {
8475
handle_error(clingo_solve_control_add_clause(ctl_, x.data(), x.size()));
8576
}
8677

87-
auto Model::symbols(bool shown, bool atoms, bool terms, bool theory) -> SymbolVec {
88-
auto res = SymbolVec{};
78+
auto Model::symbols(bool shown, bool atoms, bool terms, bool theory) -> Sequence<Symbol> {
8979
clingo_show_type_bitset_t show = 0;
9080
if (shown) {
9181
show |= clingo_show_type_shown;
@@ -99,6 +89,16 @@ auto Model::symbols(bool shown, bool atoms, bool terms, bool theory) -> SymbolVe
9989
if (theory) {
10090
show |= clingo_show_type_theory;
10191
}
92+
auto symbol_callback = [](clingo_symbol_t const *symbols, size_t size, void *data) -> bool {
93+
CLINGO_TRY {
94+
auto *res = static_cast<py::list *>(data);
95+
for (auto const &sym : std::span{symbols, size}) {
96+
res->append(*cpp_cast(&sym));
97+
}
98+
}
99+
CLINGO_CATCH;
100+
};
101+
py::list res;
102102
handle_error(clingo_model_symbols(mdl_, show, symbol_callback, &res));
103103
return res;
104104
}
@@ -117,15 +117,33 @@ auto Model::control() -> SolveControl {
117117
}
118118

119119
auto Model::str() -> std::string {
120+
auto symbol_callback = [](clingo_symbol_t const *symbols, size_t size, void *data) -> bool {
121+
CLINGO_TRY {
122+
auto [bld, res] = *static_cast<std::pair<clingo_string_builder_t *, std::string *> *>(data);
123+
bool comma = false;
124+
for (auto const &sym : std::span{symbols, size}) {
125+
if (comma) {
126+
res->append(", ");
127+
}
128+
clingo_string_builder_clear(bld);
129+
if (!clingo_symbol_to_string(sym, bld)) {
130+
return false;
131+
}
132+
clingo_string_t str;
133+
if (!clingo_string_builder_string(bld, &str)) {
134+
return false;
135+
}
136+
res->append(str.data, str.size);
137+
comma = true;
138+
}
139+
}
140+
CLINGO_CATCH;
141+
};
120142
auto res = std::string{};
121-
auto comma = false;
122-
for (auto const &sym : symbols(true, false, false, false)) {
123-
res += comma ? ", " : "";
124-
res += sym.str();
125-
comma = true;
126-
}
143+
auto data = std::pair{string_builder(), &res};
144+
handle_error(clingo_model_symbols(mdl_, clingo_show_type_shown, symbol_callback, &data));
127145
return res;
128-
};
146+
}
129147

130148
auto Model::type() -> clingo_model_type_e {
131149
clingo_model_type_t type = 0;

‎lib/python-api/src/solve.hh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class Model {
5151
public:
5252
Model(clingo_model_t const *mdl) : mdl_{mdl} {}
5353

54-
auto symbols(bool shown, bool atoms, bool terms, bool theory) -> SymbolVec;
54+
auto symbols(bool shown, bool atoms, bool terms, bool theory) -> Sequence<Symbol>;
5555
auto contains(Symbol atom) -> bool;
5656
auto control() -> SolveControl;
5757
auto type() -> clingo_model_type_e;

0 commit comments

Comments
 (0)