File indexing completed on 2025-01-31 02:19:34
0001 #ifndef FWCore_Utilities_interface_compactStringSerializer_h
0002 #define FWCore_Utilities_interface_compactStringSerializer_h
0003
0004 #include <cassert>
0005 #include <iterator>
0006 #include <numeric>
0007 #include <ranges>
0008 #include <string>
0009 #include <string_view>
0010
0011 namespace edm::compactString {
0012 namespace detail {
0013 constexpr std::string_view kDelimiters = "\x1d\x1e";
0014 constexpr char kContainerDelimiter = kDelimiters[0];
0015 constexpr char kElementDelimiter = kDelimiters[1];
0016
0017 void throwIfContainsDelimiters(std::string const& str);
0018 }
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 inline std::string serialize(std::string arg) noexcept(false) {
0032 detail::throwIfContainsDelimiters(arg);
0033 arg += detail::kContainerDelimiter;
0034 return arg;
0035 }
0036
0037 template <typename R>
0038 requires std::ranges::input_range<R> and std::is_same_v<std::ranges::range_value_t<R>, std::string>
0039 std::string serialize(R const& arg) noexcept(false) {
0040 std::string ret;
0041
0042 if (not std::ranges::empty(arg)) {
0043 for (std::string const& elem : arg) {
0044 ret.reserve(ret.size() + elem.size() + 1);
0045 detail::throwIfContainsDelimiters(elem);
0046 ret += elem;
0047 ret += detail::kElementDelimiter;
0048 }
0049 }
0050
0051 ret += detail::kContainerDelimiter;
0052 return ret;
0053 }
0054
0055 template <typename T, typename... Args>
0056 requires(sizeof...(Args) >= 1)
0057 std::string serialize(T&& arg0, Args&&... args) noexcept(false) {
0058 return serialize(std::forward<T>(arg0)) + serialize(std::forward<Args>(args)...);
0059 }
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 inline std::string_view::size_type deserialize(std::string_view input, std::string& arg) {
0085 auto const pos = input.find_first_of(detail::kDelimiters);
0086 if (pos == std::string_view::npos or input[pos] != detail::kContainerDelimiter) {
0087 return 0;
0088 }
0089 arg = input.substr(0, pos);
0090 return pos + 1;
0091 }
0092
0093 template <std::output_iterator<std::string> I>
0094 inline std::string_view::size_type deserialize(std::string_view input, I arg) {
0095 auto pos = input.find_first_of(detail::kDelimiters);
0096
0097 if (pos == std::string_view::npos) {
0098 return 0;
0099 }
0100
0101 if (input[pos] == detail::kContainerDelimiter) {
0102
0103 if (pos != 0) {
0104 return 0;
0105 }
0106
0107 return pos + 1;
0108 }
0109
0110 std::string_view::size_type prev = 0;
0111 while (pos != std::string_view::npos and input[pos] == detail::kElementDelimiter) {
0112 *arg = std::string(input.substr(prev, pos - prev));
0113 ++arg;
0114 prev = pos + 1;
0115 pos = input.find_first_of(detail::kDelimiters, prev);
0116 }
0117
0118
0119
0120 if (pos == std::string_view::npos) {
0121 return 0;
0122 }
0123 assert(input[pos] == detail::kContainerDelimiter);
0124
0125 return pos + 1;
0126 }
0127
0128 template <typename T, typename... Args>
0129 requires(sizeof...(Args) >= 1)
0130 std::string_view::size_type deserialize(std::string_view input, T&& arg0, Args&&... args) {
0131 auto pos = deserialize(input, std::forward<T>(arg0));
0132 if (pos != 0) {
0133 auto const ret = deserialize(input.substr(pos), std::forward<Args>(args)...);
0134 pos = (ret == 0) ? 0 : pos + ret;
0135 }
0136 return pos;
0137 }
0138 }
0139
0140 #endif