6 #include "knowrob/reasoner/mongolog/bson_pl.h"
7 #include "knowrob/storage/mongo/MongoException.h"
11 #define APPEND_BSON_PL_PAIR(list,key,value,type) ((PlTail*)list)->append(PlCompound("-", \
12 PlTermv(PlTerm(key), PlCompound(type, PlTerm(value))))) && false
14 static bool bson_visit_double([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
double v_double,
void *data) {
18 static bool bson_visit_int32([[maybe_unused]]
const bson_iter_t *iter,
const char *key, int32_t v_int32,
void *data) {
22 static bool bson_visit_int64([[maybe_unused]]
const bson_iter_t *iter,
const char *key, int64_t v_int64,
void *data) {
26 static bool bson_visit_oid([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
const bson_oid_t *v_oid,
void *data) {
28 bson_oid_to_string(v_oid, str);
32 static bool bson_visit_bool([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
bool v_bool,
void *data) {
33 static PlAtom ATOM_true(
"true");
34 static PlAtom ATOM_false(
"false");
44 static bool bson_visit_utf8([[maybe_unused]]
const bson_iter_t *iter, [[maybe_unused]]
const char *key,
size_t v_utf8_len,
const char *v_utf8,
void *data) {
50 static bool bson_visit_date_time([[maybe_unused]]
const bson_iter_t *iter,
const char *key, int64_t msec_since_epoch,
void *data) {
51 double sec_since_epoch = ((double)msec_since_epoch)/1000.0;
55 static bool bson_visit_decimal128([[maybe_unused]]
const bson_iter_t *iter,
const bson_decimal128_t *v_decimal128,
void *data) {
56 static PlAtom ATOM_Neg_Infinity(
"-Infinity");
57 static PlAtom ATOM_Pos_Infinity(
"Infinity");
59 auto *v_pl = (PlTail*)data;
61 if(v_decimal128->high == 0x7800000000000000) {
62 v_pl->append(PlCompound(
"double", PlTerm(ATOM_Pos_Infinity)));
65 else if(v_decimal128->high == 0xf800000000000000) {
66 v_pl->append(PlCompound(
"double", PlTerm(ATOM_Neg_Infinity)));
69 char buffer[BSON_DECIMAL128_STRING];
70 bson_decimal128_to_string(v_decimal128,buffer);
71 setlocale(LC_NUMERIC,
"C");
72 v_pl->append(PlCompound(
"double", PlTerm(atof(buffer))));
73 setlocale(LC_NUMERIC,
"");
78 static bool bson_visit_decimal128([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
const bson_decimal128_t *v_decimal128,
void *data) {
79 static PlAtom ATOM_Neg_Infinity(
"-Infinity");
80 static PlAtom ATOM_Pos_Infinity(
"Infinity");
82 auto *out_list = (PlTail*)data;
84 v_pl[0] = PlTerm(key);
86 if(v_decimal128->high == 0x7800000000000000) {
87 v_pl[1] = PlCompound(
"double", PlTerm(ATOM_Pos_Infinity));
90 else if(v_decimal128->high == 0xf800000000000000) {
91 v_pl[1] = PlCompound(
"double", PlTerm(ATOM_Neg_Infinity));
94 char buffer[BSON_DECIMAL128_STRING];
95 bson_decimal128_to_string(v_decimal128,buffer);
96 setlocale(LC_NUMERIC,
"C");
97 v_pl[1] = PlCompound(
"double", PlTerm(atof(buffer)));
98 setlocale(LC_NUMERIC,
"");
100 out_list->append(PlCompound(
"-",v_pl));
104 static bool bson_iter_append_array(bson_iter_t *iter, PlTail *pl_array) {
105 static PlAtom ATOM_true(
"true");
106 static PlAtom ATOM_false(
"false");
108 if(BSON_ITER_HOLDS_UTF8(iter)) {
109 pl_array->append(PlCompound(
"string",
110 PlTerm(bson_iter_utf8(iter,
nullptr))));
112 else if(BSON_ITER_HOLDS_DOCUMENT(iter)) {
113 const uint8_t *data =
nullptr;
115 bson_iter_document(iter, &len, &data);
116 bson_t *doc = bson_new_from_data(data, len);
120 else if(BSON_ITER_HOLDS_ARRAY(iter)) {
121 const uint8_t *array =
nullptr;
122 uint32_t array_len = 0;
123 bson_iter_array(iter, &array_len, &array);
124 bson_t *inner_doc = bson_new_from_data(array, array_len);
125 bson_iter_t inner_iter;
127 PlTail inner_array(inner_term);
128 if(bson_iter_init(&inner_iter, inner_doc)) {
129 while(bson_iter_next(&inner_iter)) {
130 bson_iter_append_array(&inner_iter,&inner_array);
134 pl_array->append(PlCompound(
"array",inner_term));
135 bson_destroy(inner_doc);
137 else if(BSON_ITER_HOLDS_DOUBLE(iter)) {
138 pl_array->append(PlCompound(
"double",
139 PlTerm(bson_iter_double(iter))));
141 else if(BSON_ITER_HOLDS_DECIMAL128(iter)) {
142 bson_decimal128_t v_decimal128;
143 bson_iter_decimal128(iter, &v_decimal128);
144 bson_visit_decimal128(iter, &v_decimal128, pl_array);
146 else if(BSON_ITER_HOLDS_INT32(iter)) {
147 pl_array->append(PlCompound(
"int",
148 PlTerm((
long)bson_iter_int32(iter))));
150 else if(BSON_ITER_HOLDS_INT64(iter)) {
151 pl_array->append(PlCompound(
"int",
152 PlTerm((
long)bson_iter_int32(iter))));
154 else if(BSON_ITER_HOLDS_BOOL(iter)) {
155 if(bson_iter_bool(iter)) {
156 pl_array->append(PlCompound(
"bool", PlTerm(ATOM_true)));
159 pl_array->append(PlCompound(
"bool", PlTerm(ATOM_false)));
162 else if(BSON_ITER_HOLDS_DATE_TIME(iter)) {
163 double sec_since_epoch = ((double)bson_iter_date_time(iter))/1000.0;
164 pl_array->append(PlCompound(
"time", PlTerm(sec_since_epoch)));
167 bson_type_t iter_t = bson_iter_type(iter);
168 std::cout <<
"WARN: unsupported array type '" << iter_t <<
"'" << std::endl;
174 static bool bson_visit_array([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
const bson_t *v_array,
void *data) {
176 PlTail pl_array(av[0]);
177 bson_iter_t array_iter;
178 if(bson_iter_init(&array_iter, v_array)) {
179 while(bson_iter_next(&array_iter)) {
180 bson_iter_append_array(&array_iter, &pl_array);
187 static bool bson_visit_document([[maybe_unused]]
const bson_iter_t *iter,
const char *key,
const bson_t *v_document,
void *data) {
188 auto *out_list = (PlTail*)data;
189 out_list->append(PlCompound(
"-",
194 static bson_visitor_t get_bson_visitor() {
195 bson_visitor_t visitor;
196 visitor.visit_double = bson_visit_double;
197 visitor.visit_decimal128 = bson_visit_decimal128;
198 visitor.visit_int32 = bson_visit_int32;
199 visitor.visit_int64 = bson_visit_int64;
200 visitor.visit_bool = bson_visit_bool;
201 visitor.visit_oid = bson_visit_oid;
202 visitor.visit_utf8 = bson_visit_utf8;
204 visitor.visit_date_time = bson_visit_date_time;
205 visitor.visit_array = bson_visit_array;
206 visitor.visit_document = bson_visit_document;
212 static bson_visitor_t visitor = get_bson_visitor();
215 PlTail out_list(
term);
216 if (bson_iter_init(&iter, doc)) {
217 if(bson_iter_visit_all(&iter, &visitor, &out_list)) {
221 MONGOC_ERROR_BSON_INVALID,
222 "BSON iteration prematurely stopped.");
230 static bool bsonpl_append_typed(bson_t *doc,
const char *key,
const PlTerm &
term, bson_error_t *err) {
231 static PlAtom ATOM_array(
"array");
232 static PlAtom ATOM_time(
"time");
233 static PlAtom ATOM_id(
"id");
234 static PlAtom ATOM_regex(
"regex");
235 static PlAtom ATOM_double(
"double");
236 static PlAtom ATOM_bool(
"bool");
237 static PlAtom ATOM_string(
"string");
238 static PlAtom ATOM_integer(
"integer");
239 static PlAtom ATOM_int(
"int");
240 static PlAtom ATOM_true(
"true");
241 static PlAtom ATOM_false(
"false");
243 const PlAtom type_atom(
term.name());
244 const PlTerm &pl_value =
term[1];
245 if(type_atom == ATOM_string) {
246 BSON_APPEND_UTF8(doc, key, (
char*)pl_value);
248 else if(type_atom == ATOM_id) {
250 bson_oid_init_from_string(&oid, (
char*)pl_value);
251 BSON_APPEND_OID(doc,key,&oid);
253 else if(type_atom == ATOM_double) {
255 bson_decimal128_t dec;
256 bson_decimal128_from_string ((
char*)pl_value, &dec);
257 BSON_APPEND_DECIMAL128(doc,key,&dec);
259 else if(type_atom == ATOM_time) {
260 BSON_APPEND_DATE_TIME(doc,key,(
unsigned long long)(1000.0*((
double)pl_value)));
262 else if(type_atom == ATOM_int || type_atom == ATOM_integer) {
263 BSON_APPEND_INT32(doc,key,(
int)pl_value);
265 else if(type_atom == ATOM_bool) {
266 if(pl_value == ATOM_true) {
267 BSON_APPEND_BOOL(doc,key,
true);
269 else if(pl_value == ATOM_false) {
270 BSON_APPEND_BOOL(doc,key,
false);
273 BSON_APPEND_BOOL(doc,key,(
bool)((
int)pl_value));
276 else if(type_atom == ATOM_regex) {
277 BSON_APPEND_REGEX(doc,key,(
char*)pl_value,
"msi");
279 else if(type_atom == ATOM_array) {
280 PlTail pl_list(pl_value);
286 BSON_APPEND_ARRAY_BEGIN(doc, key, &bson_array);
287 while(pl_list.next(pl_member)) {
288 const char *index_key;
290 bson_uint32_to_string(counter, &index_key, index_str,
sizeof index_str);
297 bson_append_array_end(doc, &bson_array);
303 MONGOC_ERROR_BSON_INVALID,
304 "invalid type: %s", (
char*)
term
312 if(PL_is_list((term_t)
term)) {
315 BSON_APPEND_DOCUMENT_BEGIN(doc, key, &nested_doc);
317 bson_append_document_end(doc, &nested_doc);
324 else if(std::string_view(
term.name()) ==
"bson_t") {
327 if(
term.arity()!=1) {
330 MONGOC_ERROR_BSON_INVALID,
331 "invalid bson_t term -- arity should be 1: %s", (
char*)
term
335 const PlTerm &bson_value =
term[1];
336 auto *sub_bson = (bson_t*)bson_value.operator
void *();
338 bool success = bson_concat(doc, sub_bson);
339 bson_destroy(sub_bson);
345 MONGOC_ERROR_BSON_INVALID,
346 "invalid bson_t term -- void pointer is null: %s", (
char*)
term
353 return bsonpl_append_typed(doc,key,
term,err);
361 if(!list.next(member)) {
365 else if(PL_is_list((term_t)member)) {
371 }
while(list.next(member));
376 const char *key = (
char*)member;
PlTerm bson_to_term(const bson_t *doc)
#define APPEND_BSON_PL_PAIR(list, key, value, type)
bool bsonpl_concat(bson_t *doc, const PlTerm &term, bson_error_t *err)
bool bsonpl_append(bson_t *doc, const char *key, const PlTerm &term, bson_error_t *err)