Program Listing for File Literal.hpp¶
↰ Return to documentation for file (src/rdf4cpp/Literal.hpp)
#ifndef RDF4CPP_LITERAL_HPP
#define RDF4CPP_LITERAL_HPP
#include <any>
#include <optional>
#include <ostream>
#include <random>
#include <rdf4cpp/Node.hpp>
#include <rdf4cpp/datatypes/LiteralDatatype.hpp>
#include <rdf4cpp/datatypes/owl.hpp>
#include <rdf4cpp/datatypes/rdf.hpp>
#include <rdf4cpp/datatypes/xsd.hpp>
#include <rdf4cpp/regex/Regex.hpp>
#include <rdf4cpp/CowString.hpp>
#include <rdf4cpp/TriBool.hpp>
#include <rdf4cpp/Assert.hpp>
#include <type_traits>
namespace rdf4cpp {
struct Literal : Node {
private:
[[nodiscard]] static bool lexical_form_needs_escape(std::string_view lexical_form) noexcept;
template<typename OpSelect>
requires std::is_nothrow_invocable_r_v<datatypes::registry::DatatypeRegistry::binop_fptr_t, OpSelect, datatypes::registry::DatatypeRegistry::NumericOpsImpl const &>
[[nodiscard]] Literal numeric_binop_impl(OpSelect op_select, Literal const &other, storage::DynNodeStoragePtr node_storage) const;
template<typename OpSelect>
requires std::is_nothrow_invocable_r_v<datatypes::registry::DatatypeRegistry::unop_fptr_t, OpSelect, datatypes::registry::DatatypeRegistry::NumericOpsImpl const &>
[[nodiscard]] Literal numeric_unop_impl(OpSelect op_select, storage::DynNodeStoragePtr node_storage) const;
template<typename Op>
[[nodiscard]] std::optional<Literal> run_binop(Literal const &other,
datatypes::registry::DatatypeIDView const &this_datatype,
datatypes::registry::DatatypeRegistry::DatatypeEntry const &this_entry,
datatypes::registry::DatatypeIDView const &other_datatype,
datatypes::registry::DatatypeRegistry::DatatypeEntry const &other_entry,
storage::DynNodeStoragePtr node_storage,
Op &&op) const;
template<typename Op>
[[nodiscard]] std::optional<Literal> run_binop_cast_rhs(Literal const &other,
datatypes::registry::DatatypeRegistry::DatatypeEntry const &other_entry,
datatypes::registry::DatatypeIDView const &other_target,
storage::DynNodeStoragePtr node_storage,
Op &&op) const;
[[nodiscard]] std::optional<Literal> chrono_add_impl(Literal const &other, storage::DynNodeStoragePtr node_storage) const;
[[nodiscard]] std::optional<Literal> chrono_sub_impl(Literal const &other, storage::DynNodeStoragePtr node_storage) const;
[[nodiscard]] std::optional<Literal> chrono_mul_impl(Literal const &other, storage::DynNodeStoragePtr node_storage) const;
[[nodiscard]] std::optional<Literal> chrono_div_impl(Literal const &other, storage::DynNodeStoragePtr node_storage) const;
std::partial_ordering compare_impl(Literal const &other, std::strong_ordering *out_alternative_ordering = nullptr) const noexcept;
[[nodiscard]] datatypes::registry::DatatypeIDView datatype_id() const noexcept;
[[nodiscard]] bool is_fixed() const noexcept;
[[nodiscard]] bool is_fixed_not_numeric() const noexcept;
[[nodiscard]] bool is_fixed_not_timepoint() const noexcept;
[[nodiscard]] bool is_fixed_not_duration() const noexcept;
[[nodiscard]] bool is_string_like() const noexcept;
[[nodiscard]] static Literal make_simple_unchecked(std::string_view lexical_form, bool needs_escape, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] static Literal make_noninlined_typed_unchecked(std::string_view lexical_form, bool needs_escape, IRI const &datatype, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] static Literal make_noninlined_special_unchecked(std::any &&value, storage::identifier::LiteralType fixed_id, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] static Literal make_inlined_typed_unchecked(storage::identifier::LiteralID inlined_value, storage::identifier::LiteralType fixed_id, storage::DynNodeStoragePtr node_storage) noexcept;
[[nodiscard]] static Literal make_typed_unchecked(std::any &&value, datatypes::registry::DatatypeIDView datatype, datatypes::registry::DatatypeRegistry::DatatypeEntry const &entry, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] static Literal make_lang_tagged_unchecked(std::string_view lexical_form, bool needs_escape, std::string_view lang, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] static Literal make_lang_tagged_unchecked_from_node_id(std::string_view lang, storage::DynNodeStoragePtr node_storage, storage::identifier::NodeBackendID node_id) noexcept;
// TODO needs escape flag
[[nodiscard]] static Literal make_string_like_copy_lang_tag(std::string_view str, Literal const &lang_tag_src, storage::DynNodeStoragePtr node_storage);
[[nodiscard]] Literal lang_tagged_get_de_inlined() const noexcept;
[[nodiscard]] bool dynamic_datatype_eq_impl(std::string_view datatype) const noexcept;
template<bool short_form>
bool serialize_impl(writer::BufWriterParts writer) const noexcept;
template<bool simplified, typename C>
auto serialize_lexical_form_impl(C &&consume) const noexcept;
[[nodiscard]] Literal cast_impl(datatypes::registry::DatatypeIDView target_dtid, storage::DynNodeStoragePtr node_storage) const;
explicit Literal(storage::identifier::NodeBackendHandle handle) noexcept;
public:
Literal() noexcept;
[[nodiscard]] static Literal make_null() noexcept;
[[nodiscard]] static Literal make_simple(std::string_view lexical_form, storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] static Literal make_simple_normalize(std::string_view lexical_form, storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] static Literal make_lang_tagged(std::string_view lexical_form, std::string_view lang_tag,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] static Literal make_lang_tagged_normalize(std::string_view lexical_form, std::string_view lang_tag,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] static Literal make_typed(std::string_view lexical_form, IRI const &datatype,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
template<datatypes::LiteralDatatype T>
[[nodiscard]] static Literal make_typed(std::string_view lexical_form,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage) {
if constexpr (std::is_same_v<T, datatypes::rdf::LangString>) {
// see: https://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal
throw std::invalid_argument{"cannot construct rdf:langString without a language tag, please call one of the other factory functions"};
} else if constexpr (std::is_same_v<T, datatypes::xsd::String>) {
return Literal::make_simple(lexical_form, node_storage);
}
auto value = T::from_string(lexical_form);
if constexpr (datatypes::IsInlineable<T>) {
if (auto const maybe_inlined = T::try_into_inlined(value); maybe_inlined.has_value()) {
return Literal::make_inlined_typed_unchecked(*maybe_inlined, T::fixed_id, node_storage);
}
}
if constexpr (datatypes::HasFixedId<T>) {
if (node_storage.has_specialized_storage_for(T::fixed_id)) {
return Literal::make_noninlined_special_unchecked(std::any{std::move(value)}, T::fixed_id, node_storage);
}
}
auto const lex = writer::StringWriter::oneshot([&value](writer::StringWriter &w) noexcept {
return T::serialize_canonical_string(value, w);
});
auto const needs_escape = lexical_form_needs_escape(lex);
return Literal::make_noninlined_typed_unchecked(lex,
needs_escape,
IRI{T::identifier, node_storage},
node_storage);
}
template<datatypes::LiteralDatatype T>
[[nodiscard]] static Literal make_typed_from_value(typename T::cpp_type const &compatible_value,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage) {
if constexpr (std::is_same_v<T, datatypes::rdf::LangString>) {
return Literal::make_lang_tagged(compatible_value.lexical_form,
compatible_value.language_tag,
node_storage);
}
if constexpr (std::is_same_v<T, datatypes::xsd::String>) {
return Literal::make_simple(compatible_value, node_storage);
}
if constexpr (datatypes::IsInlineable<T>) {
if (auto const maybe_inlined = T::try_into_inlined(compatible_value); maybe_inlined.has_value()) {
return Literal::make_inlined_typed_unchecked(*maybe_inlined, T::fixed_id, node_storage);
}
}
if constexpr (datatypes::HasFixedId<T>) {
if (node_storage.has_specialized_storage_for(T::fixed_id)) {
return Literal{storage::identifier::NodeBackendHandle{node_storage.find_or_make_id(storage::view::ValueLiteralBackendView{
.datatype = T::fixed_id,
.value = std::any{compatible_value}}),
node_storage}};
}
}
auto const lex = writer::StringWriter::oneshot([&compatible_value](writer::StringWriter &w) noexcept {
return T::serialize_canonical_string(compatible_value, w);
});
auto const needs_escape = lexical_form_needs_escape(lex);
return Literal::make_noninlined_typed_unchecked(lex,
needs_escape,
IRI{T::datatype_id, node_storage},
node_storage);
}
static Literal make_boolean(TriBool b, storage::DynNodeStoragePtr node_storage = storage::default_node_storage) noexcept;
[[nodiscard]] static Literal make_string_uuid(storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] static Literal generate_random_double(storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
template<typename Rng>
[[nodiscard]] static Literal generate_random_double(Rng &rng, storage::DynNodeStoragePtr node_storage = storage::default_node_storage) {
// uniform_real_distribution does not have any state, therefore we can construct a new one for each call
std::uniform_real_distribution<typename datatypes::xsd::Double::cpp_type> dist{0.0, 1.0};
return Literal::make_typed_from_value<datatypes::xsd::Double>(dist(rng), node_storage);
}
Literal to_node_storage(storage::DynNodeStoragePtr node_storage) const;
[[nodiscard]] Literal try_get_in_node_storage(storage::DynNodeStoragePtr node_storage) const noexcept;
private:
[[nodiscard]] static storage::identifier::NodeBackendID find_datatype_iri(datatypes::registry::DatatypeIDView id, storage::DynNodeStoragePtr node_storage) noexcept;
public:
[[nodiscard]] static Literal find_simple(std::string_view lexical_form, storage::DynNodeStoragePtr node_storage = storage::default_node_storage) noexcept;
[[nodiscard]] static Literal find_lang_tagged(std::string_view lexical_form, std::string_view lang_tag, storage::DynNodeStoragePtr node_storage = storage::default_node_storage) noexcept;
template<datatypes::LiteralDatatype T>
[[nodiscard]] static Literal find_typed_from_value(typename T::cpp_type const &compatible_value,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage) noexcept {
if constexpr (std::is_same_v<T, datatypes::rdf::LangString>) {
return find_lang_tagged(compatible_value.lexical_form,
compatible_value.language_tag,
node_storage);
}
if constexpr (std::is_same_v<T, datatypes::xsd::String>) {
return find_simple(compatible_value, node_storage);
}
if constexpr (datatypes::IsInlineable<T>) {
if (auto const maybe_inlined = T::try_into_inlined(compatible_value); maybe_inlined.has_value()) {
return Literal::make_inlined_typed_unchecked(*maybe_inlined, T::fixed_id, node_storage);
}
}
if constexpr (datatypes::HasFixedId<T>) {
if (node_storage.has_specialized_storage_for(T::fixed_id)) {
auto nid = node_storage.find_id(storage::view::ValueLiteralBackendView{
.datatype = T::fixed_id,
.value = std::any{compatible_value}});
if (nid.null())
return Literal{};
return Literal{storage::identifier::NodeBackendHandle{nid, node_storage}};
}
}
auto dty = find_datatype_iri(T::datatype_id, node_storage);
if (dty.null())
return Literal{};
auto const lex = writer::StringWriter::oneshot([&compatible_value]<typename W>(W &w) noexcept {
return T::serialize_canonical_string(compatible_value, w);
});
auto const needs_escape = lexical_form_needs_escape(lex);
auto nid = node_storage.find_id(storage::view::LexicalFormLiteralBackendView{
.datatype_id = dty,
.lexical_form = lex,
.language_tag = "",
.needs_escape = needs_escape});
if (nid.null())
return Literal{};
return Literal{storage::identifier::NodeBackendHandle{nid, node_storage}};
}
template<datatypes::LiteralDatatype T>
requires(!std::same_as<T, datatypes::rdf::LangString>)
[[nodiscard]] static Literal find_typed(std::string_view lexical_form,
storage::DynNodeStoragePtr node_storage = storage::default_node_storage) noexcept {
if constexpr (std::is_same_v<T, datatypes::xsd::String>) {
return find_simple(lexical_form, node_storage);
}
if constexpr (datatypes::HasFixedId<T>) {
auto value = T::from_string(lexical_form);
if constexpr (datatypes::IsInlineable<T>) {
if (auto const maybe_inlined = T::try_into_inlined(value); maybe_inlined.has_value()) {
return Literal::make_inlined_typed_unchecked(*maybe_inlined, T::fixed_id, node_storage);
}
}
if (node_storage.has_specialized_storage_for(T::fixed_id)) {
auto nid = node_storage.find_id(storage::view::ValueLiteralBackendView{
.datatype = T::fixed_id,
.value = std::any{value}});
if (nid.null())
return Literal{};
return Literal{storage::identifier::NodeBackendHandle{nid, node_storage}};
}
}
auto dty = find_datatype_iri(T::datatype_id, node_storage);
if (dty.null())
return Literal{};
auto const needs_escape = lexical_form_needs_escape(lexical_form);
auto nid = node_storage.find_id(storage::view::LexicalFormLiteralBackendView{
.datatype_id = dty,
.lexical_form = lexical_form,
.language_tag = "",
.needs_escape = needs_escape});
if (nid.null())
return Literal{};
return Literal{storage::identifier::NodeBackendHandle{nid, node_storage}};
}
template<datatypes::LiteralDatatype T>
[[nodiscard]] bool datatype_eq() const noexcept {
if constexpr (datatypes::HasFixedId<T>) {
if (auto const type = this->handle_.node_id().literal_type(); type.is_fixed()) {
return type == T::fixed_id;
}
return false;
}
return this->dynamic_datatype_eq_impl(T::identifier);
}
[[nodiscard]] bool datatype_eq(IRI const &datatype) const noexcept;
[[nodiscard]] bool datatype_eq(Literal const &other) const noexcept;
template<datatypes::LiteralDatatype T>
[[nodiscard]] Literal as_datatype_eq(storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept {
if (this->null()) {
return Literal{};
}
return Literal::make_boolean(this->datatype_eq<T>(), select_node_storage(node_storage));
}
[[nodiscard]] Literal as_datatype_eq(IRI const &datatype, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_datatype_eq(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal cast(IRI const &target, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
template<datatypes::LiteralDatatype T>
[[nodiscard]] Literal cast(storage::DynNodeStoragePtr node_storage = keep_node_storage) const {
return this->cast_impl(T::datatype_id, node_storage);
}
template<datatypes::LiteralDatatype T>
requires (!std::same_as<T, datatypes::xsd::String>)
std::optional<typename T::cpp_type> cast_to_value() const noexcept {
using namespace datatypes::registry;
using namespace datatypes::xsd;
if (this->null()) {
return std::nullopt;
}
auto const this_dtid = this->datatype_id();
DatatypeIDView const target_dtid = T::datatype_id;
if (this_dtid == target_dtid) {
return this->value<T>();
}
if (this_dtid == String::datatype_id) {
// string -> any
try {
return T::from_string(this->lexical_form());
} catch (...) {
return std::nullopt;
}
}
if constexpr (std::same_as<T, Boolean>) {
// any -> bool
TriBool const t = this->ebv();
if (t == TriBool::Err)
return std::nullopt;
else if (t == TriBool::True)
return true;
else
return false;
}
auto const *target_e = DatatypeRegistry::get_entry(target_dtid);
if (target_e == nullptr) {
// target not registered
return std::nullopt;
}
if (this_dtid == Boolean::datatype_id && target_e->numeric_ops.has_value()) {
// bool -> numeric
if (target_e->numeric_ops->is_impl()) {
auto value = this->template value<Boolean>() ? target_e->numeric_ops->get_impl().one_value_fptr()
: target_e->numeric_ops->get_impl().zero_value_fptr();
return std::any_cast<typename T::cpp_type>(value);
} else {
auto const &impl_converter = DatatypeRegistry::get_numeric_op_impl_conversion(*target_e);
auto const *target_num_impl = DatatypeRegistry::get_numerical_ops(impl_converter.target_type_id);
RDF4CPP_ASSERT(target_num_impl != nullptr);
// perform conversion as impl numeric type
auto const value = this->template value<Boolean>() ? target_num_impl->get_impl().one_value_fptr()
: target_num_impl->get_impl().zero_value_fptr();
// downcast to target
auto target_value = impl_converter.inverted_convert(value);
if (!target_value.has_value()) {
// not representable as target type
return std::nullopt;
}
return std::any_cast<typename T::cpp_type>(*target_value);
}
}
auto const *this_e = DatatypeRegistry::get_entry(this_dtid);
if (this_e == nullptr) {
// this datatype not registered
return std::nullopt;
}
if (auto const common_conversion = DatatypeRegistry::get_common_type_conversion(this_e->conversion_table, target_e->conversion_table); common_conversion.has_value()) {
// general cast
// TODO: if performance is bad split into separate cases for up-, down- and cross-casting to avoid one set of std::any wrapping and unwrapping for the former 2
auto const common_type_value = common_conversion->convert_lhs(this->value()); // upcast to common
auto target_value = common_conversion->inverted_convert_rhs(common_type_value); // downcast to target
if (!target_value.has_value()) {
// downcast failed
return std::nullopt;
}
return std::any_cast<typename T::cpp_type>(*target_value);
}
// no conversion found
return std::nullopt;
}
[[nodiscard]] CowString lexical_form() const noexcept;
[[nodiscard]] FetchOrSerializeResult fetch_or_serialize_lexical_form(std::string_view &out_lex_form, writer::BufWriterParts writer) const noexcept;
[[nodiscard]] Literal as_lexical_form(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] CowString simplified_lexical_form() const noexcept;
[[nodiscard]] FetchOrSerializeResult fetch_or_serialize_simplified_lexical_form(std::string_view &out_lex_form, writer::BufWriterParts writer) const noexcept;
[[nodiscard]] Literal as_simplified_lexical_form(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] IRI datatype() const noexcept;
[[nodiscard]] std::string_view language_tag() const noexcept;
[[nodiscard]] Literal as_language_tag(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] TriBool language_tag_eq(std::string_view lang_tag) const noexcept;
[[nodiscard]] TriBool language_tag_eq(Literal const &other) const noexcept;
[[nodiscard]] Literal as_language_tag_eq(std::string_view lang_tag, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_language_tag_eq(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
bool serialize(writer::BufWriterParts writer, NodeSerializationOpts opts = NodeSerializationOpts::long_form()) const noexcept;
bool serialize_lexical_form(writer::BufWriterParts writer) const noexcept;
bool serialize_simplified_lexical_form(writer::BufWriterParts writer) const noexcept;
[[nodiscard]] explicit operator std::string() const noexcept;
friend std::ostream &operator<<(std::ostream &os, const Literal &literal);
[[nodiscard]] std::any value() const noexcept;
template<datatypes::LiteralDatatype T>
typename T::cpp_type value() const {
if (!this->datatype_eq<T>()) [[unlikely]] {
throw std::runtime_error{"Literal::value error: incompatible type"};
}
if constexpr (std::is_same_v<T, datatypes::xsd::String>) {
auto const view = this->handle_.literal_backend();
auto const &lit = view.get_lexical();
return lit.lexical_form;
}
if constexpr (std::is_same_v<T, datatypes::rdf::LangString>) {
auto const handle = this->is_inlined()
? this->lang_tagged_get_de_inlined().backend_handle()
: this->backend_handle();
auto const view = handle.literal_backend();
auto const &lit = view.get_lexical();
return datatypes::registry::LangStringRepr{.lexical_form = lit.lexical_form,
.language_tag = lit.language_tag};
}
if constexpr (datatypes::IsInlineable<T>) {
if (this->is_inlined()) {
auto const inlined_value = this->handle_.node_id().literal_id();
return T::from_inlined(inlined_value);
}
}
auto const backend = handle_.literal_backend();
return backend.visit(
[](storage::view::LexicalFormLiteralBackendView const &lexical) noexcept {
return T::from_string(lexical.lexical_form);
},
[](storage::view::ValueLiteralBackendView const &any) noexcept {
RDF4CPP_ASSERT(any.datatype == T::datatype_id);
return std::any_cast<typename T::cpp_type>(any.value);
});
}
bool is_literal() const noexcept = delete;
bool is_variable() const noexcept = delete;
bool is_blank_node() const noexcept = delete;
bool is_iri() const noexcept = delete;
[[nodiscard]] bool is_numeric() const noexcept;
[[nodiscard]] bool is_timepoint() const noexcept;
[[nodiscard]] bool is_duration() const noexcept;
[[nodiscard]] std::partial_ordering compare(Literal const &other) const noexcept;
[[nodiscard]] std::strong_ordering order(Literal const &other) const noexcept;
[[nodiscard]] TriBool eq(Literal const &other) const noexcept;
[[nodiscard]] bool order_eq(Literal const &other) const noexcept;
[[nodiscard]] TriBool ne(Literal const &other) const noexcept;
[[nodiscard]] bool order_ne(Literal const &other) const noexcept;
[[nodiscard]] TriBool lt(Literal const &other) const noexcept;
[[nodiscard]] bool order_lt(Literal const &other) const noexcept;
[[nodiscard]] TriBool le(Literal const &other) const noexcept;
[[nodiscard]] bool order_le(Literal const &other) const noexcept;
[[nodiscard]] TriBool gt(Literal const &other) const noexcept;
[[nodiscard]] bool order_gt(Literal const &other) const noexcept;
[[nodiscard]] TriBool ge(Literal const &other) const noexcept;
[[nodiscard]] bool order_ge(Literal const &other) const noexcept;
[[nodiscard]] Literal as_eq(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_eq(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_ne(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_ne(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_lt(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_lt(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_le(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_le(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_gt(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_gt(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_ge(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_order_ge(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
std::partial_ordering operator<=>(Literal const &other) const noexcept;
bool operator==(Literal const &other) const noexcept;
[[nodiscard]] Literal add(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator+(Literal const &other) const;
Literal &add_assign(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage);
Literal &operator+=(Literal const &other);
[[nodiscard]] Literal sub(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator-(Literal const &other) const;
Literal &sub_assign(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage);
Literal &operator-=(Literal const &other);
[[nodiscard]] Literal mul(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator*(Literal const &other) const;
Literal &mul_assign(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage);
Literal &operator*=(Literal const &other);
[[nodiscard]] Literal div(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator/(Literal const &other) const;
Literal &div_assign(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage);
Literal &operator/=(Literal const &other);
[[nodiscard]] Literal pos(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator+() const;
[[nodiscard]] Literal neg(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
Literal operator-() const;
[[nodiscard]] Literal abs(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal round(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal floor(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal ceil(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<size_t> strlen() const noexcept;
[[nodiscard]] Literal as_strlen(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] TriBool language_tag_matches_range(std::string_view lang_range) const noexcept;
[[nodiscard]] Literal as_language_tag_matches_range(std::string_view lang_range, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_language_tag_matches_range(Literal const &lang_range, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] TriBool regex_matches(regex::Regex const &pattern) const noexcept;
[[nodiscard]] Literal as_regex_matches(regex::Regex const &pattern, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_regex_matches(Literal const &pattern, Literal const &flags = Literal::make_simple(""), storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] regex::Regex make_regex(Literal const &flags = Literal::make_simple("")) const;
[[nodiscard]] Literal regex_replace(regex::RegexReplacer const &replacer, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal regex_replace(Literal const &pattern, Literal const &replacement,
Literal const &flags = Literal::make_simple(""),
storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] TriBool contains(std::string_view needle) const noexcept;
[[nodiscard]] Literal as_contains(std::string_view needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_contains(Literal const &needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal substr_before(std::string_view needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal substr_before(Literal const &needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal substr_after(std::string_view needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal substr_after(Literal const &needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] TriBool str_starts_with(std::string_view needle) const noexcept;
[[nodiscard]] Literal as_str_starts_with(std::string_view needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_str_starts_with(Literal const &needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] TriBool str_ends_with(std::string_view needle) const noexcept;
[[nodiscard]] Literal as_str_ends_with(std::string_view needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal as_str_ends_with(Literal const &needle, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal uppercase(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal lowercase(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal concat(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] static Literal encode_for_uri(std::string_view string, storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] Literal encode_for_uri(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal substr(size_t start,
size_t len = std::string_view::npos,
storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal substr(Literal const &start,
Literal const &len = Literal::make_typed_from_value<datatypes::xsd::Double>(std::numeric_limits<datatypes::xsd::Double::cpp_type>::infinity()),
storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
private:
[[nodiscard]] Literal hash_with(const char *alg, storage::DynNodeStoragePtr node_storage) const;
public:
[[nodiscard]] Literal md5(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal sha1(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal sha256(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal sha384(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal sha512(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] static Literal now(storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] std::optional<Year> year() const noexcept;
[[nodiscard]] Literal as_year(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::chrono::month> month() const noexcept;
[[nodiscard]] Literal as_month(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::chrono::day> day() const noexcept;
[[nodiscard]] Literal as_day(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::chrono::hours> hours() const noexcept;
[[nodiscard]] Literal as_hours(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::chrono::minutes> minutes() const noexcept;
[[nodiscard]] Literal as_minutes(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::chrono::nanoseconds> seconds() const noexcept;
[[nodiscard]] Literal as_seconds(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<Timezone> timezone() const noexcept;
[[nodiscard]] Literal as_timezone(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] std::optional<std::string> tz() const noexcept;
[[nodiscard]] Literal as_tz(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] TriBool ebv() const noexcept;
[[nodiscard]] Literal as_ebv(storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
[[nodiscard]] Literal logical_and(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
Literal operator&&(Literal const &other) const noexcept;
[[nodiscard]] Literal logical_or(Literal const &other, storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
Literal operator||(Literal const &other) const noexcept;
[[nodiscard]] Literal logical_not(storage::DynNodeStoragePtr node_storage = keep_node_storage) const noexcept;
Literal operator!() const noexcept;
friend struct Node;
friend Literal lang_matches(Literal const &lang_tag, Literal const &lang_range, storage::DynNodeStoragePtr node_storage) noexcept;
[[nodiscard]] static Literal math_pi(storage::DynNodeStoragePtr node_storage = storage::default_node_storage);
[[nodiscard]] Literal math_exp(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_exp10(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_log(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_log10(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_pow(Literal exp, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_sqrt(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_sin(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_cos(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_tan(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_asin(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_acos(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_atan(storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
[[nodiscard]] Literal math_atan2(Literal y, storage::DynNodeStoragePtr node_storage = keep_node_storage) const;
};
[[nodiscard]] std::string normalize_unicode(std::string_view utf8);
[[nodiscard]] bool lang_matches(std::string_view lang_tag, std::string_view lang_range) noexcept;
[[nodiscard]] Literal lang_matches(Literal const &lang_tag, Literal const &lang_range, storage::DynNodeStoragePtr node_storage = keep_node_storage) noexcept;
inline namespace shorthands {
Literal operator""_xsd_string(char const *str, size_t len);
Literal operator""_xsd_double(long double d);
Literal operator""_xsd_float(long double d) noexcept;
Literal operator""_xsd_decimal(char const *str, size_t len);
Literal operator""_xsd_integer(unsigned long long int i);
Literal operator""_xsd_byte(unsigned long long int i) noexcept;
Literal operator""_xsd_ubyte(unsigned long long int i) noexcept;
Literal operator""_xsd_short(unsigned long long int i) noexcept;
Literal operator""_xsd_ushort(unsigned long long int i) noexcept;
Literal operator""_xsd_int(unsigned long long int i) noexcept;
Literal operator""_xsd_uint(unsigned long long int i) noexcept;
Literal operator""_xsd_long(unsigned long long int i);
Literal operator""_xsd_ulong(unsigned long long int i);
} // namespace shorthands
struct LiteralOrderByLess {
bool operator()(Literal lhs, Literal rhs) const noexcept {
return lhs.order_lt(rhs);
}
};
struct LiteralOrderByGreater {
bool operator()(Literal lhs, Literal rhs) const noexcept {
return lhs.order_gt(rhs);
}
};
} // namespace rdf4cpp
template<>
struct std::hash<rdf4cpp::Literal> {
inline size_t operator()(rdf4cpp::Literal const &v) const noexcept {
return std::hash<rdf4cpp::Node>()(v);
}
};
template<>
struct std::formatter<rdf4cpp::Literal> : std::formatter<rdf4cpp::Node> {
auto format(rdf4cpp::Literal n, format_context &ctx) const -> decltype(ctx.out());
};
#endif //RDF4CPP_LITERAL_HPP