From ff6c43e68b15fa959d6aaeaedd45d3e5bea841f4 Mon Sep 17 00:00:00 2001 From: mgondan Date: Sun, 19 Apr 2026 10:16:19 +0200 Subject: [PATCH 1/3] PlEncoding headers for frequent Pl-objects Would you please check if I am on the right path? Then I will add a few unit tests and make a few cosmetic changes. --- SWI-cpp2.cpp | 8 ++++---- SWI-cpp2.h | 40 ++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/SWI-cpp2.cpp b/SWI-cpp2.cpp index 4b65b7d..a0db88b 100644 --- a/SWI-cpp2.cpp +++ b/SWI-cpp2.cpp @@ -722,8 +722,8 @@ PlCompound::PlCompound(const std::wstring& text) } _SWI_CPP2_CPP_inline -PlCompound::PlCompound(const char *functor, const PlTermv& args) -{ functor_t f = Plx_new_functor(Plx_new_atom(functor), args.size()); +PlCompound::PlCompound(const char *functor, const PlTermv& args, PlEncoding rep) +{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars((int) rep, -1, functor), args.size()); PlEx(f != (functor_t)0); Plx_cons_functor_v(unwrap(), f, args.termv()); } @@ -736,8 +736,8 @@ PlCompound::PlCompound(const wchar_t *functor, const PlTermv& args) } _SWI_CPP2_CPP_inline -PlCompound::PlCompound(const std::string& functor, const PlTermv& args) -{ functor_t f = Plx_new_functor(Plx_new_atom_nchars(functor.size(), functor.data()), args.size()); +PlCompound::PlCompound(const std::string& functor, const PlTermv& args, PlEncoding rep) +{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars((int) rep, functor.size(), functor.data()), args.size()); Plx_cons_functor_v(unwrap(), f, args.termv()); } diff --git a/SWI-cpp2.h b/SWI-cpp2.h index 1c31ce9..26f9415 100644 --- a/SWI-cpp2.h +++ b/SWI-cpp2.h @@ -305,10 +305,16 @@ class PlAtom : public WrappedC explicit PlAtom(const char *text) : WrappedC(Plx_new_atom_nchars(static_cast(-1), text)) { } - explicit PlAtom(PlEncoding rep, size_t len, const char *s) + // explicit PlAtom(PlEncoding rep, size_t len, const char *s) + // : WrappedC(Plx_new_atom_mbchars(static_cast(rep), len, s)) + // { } + explicit PlAtom(size_t len, const char *s, PlEncoding rep /* =ENC_INPUT */) : WrappedC(Plx_new_atom_mbchars(static_cast(rep), len, s)) { } - explicit PlAtom(PlEncoding rep, std::string& text) // TODO: rep as optional with default ENC_INPUT + // explicit PlAtom(PlEncoding rep, std::string& text) + // : WrappedC(Plx_new_atom_mbchars(static_cast(rep), text.size(), text.data())) + // { } + explicit PlAtom(const std::string& text, PlEncoding rep /* =ENC_INPUT */) : WrappedC(Plx_new_atom_mbchars(static_cast(rep), text.size(), text.data())) { } @@ -388,14 +394,14 @@ class PlFunctor : public WrappedC // PlFunctor(const char*) is handled by std::string constructor // TODO: add encoding to string - explicit PlFunctor(const std::string& name, size_t arity) + explicit PlFunctor(const std::string& name, size_t arity, PlEncoding rep=ENC_INPUT) : WrappedC(null) - { PlAtom a(name); + { PlAtom a(name, rep); reset_wrapped(Plx_new_functor(a.unwrap(), arity)); Plx_unregister_atom(a.unwrap()); } - explicit PlFunctor(const std::wstring& name, size_t arity) + explicit PlFunctor(const std::wstring& name, size_t arity, PlEncoding rep=ENC_INPUT) : WrappedC(null) { PlAtom a(name); reset_wrapped(Plx_new_functor(a.unwrap(), arity)); @@ -420,8 +426,8 @@ class PlModule : public WrappedC public: explicit PlModule(module_t m = 0) : WrappedC(m) { } - explicit PlModule(const std::string& name) - : WrappedC(Plx_new_module(PlAtom(name).unwrap())) + explicit PlModule(const std::string& name, PlEncoding rep=ENC_INPUT) + : WrappedC(Plx_new_module(PlAtom(name, rep).unwrap())) { } explicit PlModule(PlAtom name) : WrappedC(Plx_new_module(name.unwrap())) @@ -888,9 +894,11 @@ class PlTerm_atom : public PlTerm // For now, these are safe only with ASCII (PlEncoding::Latin1): explicit PlTerm_atom(atom_t a) { Plx_put_atom(unwrap(), a); } explicit PlTerm_atom(PlAtom a) { Plx_put_atom(unwrap(), a.unwrap()); } - explicit PlTerm_atom(const char *text) { Plx_put_atom_chars(unwrap(), text); } // TODO: add encoding + explicit PlTerm_atom(const char *text, PlEncoding rep=ENC_INPUT) + { Plx_put_chars(unwrap(), PL_ATOM | (int) rep, -1, text); } explicit PlTerm_atom(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_ATOM, static_cast(-1), text)); } - explicit PlTerm_atom(const std::string& text) { Plx_put_atom_nchars(unwrap(), text.size(), text.data()); } // TODO: add encoding + explicit PlTerm_atom(const std::string& text, PlEncoding rep=ENC_INPUT) + { Plx_put_chars(unwrap(), PL_ATOM | (int) rep, text.size(), text.data()); } explicit PlTerm_atom(const std::wstring& text) { PlEx(Plx_unify_wchars(unwrap(), PL_ATOM, text.size(), text.data())); } }; @@ -960,7 +968,7 @@ class PlPredicate : public WrappedC explicit PlPredicate(PlFunctor f, PlModule m) : WrappedC(Plx_pred(f.unwrap(), m.unwrap())) { } - explicit PlPredicate(const char *name, int arity, const char *module) + explicit PlPredicate(const char *name, int arity, const char *module, PlEncoding rep=ENC_INPUT) : WrappedC(Plx_predicate(name, arity, module)) { } explicit PlPredicate(const std::string& name, int arity, const std::string& module) @@ -1036,9 +1044,9 @@ class PlCompound : public PlTerm explicit PlCompound(const wchar_t *text); explicit PlCompound(const std::string& text, PlEncoding enc=ENC_INPUT); explicit PlCompound(const std::wstring& text); - PlCompound(const char *functor, const PlTermv& args); // TODO: PlEncoding + PlCompound(const char *functor, const PlTermv& args, PlEncoding rep=ENC_INPUT); PlCompound(const wchar_t *functor, const PlTermv& args); - PlCompound(const std::string& functor, const PlTermv& args); // TODO: PlEncoding + PlCompound(const std::string& functor, const PlTermv& args, PlEncoding rep=ENC_INPUT); PlCompound(const std::wstring& functor, const PlTermv& args); }; @@ -1046,12 +1054,11 @@ class PlCompound : public PlTerm class PlTerm_string : public PlTerm { public: - // TODO: PlEncoding - PlTerm_string(const char *text) { Plx_put_string_chars(unwrap(), text); } - PlTerm_string(const char *text, size_t len) { Plx_put_string_nchars(unwrap(), len, text); } + PlTerm_string(const char *text, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, -1, text); } + PlTerm_string(const char *text, size_t len, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, len, text); } PlTerm_string(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, static_cast(-1), text)); } PlTerm_string(const wchar_t *text, size_t len) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, len, text));} - PlTerm_string(const std::string& text) { Plx_put_string_nchars(unwrap(), text.size(), text.data()); } + PlTerm_string(const std::string& text, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, text.size(), text.data()); } PlTerm_string(const std::wstring& text) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, text.size(), text.data())); } }; @@ -1069,6 +1076,7 @@ class PlTerm_list_chars : public PlTerm { public: // TODO: PlEncoding + deprecate this interface + // skipped that one PlTerm_list_chars(const char *text) { Plx_put_list_chars(unwrap(), text); } PlTerm_list_chars(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_CHAR_LIST, static_cast(-1), text)); } }; From 9f32199b071c00122e79c2f8a6a1a5808ef4e921 Mon Sep 17 00:00:00 2001 From: mgondan Date: Mon, 20 Apr 2026 21:39:23 +0200 Subject: [PATCH 2/3] PlEncoding for all initializers --- SWI-cpp2.cpp | 8 +++--- SWI-cpp2.h | 74 ++++++++++++++++++++++++++++++---------------------- test_cpp.cpp | 20 ++++++++++++++ 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/SWI-cpp2.cpp b/SWI-cpp2.cpp index a0db88b..65c3502 100644 --- a/SWI-cpp2.cpp +++ b/SWI-cpp2.cpp @@ -723,7 +723,7 @@ PlCompound::PlCompound(const std::wstring& text) _SWI_CPP2_CPP_inline PlCompound::PlCompound(const char *functor, const PlTermv& args, PlEncoding rep) -{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars((int) rep, -1, functor), args.size()); +{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars(static_cast(rep), static_cast(-1), functor), args.size()); PlEx(f != (functor_t)0); Plx_cons_functor_v(unwrap(), f, args.termv()); } @@ -737,7 +737,7 @@ PlCompound::PlCompound(const wchar_t *functor, const PlTermv& args) _SWI_CPP2_CPP_inline PlCompound::PlCompound(const std::string& functor, const PlTermv& args, PlEncoding rep) -{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars((int) rep, functor.size(), functor.data()), args.size()); +{ functor_t f = Plx_new_functor(Plx_new_atom_mbchars(static_cast(rep), functor.size(), functor.data()), args.size()); Plx_cons_functor_v(unwrap(), f, args.termv()); } @@ -863,8 +863,8 @@ PlException::as_string(PlEncoding enc) const // allocating the std::string) even though we specify "throw()" - // telling the truth "noexcept(false)" results in a compilation // error. - (void)enc; // TODO: use this - const_cast(this)->set_what_str(); + (void)enc; // TODO: use this (MG: see next line + const_cast(this)->set_what_str(/* enc? */); return what_str_; } diff --git a/SWI-cpp2.h b/SWI-cpp2.h index 26f9415..5ddac44 100644 --- a/SWI-cpp2.h +++ b/SWI-cpp2.h @@ -293,8 +293,8 @@ class PlAtom : public WrappedC public: explicit PlAtom(atom_t v) : WrappedC(v) { } - explicit PlAtom(const std::string& text) - : WrappedC(Plx_new_atom_nchars(text.size(), text.data())) + explicit PlAtom(const std::string& text, PlEncoding rep=ENC_INPUT) + : WrappedC(Plx_new_atom_mbchars(static_cast(rep), text.size(), text.data())) { } explicit PlAtom(const std::wstring& text) : WrappedC(Plx_new_atom_wchars(text.size(), text.data())) @@ -302,19 +302,16 @@ class PlAtom : public WrappedC explicit PlAtom(const pl_wchar_t *text) : WrappedC(Plx_new_atom_wchars(static_cast(-1), text)) { } - explicit PlAtom(const char *text) - : WrappedC(Plx_new_atom_nchars(static_cast(-1), text)) + explicit PlAtom(const char *text, PlEncoding rep=ENC_INPUT) + : WrappedC(Plx_new_atom_mbchars(static_cast(rep), static_cast(-1), text)) { } - // explicit PlAtom(PlEncoding rep, size_t len, const char *s) - // : WrappedC(Plx_new_atom_mbchars(static_cast(rep), len, s)) - // { } - explicit PlAtom(size_t len, const char *s, PlEncoding rep /* =ENC_INPUT */) + explicit PlAtom(size_t len, const char *s, PlEncoding rep=ENC_INPUT) + : WrappedC(Plx_new_atom_mbchars(static_cast(rep), len, s)) + { } + [[deprecated("use PlAtom(size_t, const char*, PlEncoding)")]] explicit PlAtom(PlEncoding rep, size_t len, const char *s) : WrappedC(Plx_new_atom_mbchars(static_cast(rep), len, s)) { } - // explicit PlAtom(PlEncoding rep, std::string& text) - // : WrappedC(Plx_new_atom_mbchars(static_cast(rep), text.size(), text.data())) - // { } - explicit PlAtom(const std::string& text, PlEncoding rep /* =ENC_INPUT */) + [[deprecated("use PlAtom(std::string&, PlEncoding)")]] explicit PlAtom(PlEncoding rep, std::string& text) : WrappedC(Plx_new_atom_mbchars(static_cast(rep), text.size(), text.data())) { } @@ -348,7 +345,6 @@ class PlAtom : public WrappedC [[deprecated("use PlAtom instead of atom_t")]] bool operator !=(atom_t to) const { return unwrap() != to; } // TODO: when C++17 becomes standard, rename register_ref() to register(). - void register_ref() const { Plx_register_atom(unwrap()); } @@ -392,8 +388,8 @@ class PlFunctor : public WrappedC : WrappedC(v) { } // PlFunctor(const char*) is handled by std::string constructor + // MG: hmm. Couldn't we deprecate and remove all const char* initializers then? - // TODO: add encoding to string explicit PlFunctor(const std::string& name, size_t arity, PlEncoding rep=ENC_INPUT) : WrappedC(null) { PlAtom a(name, rep); @@ -411,8 +407,8 @@ class PlFunctor : public WrappedC explicit PlFunctor(PlAtom name, size_t arity) : WrappedC(Plx_new_functor(name.unwrap(), arity)) { } - [[deprecated("use PlPredicate")]] predicate_t pred(module_t m) const { - predicate_t p = Plx_pred(unwrap(), m); + [[deprecated("use PlPredicate")]] predicate_t pred(module_t m) const + { predicate_t p = Plx_pred(unwrap(), m); return p; } @@ -425,7 +421,8 @@ class PlModule : public WrappedC { public: explicit PlModule(module_t m = 0) - : WrappedC(m) { } + : WrappedC(m) + { } explicit PlModule(const std::string& name, PlEncoding rep=ENC_INPUT) : WrappedC(Plx_new_module(PlAtom(name, rep).unwrap())) { } @@ -692,10 +689,14 @@ class PlTerm : public WrappedC // All the unify_*() methods check for an exception (and throw), so // the return code is whether the unification succeeded or not. // TODO: replace PL_unify_*() with PL_unify_string() and flags, where appropriate - // TODO: encodings for char*, std::string + // TODO: encodings for char*, std::string (MG: see below) [[nodiscard]] bool unify_term(PlTerm t2) const { return Plx_unify(unwrap(), t2.unwrap()); } [[nodiscard]] bool unify_atom(PlAtom a) const { return Plx_unify_atom(unwrap(), a.unwrap()); } [[nodiscard]] bool unify_chars(int flags, size_t len, const char *s) const { return Plx_unify_chars(unwrap(), flags, len, s); } + // MG: The line above would read as + // unify_chars(int flags, size_t len, const char *s, PlEncoding rep=ENC_INPUT) const + // { return Plx_unify_chars(unwrap(), flags | rep, len, s); } + // Do we need this? I tend to yes, because rep can be set as the default [[nodiscard]] bool unify_chars(int flags, const std::string& s) const { return Plx_unify_chars(unwrap(), flags, s.size(), s.data()); } [[nodiscard]] bool unify_atom(const char* v) const { return Plx_unify_atom_chars(unwrap(), v); } [[nodiscard]] bool unify_atom(const wchar_t* v) const { return Plx_unify_wchars(unwrap(), PL_ATOM, static_cast(-1), v); } @@ -786,7 +787,7 @@ class PlTerm : public WrappedC }; -// PlTermScoped is an *experimental* inteface, which may change +// PlTermScoped is an *experimental* interface, which may change // in the future. It implements a PlTerm that is automatically // freed when it goes out of scope. The API is similar to // std::unique_ptr. @@ -895,10 +896,10 @@ class PlTerm_atom : public PlTerm explicit PlTerm_atom(atom_t a) { Plx_put_atom(unwrap(), a); } explicit PlTerm_atom(PlAtom a) { Plx_put_atom(unwrap(), a.unwrap()); } explicit PlTerm_atom(const char *text, PlEncoding rep=ENC_INPUT) - { Plx_put_chars(unwrap(), PL_ATOM | (int) rep, -1, text); } + { Plx_put_chars(unwrap(), PL_ATOM | static_cast(rep), static_cast(-1), text); } explicit PlTerm_atom(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_ATOM, static_cast(-1), text)); } explicit PlTerm_atom(const std::string& text, PlEncoding rep=ENC_INPUT) - { Plx_put_chars(unwrap(), PL_ATOM | (int) rep, text.size(), text.data()); } + { Plx_put_chars(unwrap(), PL_ATOM | static_cast(rep), text.size(), text.data()); } explicit PlTerm_atom(const std::wstring& text) { PlEx(Plx_unify_wchars(unwrap(), PL_ATOM, text.size(), text.data())); } }; @@ -968,11 +969,13 @@ class PlPredicate : public WrappedC explicit PlPredicate(PlFunctor f, PlModule m) : WrappedC(Plx_pred(f.unwrap(), m.unwrap())) { } - explicit PlPredicate(const char *name, int arity, const char *module, PlEncoding rep=ENC_INPUT) - : WrappedC(Plx_predicate(name, arity, module)) + // MG: Should we add PlEncoding here? I tend to yes. + // Would be something like PlPredicate(PlFunctor(name, arity, rep), module) + explicit PlPredicate(const char *name, int arity, const char *module) + : WrappedC(Plx_predicate(name, arity, module)) { } explicit PlPredicate(const std::string& name, int arity, const std::string& module) - : WrappedC(Plx_predicate(name.c_str(), arity, module.c_str())) + : WrappedC(Plx_predicate(name.c_str(), arity, module.c_str())) { } void predicate_info(PlAtom *name, size_t *arity, PlModule *module) { atom_t n; @@ -1041,6 +1044,7 @@ class PlTermv class PlCompound : public PlTerm { public: + // PlCompound("parent(alex, matthias") or what? Do you want to keep this? explicit PlCompound(const wchar_t *text); explicit PlCompound(const std::string& text, PlEncoding enc=ENC_INPUT); explicit PlCompound(const std::wstring& text); @@ -1054,12 +1058,19 @@ class PlCompound : public PlTerm class PlTerm_string : public PlTerm { public: - PlTerm_string(const char *text, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, -1, text); } - PlTerm_string(const char *text, size_t len, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, len, text); } - PlTerm_string(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, static_cast(-1), text)); } - PlTerm_string(const wchar_t *text, size_t len) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, len, text));} - PlTerm_string(const std::string& text, PlEncoding rep=ENC_INPUT) { Plx_put_chars(unwrap(), PL_STRING | (int) rep, text.size(), text.data()); } - PlTerm_string(const std::wstring& text) { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, text.size(), text.data())); } + // Commented out because this does not seem to be necessary (see a few lines below) + // PlTerm_string(const char *text, PlEncoding rep=ENC_INPUT) + // { Plx_put_chars(unwrap(), PL_STRING | static_cast(rep), static_cast(-1), text); } + PlTerm_string(const char *text, size_t len, PlEncoding rep=ENC_INPUT) + { Plx_put_chars(unwrap(), PL_STRING | static_cast(rep), len, text); } + PlTerm_string(const wchar_t *text) + { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, static_cast(-1), text)); } + PlTerm_string(const wchar_t *text, size_t len) + { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, len, text));} + PlTerm_string(const std::string& text, PlEncoding rep=ENC_INPUT) // here + { Plx_put_chars(unwrap(), PL_STRING | static_cast(rep), text.size(), text.data()); } + PlTerm_string(const std::wstring& text) + { PlEx(Plx_unify_wchars(unwrap(), PL_STRING, text.size(), text.data())); } }; @@ -1067,6 +1078,7 @@ class PlTerm_list_codes : public PlTerm { public: // TODO: PlEncoding + deprecate this interface + // I'll skip that one since it's deprecated PlTerm_list_codes(const char *text) { Plx_put_list_codes(unwrap(), text); } PlTerm_list_codes(const wchar_t *text) { PlEx(Plx_unify_wchars(unwrap(), PL_CODE_LIST, static_cast(-1), text)); } }; @@ -1172,7 +1184,7 @@ class PlRecordExternalCopy : C_(external) { } - PlRecordExternalCopy(const char*external, size_t len) + PlRecordExternalCopy(const char *external, size_t len) : C_(std::string(external, len)) { } diff --git a/test_cpp.cpp b/test_cpp.cpp index 1f041b5..54ba171 100644 --- a/test_cpp.cpp +++ b/test_cpp.cpp @@ -715,10 +715,14 @@ PREDICATE(ensure_PlTerm_forward_declarations_are_implemented, 0) *********************************************************************/ PlTerm_var t_var; PlTerm_atom t_atom1("abc"); + PlTerm_atom t_atom1a("abc", PlEncoding::UTF8); PlTerm_atom t_atom2(L"ABC"); + PlTerm_atom t_atom2a("ABC", PlEncoding::UTF8); PlTerm_atom t_atom3(PlAtom("an atom")); PlTerm_atom p_atom4(std::string("abc")); PlTerm_atom p_atom5(std::wstring(L"世界")); + PlTerm_atom p_atom5a(std::string("世界"), PlEncoding::UTF8); + PlTerm_term_t t_t(Plx_new_term_ref()); PlTerm_term_t t_null(PlTerm::null); PlTerm t_t2(Plx_new_term_ref()); @@ -749,6 +753,7 @@ PREDICATE(ensure_PlTerm_forward_declarations_are_implemented, 0) PlTerm_string t_string1("abc"); PlTerm_string t_string2(L"世界"); + PlTerm_string t_string3("世界", PlEncoding::UTF8); const char codes[] = {81,82,83,0}; PlTerm_list_codes s02(codes); PlTerm_list_chars s03("mno"); @@ -776,8 +781,14 @@ PREDICATE(ensure_PlTerm_forward_declarations_are_implemented, 0) PlAtom atom1("atom1"); PlAtom atom2(L"原子2"); + PlAtom atom2a("原子2", PlEncoding::UTF8); + PlAtom atom2b(2, "原子2", PlEncoding::UTF8); + // PlAtom atom2c(PlEncoding::UTF8, 2, "原子2"); // deprecated PlAtom atom3(std::string("atom3")); PlAtom atom4(std::wstring(L"原子4")); + PlAtom atom4a(std::string("原子4"), PlEncoding::UTF8); + std::string s4b("原子4"); + // PlAtom atom4b(PlEncoding::UTF8, s4b); // deprecated PlAtom a5a(t_atom1.as_atom()); PlAtom atom_null(PlAtom::null); // The following are unsafe (the as_string() is deleted in the statement): @@ -910,6 +921,15 @@ PREDICATE(ensure_PlTerm_forward_declarations_are_implemented, 0) // TODO: the rest of the methods strm.release(); + PlFunctor f1(std::string("functor1"), 1, ENC_INPUT); + PlFunctor f2(std::string("世界2"), 2, PlEncoding::UTF8); + PlFunctor f3(std::wstring(L"世界3"), 3); + PlFunctor f4(PlAtom("世界", PlEncoding::UTF8), 4); + + PlCompound c5("functor5", PlTermv(t_int1, t_int2), PlEncoding::UTF8); + PlCompound c6(L"世界6", PlTermv(t_int1, t_int2)); + PlCompound c7(std::string("世界7"), PlTermv(t_int1, t_int2), PlEncoding::UTF8); + PlCompound c8(std::wstring(L"世界8"), PlTermv(t_int1, t_int2)); return true; } From ff6c7aa9edcb6a9415303845fd155cdb2c1a34b4 Mon Sep 17 00:00:00 2001 From: mgondan Date: Wed, 6 May 2026 22:21:52 +0200 Subject: [PATCH 3/3] added more unit tests --- SWI-cpp2.h | 12 +++++------- test_cpp.cpp | 34 ++++++++++++++++++++++++++++++++++ test_cpp.pl | 12 ++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/SWI-cpp2.h b/SWI-cpp2.h index 07c56bf..8f6a7d2 100644 --- a/SWI-cpp2.h +++ b/SWI-cpp2.h @@ -690,15 +690,13 @@ class PlTerm : public WrappedC // All the unify_*() methods check for an exception (and throw), so // the return code is whether the unification succeeded or not. // TODO: replace PL_unify_*() with PL_unify_string() and flags, where appropriate - // TODO: encodings for char*, std::string (MG: see below) + // TODO: encodings for char*, std::string [[nodiscard]] bool unify_term(PlTerm t2) const { return Plx_unify(unwrap(), t2.unwrap()); } [[nodiscard]] bool unify_atom(PlAtom a) const { return Plx_unify_atom(unwrap(), a.unwrap()); } - [[nodiscard]] bool unify_chars(int flags, size_t len, const char *s) const { return Plx_unify_chars(unwrap(), flags, len, s); } - // MG: The line above would read as - // unify_chars(int flags, size_t len, const char *s, PlEncoding rep=ENC_INPUT) const - // { return Plx_unify_chars(unwrap(), flags | rep, len, s); } - // Do we need this? I tend to yes, because rep can be set as the default - [[nodiscard]] bool unify_chars(int flags, const std::string& s) const { return Plx_unify_chars(unwrap(), flags, s.size(), s.data()); } + [[nodiscard]] bool unify_chars(int flags, size_t len, const char *s, PlEncoding rep=ENC_INPUT) const + { return Plx_unify_chars(unwrap(), flags | static_cast(rep), len, s); } + [[nodiscard]] bool unify_chars(int flags, const std::string& s, PlEncoding rep=ENC_INPUT) const + { return Plx_unify_chars(unwrap(), flags | static_cast(rep), s.size(), s.data()); } [[nodiscard]] bool unify_atom(const char* v) const { return Plx_unify_atom_chars(unwrap(), v); } [[nodiscard]] bool unify_atom(const wchar_t* v) const { return Plx_unify_wchars(unwrap(), PL_ATOM, static_cast(-1), v); } [[nodiscard]] bool unify_atom(const std::string& v) const { return Plx_unify_atom_nchars(unwrap(), v.size(), v.data()); } diff --git a/test_cpp.cpp b/test_cpp.cpp index 1825b40..f802d70 100644 --- a/test_cpp.cpp +++ b/test_cpp.cpp @@ -166,6 +166,34 @@ PREDICATE(hello4, 1) return hello_world.unify_term(hello_world_compound); } +PREDICATE(hello5, 3) +{ PlCheckFail(A1.unify_atom("abc")); + PlCheckFail(A2.unify_atom(std::wstring(L"世界"))); + PlCheckFail(A3.unify_chars(PL_ATOM|REP_UTF8, -1, "世界")); + return true; +} + +PREDICATE(hello6, 3) +{ PlCheckFail(A1.unify_atom(PlAtom("abc"))); + PlCheckFail(A2.unify_atom(PlAtom(std::wstring(L"世界")))); + PlCheckFail(A3.unify_atom(PlAtom(std::string("世界"), PlEncoding::UTF8))); + return true; +} + +PREDICATE(hello7, 3) +{ PlCheckFail(A1.unify_string("abc")); + PlCheckFail(A2.unify_wstring(L"世界")); + PlCheckFail(A3.unify_chars(PL_STRING|REP_UTF8, -1, "世界")); + return true; +} + +PREDICATE(hello8, 3) +{ PlCheckFail(A1.unify_term(PlCompound("abc", PlTermv(PlTerm_atom(L"世界"), PlTerm_atom("世界", PlEncoding::UTF8)), PlEncoding::UTF8))); + PlCheckFail(A2.unify_term(PlCompound(L"世界", PlTermv(PlTerm_atom("世界", PlEncoding::UTF8), PlTerm_atom("abc", PlEncoding::UTF8))))); + PlCheckFail(A3.unify_term(PlCompound("世界", PlTermv(PlTerm_atom("abc", PlEncoding::UTF8), PlTerm_atom(L"世界")), PlEncoding::UTF8))); + return true; +} + // TODO: add tests PREDICATE(as_string, 2) { return A2.unify_string(A1.as_string()); @@ -1128,6 +1156,12 @@ PREDICATE(unify_foo_string_2b, 1) return A1.unify_term(foo); } +// 1.0 sec +PREDICATE(unify_foo_string_2c, 1) +{ PlTerm_string foo("世界", PlEncoding::UTF8); + return A1.unify_term(foo); +} + // end of benchmarking predicates // Example pl_write_atoms from foreign.doc diff --git a/test_cpp.pl b/test_cpp.pl index f1d4f04..0648c9b 100644 --- a/test_cpp.pl +++ b/test_cpp.pl @@ -112,6 +112,18 @@ test(hello4, Out == hello(world)) :- hello4(Out). +test(hello5, [Out1, Out2, Out3] == [abc, 世界, 世界]) :- + hello5(Out1, Out2, Out3). + +test(hello6, [Out1, Out2, Out3] == [abc, 世界, 世界]) :- + hello6(Out1, Out2, Out3). + +test(hello7, [Out1, Out2, Out3] == ["abc", "世界", "世界"]) :- + hello7(Out1, Out2, Out3). + +test(hello8, [Out1, Out2, Out3] == [abc(世界, 世界), 世界(世界, abc), 世界(abc, 世界)]) :- + hello8(Out1, Out2, Out3). + test(call_cpp, Out == "hello(foo)\n") :- with_output_to(string(Out), call_cpp(writeln(hello(foo)))). test(call_cpp, Out == "hello(世界四)\n") :-