Refactor StringRef.
This commit is contained in:
parent
a145b4c61c
commit
30ab349173
65
format.h
65
format.h
@ -309,7 +309,32 @@ class Formatter {
|
|||||||
void Write(const std::string &s, unsigned width);
|
void Write(const std::string &s, unsigned width);
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringRef;
|
// A reference to a string. It can be constructed from a C string,
|
||||||
|
// std::string or as a result of a formatting operation. It is most useful
|
||||||
|
// as a parameter type to allow passing different types of strings in a
|
||||||
|
// function, for example:
|
||||||
|
// void SetName(StringRef s) {
|
||||||
|
// std::string name = s;
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
class StringRef {
|
||||||
|
private:
|
||||||
|
const char *data_;
|
||||||
|
mutable std::size_t size_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StringRef(const char *s, std::size_t size = 0) : data_(s), size_(size) {}
|
||||||
|
StringRef(const std::string &s) : data_(s.c_str()), size_(s.size()) {}
|
||||||
|
|
||||||
|
operator std::string() const { return std::string(data_, size()); }
|
||||||
|
|
||||||
|
const char *c_str() const { return data_; }
|
||||||
|
|
||||||
|
std::size_t size() const {
|
||||||
|
if (size_ == 0) size_ = std::strlen(data_);
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -384,6 +409,11 @@ class ArgInserter {
|
|||||||
return Proxy(f);
|
return Proxy(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator StringRef() {
|
||||||
|
const Formatter *f = Format();
|
||||||
|
return StringRef(f->c_str(), f->size());
|
||||||
|
}
|
||||||
|
|
||||||
// Performs formatting and returns a std::string with the output.
|
// Performs formatting and returns a std::string with the output.
|
||||||
friend std::string str(Proxy p) {
|
friend std::string str(Proxy p) {
|
||||||
return p.Format()->str();
|
return p.Format()->str();
|
||||||
@ -402,39 +432,6 @@ const char *c_str(ArgInserter::Proxy p);
|
|||||||
using format::internal::str;
|
using format::internal::str;
|
||||||
using format::internal::c_str;
|
using format::internal::c_str;
|
||||||
|
|
||||||
// A reference to a string. It can be constructed from a C string,
|
|
||||||
// std::string or as a result of a formatting operation. It is most useful
|
|
||||||
// as a parameter type to allow passing different types of strings in a
|
|
||||||
// function, for example:
|
|
||||||
// void SetName(StringRef s) {
|
|
||||||
// std::string name = s;
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
class StringRef {
|
|
||||||
private:
|
|
||||||
const char *data_;
|
|
||||||
mutable std::size_t size_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StringRef(const char *s) : data_(s), size_(0) {}
|
|
||||||
StringRef(const std::string &s) : data_(s.c_str()), size_(s.size()) {}
|
|
||||||
|
|
||||||
StringRef(internal::ArgInserter::Proxy p) {
|
|
||||||
Formatter *f = p.Format();
|
|
||||||
data_ = f->c_str();
|
|
||||||
size_ = f->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::string() const { return std::string(data_, size_); }
|
|
||||||
|
|
||||||
const char *c_str() const { return data_; }
|
|
||||||
|
|
||||||
std::size_t size() const {
|
|
||||||
if (size_ == 0) size_ = std::strlen(data_);
|
|
||||||
return size_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ArgFormatter provides access to the format buffer within custom
|
// ArgFormatter provides access to the format buffer within custom
|
||||||
// Format functions. It is not desirable to pass Formatter to these
|
// Format functions. It is not desirable to pass Formatter to these
|
||||||
// functions because Formatter::operator() is not reentrant and
|
// functions because Formatter::operator() is not reentrant and
|
||||||
|
@ -735,15 +735,17 @@ TEST(FormatterTest, StrNamespace) {
|
|||||||
fmt::c_str(Format(""));
|
fmt::c_str(Format(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, StringRef) {
|
TEST(StringRefTest, Ctor) {
|
||||||
EXPECT_STREQ("abc", StringRef("abc").c_str());
|
EXPECT_STREQ("abc", StringRef("abc").c_str());
|
||||||
EXPECT_EQ(3u, StringRef("abc").size());
|
EXPECT_EQ(3u, StringRef("abc").size());
|
||||||
|
|
||||||
EXPECT_STREQ("defg", StringRef(std::string("defg")).c_str());
|
EXPECT_STREQ("defg", StringRef(std::string("defg")).c_str());
|
||||||
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
|
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_STREQ("hijkl", StringRef(Format("hi{0}kl") << 'j').c_str());
|
TEST(StringRefTest, ConvertToString) {
|
||||||
EXPECT_EQ(5u, StringRef(Format("hi{0}kl") << 'j').size());
|
std::string s = StringRef("abc");
|
||||||
|
EXPECT_EQ("abc", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CountCalls {
|
struct CountCalls {
|
||||||
@ -791,6 +793,11 @@ TEST(TempFormatterTest, ArgLifetime) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST(TempFormatterTest, ConvertToStringRef) {
|
||||||
|
EXPECT_STREQ("abc", StringRef(Format("a{0}c") << 'b').c_str());
|
||||||
|
EXPECT_EQ(3u, StringRef(Format("a{0}c") << 'b').size());
|
||||||
|
}
|
||||||
|
|
||||||
struct PrintError {
|
struct PrintError {
|
||||||
void operator()(const fmt::Formatter &f) const {
|
void operator()(const fmt::Formatter &f) const {
|
||||||
std::cerr << "Error: " << f.str() << std::endl;
|
std::cerr << "Error: " << f.str() << std::endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user