Implement StringRef.

This commit is contained in:
Victor Zverovich 2012-12-18 15:39:42 -08:00
parent 2ba1573ac3
commit 2baf6d3030
2 changed files with 59 additions and 10 deletions

View File

@ -29,7 +29,8 @@
#define FORMAT_H_ #define FORMAT_H_
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>>
#include <cstring>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -308,6 +309,8 @@ class Formatter {
void Write(const std::string &s, unsigned width); void Write(const std::string &s, unsigned width);
}; };
class StringRef;
namespace internal { namespace internal {
// This is a transient object that normally exists only as a temporary // This is a transient object that normally exists only as a temporary
@ -319,6 +322,7 @@ class ArgInserter {
mutable Formatter *formatter_; mutable Formatter *formatter_;
friend class format::Formatter; friend class format::Formatter;
friend class format::StringRef;
// Do not implement. // Do not implement.
void operator=(const ArgInserter& other); void operator=(const ArgInserter& other);
@ -354,12 +358,12 @@ class ArgInserter {
struct Proxy { struct Proxy {
Formatter *formatter; Formatter *formatter;
explicit Proxy(Formatter *f) : formatter(f) {} explicit Proxy(Formatter *f) : formatter(f) {}
};
static Formatter *Format(Proxy p) { Formatter *Format() {
p.formatter->CompleteFormatting(); formatter->CompleteFormatting();
return p.formatter; return formatter;
} }
};
public: public:
~ArgInserter() { ~ArgInserter() {
@ -382,21 +386,54 @@ class ArgInserter {
// 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 Format(p)->str(); return p.Format()->str();
} }
// Performs formatting and returns a C string with the output. // Performs formatting and returns a C string with the output.
friend const char *c_str(Proxy p) { friend const char *c_str(Proxy p) {
return Format(p)->c_str(); return p.Format()->c_str();
} }
}; };
const char *c_str(ArgInserter::Proxy p);
std::string str(ArgInserter::Proxy p); std::string str(ArgInserter::Proxy p);
const char *c_str(ArgInserter::Proxy p);
} }
using format::internal::c_str;
using format::internal::str; using format::internal::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

View File

@ -44,6 +44,7 @@ using fmt::internal::Array;
using fmt::Formatter; using fmt::Formatter;
using fmt::Format; using fmt::Format;
using fmt::FormatError; using fmt::FormatError;
using fmt::StringRef;
#define FORMAT_TEST_THROW_(statement, expected_exception, message, fail) \ #define FORMAT_TEST_THROW_(statement, expected_exception, message, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
@ -734,6 +735,17 @@ TEST(FormatterTest, StrNamespace) {
fmt::c_str(Format("")); fmt::c_str(Format(""));
} }
TEST(FormatterTest, StringRef) {
EXPECT_STREQ("abc", StringRef("abc").c_str());
EXPECT_EQ(3u, StringRef("abc").size());
EXPECT_STREQ("defg", StringRef(std::string("defg")).c_str());
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
EXPECT_STREQ("hijkl", StringRef(Format("hi{0}kl") << 'j').c_str());
EXPECT_EQ(5u, StringRef(Format("hi{0}kl") << 'j').size());
}
struct CountCalls { struct CountCalls {
int &num_calls; int &num_calls;