diff --git a/SWI-cpp2.cpp b/SWI-cpp2.cpp index 30427f0..f00c531 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(static_cast(rep), static_cast(-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(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 ac82bab..8f6a7d2 100644 --- a/SWI-cpp2.h +++ b/SWI-cpp2.h @@ -294,8 +294,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())) @@ -303,13 +303,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) + 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) // TODO: rep as optional with default 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())) { } @@ -343,7 +346,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()); } @@ -387,16 +389,16 @@ 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) + 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)); @@ -406,8 +408,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; } @@ -420,9 +422,10 @@ 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())) + : WrappedC(m) + { } + 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())) @@ -690,8 +693,10 @@ class PlTerm : public WrappedC // 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); } - [[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()); } @@ -782,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. @@ -890,9 +895,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 | 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) { 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 | 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())); } }; @@ -962,11 +969,13 @@ class PlPredicate : public WrappedC explicit PlPredicate(PlFunctor f, PlModule m) : WrappedC(Plx_pred(f.unwrap(), m.unwrap())) { } + // 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)) + : 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; @@ -1035,12 +1044,13 @@ 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); - 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); }; @@ -1048,13 +1058,19 @@ 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 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::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())); } }; @@ -1062,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)); } }; @@ -1071,6 +1088,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)); } }; @@ -1166,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 e62547a..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()); @@ -715,10 +743,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 +781,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 +809,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 +949,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; } @@ -1108,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") :-