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)