.. _program_listing_file_zeep_value-serializer.hpp: Program Listing for File value-serializer.hpp ============================================= |exhale_lsh| :ref:`Return to documentation for file ` (``zeep/value-serializer.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright Maarten L. Hekkelman, 2014-2023 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #pragma once #include #include #include #include #include #include #include #include #if __has_include() #include #endif namespace zeep { // -------------------------------------------------------------------- template struct value_serializer; template <> struct value_serializer { static constexpr const char *type_name() { return "xsd:boolean"; } static std::string to_string(bool value) { return value ? "true" : "false"; } static bool from_string(const std::string &value) { return value == "true" or value == "1" or value == "yes"; } }; template <> struct value_serializer { static constexpr const char *type_name() { return "xsd:string"; } static std::string to_string(const std::string &value) { return value; } static std::string from_string(const std::string &value) { return value; } }; template struct char_conv_serializer { using value_type = T; static constexpr const char *derived_type_name() { using value_serializer_type = value_serializer; return value_serializer_type::type_name(); } static std::string to_string(value_type value) { return std::to_string(value); } static value_type from_string(const std::string &value) { value_type result{}; auto r = std::from_chars(value.data(), value.data() + value.length(), result); if (r.ec != std::errc{} or r.ptr != value.data() + value.length()) throw std::system_error(std::make_error_code(r.ec), "Error converting value '" + value + "' to type " + derived_type_name()); return result; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:byte"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:unsignedByte"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:short"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:unsignedShort"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:int"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:unsignedInt"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:long"; } }; template <> struct value_serializer : char_conv_serializer { static constexpr const char *type_name() { return "xsd:unsignedLong"; } }; template <> struct value_serializer { static constexpr const char *type_name() { return "xsd:float"; } // static std::string to_string(float value) { return std::to_string(value); } static std::string to_string(float value) { std::ostringstream s; s << value; return s.str(); } static float from_string(const std::string &value) { return std::stof(value); } }; template <> struct value_serializer { static constexpr const char *type_name() { return "xsd:double"; } // static std::string to_string(double value) { return std::to_string(value); } static std::string to_string(double value) { std::ostringstream s; s << value; return s.str(); } static double from_string(const std::string &value) { return std::stod(value); } }; template struct value_serializer>> { std::string m_type_name; using value_map_type = std::map; using value_map_value_type = typename value_map_type::value_type; value_map_type m_value_map; static void init(const char *name, std::initializer_list values) { instance(name).m_value_map = value_map_type(values); } static void init(std::initializer_list values) { instance().m_value_map = value_map_type(values); } static value_serializer &instance(const char *name = nullptr) { static value_serializer s_instance; if (name and s_instance.m_type_name.empty()) s_instance.m_type_name = name; return s_instance; } value_serializer &operator()(T v, const std::string &name) { m_value_map[v] = name; return *this; } value_serializer &operator()(const std::string &name, T v) { m_value_map[v] = name; return *this; } static const char *type_name() { return instance().m_type_name; } static std::string to_string(T value) { return instance().m_value_map[value]; } static T from_string(const std::string &value) { T result = {}; for (auto &t : instance().m_value_map) if (t.second == value) { result = t.first; break; } return result; } static bool empty() { return instance().m_value_map.empty(); } }; // -------------------------------------------------------------------- // date/time support // We're using Howard Hinands date functions here. If available... #if __has_include() template <> struct value_serializer { using time_type = std::chrono::system_clock::time_point; static constexpr const char *type_name() { return "xsd:dateTime"; } static std::string to_string(const time_type &v) { std::ostringstream ss; ss << date::format("%FT%TZ", v); return ss.str(); } static time_type from_string(const std::string &s) { time_type result; std::regex kRX(R"(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?)"); std::smatch m; if (not std::regex_match(s, m, kRX)) throw std::runtime_error("Invalid date format"); std::istringstream is(s); if (m[1].matched) { if (m[1] == "Z") date::from_stream(is, "%FT%TZ", result); else date::from_stream(is, "%FT%T%0z", result); } else date::from_stream(is, "%FT%T", result); if (is.bad() or is.fail()) throw std::runtime_error("invalid formatted date"); return result; } }; template <> struct value_serializer { static constexpr const char *type_name() { return "xsd:date"; } static std::string to_string(const date::sys_days &v) { std::ostringstream ss; date::to_stream(ss, "%F", v); return ss.str(); } static date::sys_days from_string(const std::string &s) { date::sys_days result; std::istringstream is(s); date::from_stream(is, "%F", result); if (is.bad() or is.fail()) throw std::runtime_error("invalid formatted date"); return result; } }; #endif } // namespace zeep