ImmutableString: Ensure that c_str() returns non-nullptr if it is default constructed
This commit is contained in:
parent
ba543e3895
commit
5131b95c2f
|
@ -215,10 +215,7 @@ inline std::unique_ptr<char[]> strcopy(const std::unique_ptr<char[]> &val,
|
||||||
// std::string. It has c_str() and size() functions to mimic
|
// std::string. It has c_str() and size() functions to mimic
|
||||||
// std::string. It manages buffer by itself. Just like std::string,
|
// std::string. It manages buffer by itself. Just like std::string,
|
||||||
// c_str() returns NULL-terminated string, but NULL character may
|
// c_str() returns NULL-terminated string, but NULL character may
|
||||||
// appear before the final terminal NULL. The crucial difference
|
// appear before the final terminal NULL.
|
||||||
// between this and std::string is that when ImmutableString is
|
|
||||||
// default constructed, c_str() returns nullptr, whereas std::string
|
|
||||||
// will return non nullptr. Both size() returns 0.
|
|
||||||
class ImmutableString {
|
class ImmutableString {
|
||||||
public:
|
public:
|
||||||
using traits_type = std::char_traits<char>;
|
using traits_type = std::char_traits<char>;
|
||||||
|
@ -231,24 +228,30 @@ public:
|
||||||
using const_pointer = const value_type *;
|
using const_pointer = const value_type *;
|
||||||
using const_iterator = const_pointer;
|
using const_iterator = const_pointer;
|
||||||
|
|
||||||
ImmutableString() : len(0) {}
|
ImmutableString() : len(0), base("") {}
|
||||||
ImmutableString(const char *s, size_t slen)
|
ImmutableString(const char *s, size_t slen)
|
||||||
: len(slen), base(strcopy(s, len)) {}
|
: len(slen), holder(strcopy(s, len)), base(holder.get()) {}
|
||||||
ImmutableString(const char *s) : len(strlen(s)), base(strcopy(s, len)) {}
|
ImmutableString(const char *s)
|
||||||
|
: len(strlen(s)), holder(strcopy(s, len)), base(holder.get()) {}
|
||||||
ImmutableString(std::unique_ptr<char[]> s)
|
ImmutableString(std::unique_ptr<char[]> s)
|
||||||
: len(strlen(s.get())), base(std::move(s)) {}
|
: len(strlen(s.get())), holder(std::move(s)), base(holder.get()) {}
|
||||||
ImmutableString(std::unique_ptr<char[]> s, size_t slen)
|
ImmutableString(std::unique_ptr<char[]> s, size_t slen)
|
||||||
: len(slen), base(std::move(s)) {}
|
: len(slen), holder(std::move(s)), base(holder.get()) {}
|
||||||
ImmutableString(const std::string &s) : len(s.size()), base(strcopy(s)) {}
|
ImmutableString(const std::string &s)
|
||||||
|
: len(s.size()), holder(strcopy(s)), base(holder.get()) {}
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
ImmutableString(InputIt first, InputIt last)
|
ImmutableString(InputIt first, InputIt last)
|
||||||
: len(std::distance(first, last)), base(strcopy(first, last)) {}
|
: len(std::distance(first, last)), holder(strcopy(first, last)),
|
||||||
|
base(holder.get()) {}
|
||||||
ImmutableString(const ImmutableString &other)
|
ImmutableString(const ImmutableString &other)
|
||||||
: len(other.len), base(strcopy(other.base, other.len)) {}
|
: len(other.len), holder(strcopy(other.holder, other.len)),
|
||||||
|
base(holder.get()) {}
|
||||||
ImmutableString(ImmutableString &&other) noexcept
|
ImmutableString(ImmutableString &&other) noexcept
|
||||||
: len(other.len),
|
: len(other.len),
|
||||||
base(std::move(other.base)) {
|
holder(std::move(other.holder)),
|
||||||
|
base(holder.get()) {
|
||||||
other.len = 0;
|
other.len = 0;
|
||||||
|
other.base = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableString &operator=(const ImmutableString &other) {
|
ImmutableString &operator=(const ImmutableString &other) {
|
||||||
|
@ -256,7 +259,8 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
len = other.len;
|
len = other.len;
|
||||||
base = strcopy(other.base, other.len);
|
holder = strcopy(other.holder, other.len);
|
||||||
|
base = holder.get();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ImmutableString &operator=(ImmutableString &&other) noexcept {
|
ImmutableString &operator=(ImmutableString &&other) noexcept {
|
||||||
|
@ -264,8 +268,10 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
len = other.len;
|
len = other.len;
|
||||||
base = std::move(other.base);
|
holder = std::move(other.holder);
|
||||||
|
base = holder.get();
|
||||||
other.len = 0;
|
other.len = 0;
|
||||||
|
other.base = "";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,12 +279,13 @@ public:
|
||||||
return ImmutableString(s, N - 1);
|
return ImmutableString(s, N - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *c_str() const { return base.get(); }
|
const char *c_str() const { return base; }
|
||||||
size_type size() const { return len; }
|
size_type size() const { return len; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type len;
|
size_type len;
|
||||||
std::unique_ptr<char[]> base;
|
std::unique_ptr<char[]> holder;
|
||||||
|
const char *base;
|
||||||
};
|
};
|
||||||
|
|
||||||
// StringRef is a reference to a string owned by something else. So
|
// StringRef is a reference to a string owned by something else. So
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace nghttp2 {
|
||||||
void test_template_immutable_string(void) {
|
void test_template_immutable_string(void) {
|
||||||
ImmutableString null;
|
ImmutableString null;
|
||||||
|
|
||||||
CU_ASSERT(nullptr == null.c_str());
|
CU_ASSERT("" == null);
|
||||||
CU_ASSERT(0 == null.size());
|
CU_ASSERT(0 == null.size());
|
||||||
|
|
||||||
ImmutableString from_cstr("alpha");
|
ImmutableString from_cstr("alpha");
|
||||||
|
@ -71,7 +71,7 @@ void test_template_immutable_string(void) {
|
||||||
|
|
||||||
CU_ASSERT("charlie" == move);
|
CU_ASSERT("charlie" == move);
|
||||||
CU_ASSERT(7 == move.size());
|
CU_ASSERT(7 == move.size());
|
||||||
CU_ASSERT(nullptr == copy.c_str());
|
CU_ASSERT("" == copy);
|
||||||
CU_ASSERT(0 == copy.size());
|
CU_ASSERT(0 == copy.size());
|
||||||
|
|
||||||
// move assignment
|
// move assignment
|
||||||
|
@ -79,7 +79,7 @@ void test_template_immutable_string(void) {
|
||||||
|
|
||||||
CU_ASSERT("alpha" == move);
|
CU_ASSERT("alpha" == move);
|
||||||
CU_ASSERT(5 == move.size());
|
CU_ASSERT(5 == move.size());
|
||||||
CU_ASSERT(nullptr == from_cstr.c_str());
|
CU_ASSERT("" == from_cstr);
|
||||||
CU_ASSERT(0 == from_cstr.size());
|
CU_ASSERT(0 == from_cstr.size());
|
||||||
|
|
||||||
// from string literal
|
// from string literal
|
||||||
|
|
Loading…
Reference in New Issue