]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/seastar/include/seastar/core/sstring.hh
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / seastar / include / seastar / core / sstring.hh
index f57f72bc3b76bdbf48a41ecbc97b782c76af8d4c..781f30f57086b3fad074fd8a78e036a070f6e8a3 100644 (file)
@@ -42,10 +42,17 @@ namespace seastar {
 template <typename char_type, typename Size, Size max_size, bool NulTerminate = true>
 class basic_sstring;
 
+#ifdef SEASTAR_SSTRING
 using sstring = basic_sstring<char, uint32_t, 15>;
-
-template <typename string_type = sstring, typename T>
-inline string_type to_sstring(T value);
+#else
+using sstring = std::string;
+#endif
+
+namespace internal {
+[[noreturn]] void throw_bad_alloc();
+[[noreturn]] void throw_sstring_overflow();
+[[noreturn]] void throw_sstring_out_of_range();
+}
 
 template <typename char_type, typename Size, Size max_size, bool NulTerminate>
 class basic_sstring {
@@ -73,80 +80,13 @@ class basic_sstring {
     bool is_external() const noexcept {
         return !is_internal();
     }
-    const char_type* str() const {
+    const char_type* str() const noexcept {
         return is_internal() ? u.internal.str : u.external.str;
     }
-    char_type* str() {
+    char_type* str() noexcept {
         return is_internal() ? u.internal.str : u.external.str;
     }
 
-    template <typename string_type, typename T>
-    static inline string_type to_sstring_sprintf(T value, const char* fmt) {
-        char tmp[sizeof(value) * 3 + 2];
-        auto len = std::sprintf(tmp, fmt, value);
-        using ch_type = typename string_type::value_type;
-        return string_type(reinterpret_cast<ch_type*>(tmp), len);
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(int value) {
-        return to_sstring_sprintf<string_type>(value, "%d");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(unsigned value) {
-        return to_sstring_sprintf<string_type>(value, "%u");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(long value) {
-        return to_sstring_sprintf<string_type>(value, "%ld");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(unsigned long value) {
-        return to_sstring_sprintf<string_type>(value, "%lu");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(long long value) {
-        return to_sstring_sprintf<string_type>(value, "%lld");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(unsigned long long value) {
-        return to_sstring_sprintf<string_type>(value, "%llu");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(float value) {
-        return to_sstring_sprintf<string_type>(value, "%g");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(double value) {
-        return to_sstring_sprintf<string_type>(value, "%g");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(long double value) {
-        return to_sstring_sprintf<string_type>(value, "%Lg");
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(const char* value) {
-        return string_type(value);
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(sstring value) {
-        return value;
-    }
-
-    template <typename string_type>
-    static inline string_type to_sstring(const temporary_buffer<char>& buf) {
-        return string_type(buf.get(), buf.size());
-    }
 public:
     using value_type = char_type;
     using traits_type = std::char_traits<char_type>;
@@ -178,7 +118,7 @@ public:
             u.internal.size = -1;
             u.external.str = reinterpret_cast<char_type*>(std::malloc(x.u.external.size + padding()));
             if (!u.external.str) {
-                throw std::bad_alloc();
+                internal::throw_bad_alloc();
             }
             std::copy(x.u.external.str, x.u.external.str + x.u.external.size + padding(), u.external.str);
             u.external.size = x.u.external.size;
@@ -197,7 +137,7 @@ public:
     }
     basic_sstring(initialized_later, size_t size) {
         if (size_type(size) != size) {
-            throw std::overflow_error("sstring overflow");
+            internal::throw_sstring_overflow();
         }
         if (size + padding() <= sizeof(u.internal.str)) {
             if (NulTerminate) {
@@ -208,7 +148,7 @@ public:
             u.internal.size = -1;
             u.external.str = reinterpret_cast<char_type*>(std::malloc(size + padding()));
             if (!u.external.str) {
-                throw std::bad_alloc();
+                internal::throw_bad_alloc();
             }
             u.external.size = size;
             if (NulTerminate) {
@@ -218,7 +158,7 @@ public:
     }
     basic_sstring(const char_type* x, size_t size) {
         if (size_type(size) != size) {
-            throw std::overflow_error("sstring overflow");
+            internal::throw_sstring_overflow();
         }
         if (size + padding() <= sizeof(u.internal.str)) {
             std::copy(x, x + size, u.internal.str);
@@ -230,7 +170,7 @@ public:
             u.internal.size = -1;
             u.external.str = reinterpret_cast<char_type*>(std::malloc(size + padding()));
             if (!u.external.str) {
-                throw std::bad_alloc();
+                internal::throw_bad_alloc();
             }
             u.external.size = size;
             std::copy(x, x + size, u.external.str);
@@ -255,7 +195,7 @@ public:
             : basic_sstring(initialized_later(), std::distance(first, last)) {
         std::copy(first, last, begin());
     }
-    explicit basic_sstring(compat::basic_string_view<char_type, traits_type> v)
+    explicit basic_sstring(std::basic_string_view<char_type, traits_type> v)
             : basic_sstring(v.data(), v.size()) {
     }
     ~basic_sstring() noexcept {
@@ -270,8 +210,8 @@ public:
     }
     basic_sstring& operator=(basic_sstring&& x) noexcept {
         if (this != &x) {
-            swap(x);
-            x.reset();
+            this->~basic_sstring();
+            new (this) basic_sstring(std::move(x));
         }
         return *this;
     }
@@ -389,7 +329,7 @@ public:
     basic_sstring& replace(size_type pos, size_type n1, const char_type* s,
              size_type n2) {
         if (pos > size()) {
-            throw std::out_of_range("sstring::replace out of range");
+            internal::throw_sstring_out_of_range();
         }
 
         if (n1 > size() - pos) {
@@ -419,7 +359,7 @@ public:
     basic_sstring& replace (const_iterator i1, const_iterator i2,
             InputIterator first, InputIterator last) {
         if (i1 < begin() || i1 > end() || i2 < begin()) {
-            throw std::out_of_range("sstring::replace out of range");
+            internal::throw_sstring_out_of_range();
         }
         if (i2 > end()) {
             i2 = end();
@@ -476,7 +416,7 @@ public:
 
     basic_sstring substr(size_t from, size_t len = npos)  const {
         if (from > size()) {
-            throw std::out_of_range("sstring::substr out of range");
+            internal::throw_sstring_out_of_range();
         }
         if (len > size() - from) {
             len = size() - from;
@@ -489,14 +429,14 @@ public:
 
     const char_type& at(size_t pos) const {
         if (pos >= size()) {
-            throw std::out_of_range("sstring::at out of range");
+            internal::throw_sstring_out_of_range();
         }
         return *(str() + pos);
     }
 
     char_type& at(size_t pos) {
         if (pos >= size()) {
-            throw std::out_of_range("sstring::at out of range");
+            internal::throw_sstring_out_of_range();
         }
         return *(str() + pos);
     }
@@ -504,6 +444,9 @@ public:
     bool empty() const noexcept {
         return u.internal.size == 0;
     }
+
+    // Deprecated March 2020.
+    [[deprecated("Use = {}")]]
     void reset() noexcept {
         if (is_external()) {
             std::free(u.external.str);
@@ -530,7 +473,7 @@ public:
             return buf;
         }
     }
-    int compare(const basic_sstring& x) const noexcept {
+    int compare(std::basic_string_view<char_type, traits_type> x) const noexcept {
         auto n = traits_type::compare(begin(), x.begin(), std::min(size(), x.size()));
         if (n != 0) {
             return n;
@@ -544,9 +487,9 @@ public:
         }
     }
 
-    int compare(size_t pos, size_t sz, const basic_sstring& x) const {
+    int compare(size_t pos, size_t sz, std::basic_string_view<char_type, traits_type> x) const {
         if (pos > size()) {
-            throw std::out_of_range("pos larger than string size");
+            internal::throw_sstring_out_of_range();
         }
 
         sz = std::min(size() - pos, sz);
@@ -569,28 +512,28 @@ public:
         x.u = u;
         u = tmp;
     }
-    char_type* data() {
+    char_type* data() noexcept {
         return str();
     }
-    const char_type* data() const {
+    const char_type* data() const noexcept {
         return str();
     }
-    const char_type* c_str() const {
+    const char_type* c_str() const noexcept {
         return str();
     }
-    const char_type* begin() const { return str(); }
-    const char_type* end() const { return str() + size(); }
-    const char_type* cbegin() const { return str(); }
-    const char_type* cend() const { return str() + size(); }
-    char_type* begin() { return str(); }
-    char_type* end() { return str() + size(); }
-    bool operator==(const basic_sstring& x) const {
+    const char_type* begin() const noexcept { return str(); }
+    const char_type* end() const noexcept { return str() + size(); }
+    const char_type* cbegin() const noexcept { return str(); }
+    const char_type* cend() const noexcept { return str() + size(); }
+    char_type* begin() noexcept { return str(); }
+    char_type* end() noexcept { return str() + size(); }
+    bool operator==(const basic_sstring& x) const noexcept {
         return size() == x.size() && std::equal(begin(), end(), x.begin());
     }
-    bool operator!=(const basic_sstring& x) const {
+    bool operator!=(const basic_sstring& x) const noexcept {
         return !operator==(x);
     }
-    bool operator<(const basic_sstring& x) const {
+    bool operator<(const basic_sstring& x) const noexcept {
         return compare(x) < 0;
     }
     basic_sstring operator+(const basic_sstring& x) const {
@@ -602,23 +545,43 @@ public:
     basic_sstring& operator+=(const basic_sstring& x) {
         return *this = *this + x;
     }
-    char_type& operator[](size_type pos) {
+    char_type& operator[](size_type pos) noexcept {
         return str()[pos];
     }
-    const char_type& operator[](size_type pos) const {
+    const char_type& operator[](size_type pos) const noexcept {
         return str()[pos];
     }
 
-    operator compat::basic_string_view<char_type>() const {
-        return compat::basic_string_view<char_type>(str(), size());
+    operator std::basic_string_view<char_type>() const noexcept {
+        // we assume that std::basic_string_view<char_type>(str(), size())
+        // won't throw, although it is not specified as noexcept in
+        // https://en.cppreference.com/w/cpp/string/basic_string_view/basic_string_view
+        // at this time (C++20).
+        //
+        // This is similar to std::string operator std::basic_string_view:
+        // https://en.cppreference.com/w/cpp/string/basic_string/operator_basic_string_view
+        // that is specified as noexcept too.
+        static_assert(noexcept(std::basic_string_view<char_type>(str(), size())));
+        return std::basic_string_view<char_type>(str(), size());
     }
-
-    template <typename string_type, typename T>
-    friend inline string_type to_sstring(T value);
 };
 template <typename char_type, typename Size, Size max_size, bool NulTerminate>
 constexpr Size basic_sstring<char_type, Size, max_size, NulTerminate>::npos;
 
+template <typename string_type = sstring>
+string_type uninitialized_string(size_t size) {
+    string_type ret;
+    // FIXME: use __resize_default_init if available
+    ret.resize(size);
+    return ret;
+}
+
+template <typename char_type, typename Size, Size max_size, bool NulTerminate>
+basic_sstring<char_type, Size, max_size, NulTerminate> uninitialized_string(size_t size) {
+    using sstring_type = basic_sstring<char_type, Size, max_size, NulTerminate>;
+    return sstring_type(sstring_type::initialized_later(), size);
+}
+
 template <typename char_type, typename size_type, size_type Max, size_type N, bool NulTerminate>
 inline
 basic_sstring<char_type, size_type, Max, NulTerminate>
@@ -631,34 +594,15 @@ operator+(const char(&s)[N], const basic_sstring<char_type, size_type, Max, NulT
     return ret;
 }
 
-template <size_t N>
-static inline
-size_t str_len(const char(&s)[N]) { return N - 1; }
-
-template <size_t N>
 static inline
-const char* str_begin(const char(&s)[N]) { return s; }
-
-template <size_t N>
-static inline
-const char* str_end(const char(&s)[N]) { return str_begin(s) + str_len(s); }
-
-template <typename char_type, typename size_type, size_type max_size, bool NulTerminate>
-static inline
-const char_type* str_begin(const basic_sstring<char_type, size_type, max_size, NulTerminate>& s) { return s.begin(); }
-
-template <typename char_type, typename size_type, size_type max_size, bool NulTerminate>
-static inline
-const char_type* str_end(const basic_sstring<char_type, size_type, max_size, NulTerminate>& s) { return s.end(); }
-
-template <typename char_type, typename size_type, size_type max_size, bool NulTerminate>
-static inline
-size_type str_len(const basic_sstring<char_type, size_type, max_size, NulTerminate>& s) { return s.size(); }
+size_t str_len() {
+    return 0;
+}
 
-template <typename First, typename Second, typename... Tail>
+template <typename First, typename... Tail>
 static inline
-size_t str_len(const First& first, const Second& second, const Tail&... tail) {
-    return str_len(first) + str_len(second, tail...);
+size_t str_len(const First& first, const Tail&... tail) {
+    return std::string_view(first).size() + str_len(tail...);
 }
 
 template <typename char_type, typename size_type, size_type max_size>
@@ -695,7 +639,7 @@ namespace std {
 template <typename char_type, typename size_type, size_type max_size, bool NulTerminate>
 struct hash<seastar::basic_sstring<char_type, size_type, max_size, NulTerminate>> {
     size_t operator()(const seastar::basic_sstring<char_type, size_type, max_size, NulTerminate>& s) const {
-        return std::hash<seastar::compat::basic_string_view<char_type>>()(s);
+        return std::hash<std::basic_string_view<char_type>>()(s);
     }
 };
 
@@ -711,22 +655,92 @@ char* copy_str_to(char* dst) {
 template <typename Head, typename... Tail>
 static inline
 char* copy_str_to(char* dst, const Head& head, const Tail&... tail) {
-    return copy_str_to(std::copy(str_begin(head), str_end(head), dst), tail...);
+    std::string_view v(head);
+    return copy_str_to(std::copy(v.begin(), v.end(), dst), tail...);
 }
 
 template <typename String = sstring, typename... Args>
 static String make_sstring(Args&&... args)
 {
-    String ret(sstring::initialized_later(), str_len(args...));
-    copy_str_to(ret.begin(), args...);
+    String ret = uninitialized_string<String>(str_len(args...));
+    copy_str_to(ret.data(), args...);
     return ret;
 }
 
+namespace internal {
 template <typename string_type, typename T>
-inline string_type to_sstring(T value) {
-    return sstring::to_sstring<string_type>(value);
+string_type to_sstring_sprintf(T value, const char* fmt) {
+    char tmp[sizeof(value) * 3 + 2];
+    auto len = std::sprintf(tmp, fmt, value);
+    using ch_type = typename string_type::value_type;
+    return string_type(reinterpret_cast<ch_type*>(tmp), len);
+}
+
+template <typename string_type>
+string_type to_sstring(int value) {
+    return to_sstring_sprintf<string_type>(value, "%d");
+}
+
+template <typename string_type>
+string_type to_sstring(unsigned value) {
+    return to_sstring_sprintf<string_type>(value, "%u");
+}
+
+template <typename string_type>
+string_type to_sstring(long value) {
+    return to_sstring_sprintf<string_type>(value, "%ld");
+}
+
+template <typename string_type>
+string_type to_sstring(unsigned long value) {
+    return to_sstring_sprintf<string_type>(value, "%lu");
 }
 
+template <typename string_type>
+string_type to_sstring(long long value) {
+    return to_sstring_sprintf<string_type>(value, "%lld");
+}
+
+template <typename string_type>
+string_type to_sstring(unsigned long long value) {
+    return to_sstring_sprintf<string_type>(value, "%llu");
+}
+
+template <typename string_type>
+string_type to_sstring(float value) {
+    return to_sstring_sprintf<string_type>(value, "%g");
+}
+
+template <typename string_type>
+string_type to_sstring(double value) {
+    return to_sstring_sprintf<string_type>(value, "%g");
+}
+
+template <typename string_type>
+string_type to_sstring(long double value) {
+    return to_sstring_sprintf<string_type>(value, "%Lg");
+}
+
+template <typename string_type>
+string_type to_sstring(const char* value) {
+    return string_type(value);
+}
+
+template <typename string_type>
+string_type to_sstring(sstring value) {
+    return value;
+}
+
+template <typename string_type>
+string_type to_sstring(const temporary_buffer<char>& buf) {
+    return string_type(buf.get(), buf.size());
+}
+}
+
+template <typename string_type = sstring, typename T>
+string_type to_sstring(T value) {
+    return internal::to_sstring<string_type>(value);
+}
 }
 
 namespace std {