Add BasicCStringRef to represent a null-termated string (#100)

and use it instead of BasicStringRef in cases that assume that the
string is null-terminated such as POSIX function and format string
parser.
This commit is contained in:
vitaut 2015-06-26 07:43:54 -07:00
parent 88c7c20102
commit 438bd9b0e6
7 changed files with 141 additions and 83 deletions

View File

@ -527,7 +527,7 @@ class PrintfArgFormatter :
} // namespace fmt } // namespace fmt
FMT_FUNC void fmt::SystemError::init( FMT_FUNC void fmt::SystemError::init(
int err_code, StringRef format_str, ArgList args) { int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code; error_code_ = err_code;
MemoryWriter w; MemoryWriter w;
internal::format_system_error(w, err_code, format(format_str, args)); internal::format_system_error(w, err_code, format(format_str, args));
@ -927,7 +927,7 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
template <typename Char> template <typename Char>
void fmt::internal::PrintfFormatter<Char>::format( void fmt::internal::PrintfFormatter<Char>::format(
BasicWriter<Char> &writer, BasicStringRef<Char> format_str, BasicWriter<Char> &writer, BasicCStringRef<Char> format_str,
const ArgList &args) { const ArgList &args) {
const Char *start = format_str.c_str(); const Char *start = format_str.c_str();
set_args(args); set_args(args);
@ -1198,7 +1198,7 @@ const Char *fmt::BasicFormatter<Char>::format(
template <typename Char> template <typename Char>
void fmt::BasicFormatter<Char>::format( void fmt::BasicFormatter<Char>::format(
BasicStringRef<Char> format_str, const ArgList &args) { BasicCStringRef<Char> format_str, const ArgList &args) {
const Char *s = start_ = format_str.c_str(); const Char *s = start_ = format_str.c_str();
set_args(args); set_args(args);
while (*s) { while (*s) {
@ -1230,23 +1230,23 @@ FMT_FUNC void fmt::report_windows_error(
} }
#endif #endif
FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) { FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
MemoryWriter w; MemoryWriter w;
w.write(format_str, args); w.write(format_str, args);
std::fwrite(w.data(), 1, w.size(), f); std::fwrite(w.data(), 1, w.size(), f);
} }
FMT_FUNC void fmt::print(StringRef format_str, ArgList args) { FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
print(stdout, format_str, args); print(stdout, format_str, args);
} }
FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
MemoryWriter w; MemoryWriter w;
w.write(format_str, args); w.write(format_str, args);
os.write(w.data(), w.size()); os.write(w.data(), w.size());
} }
FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
char escape[] = "\x1b[30m"; char escape[] = "\x1b[30m";
escape[3] = '0' + static_cast<char>(c); escape[3] = '0' + static_cast<char>(c);
std::fputs(escape, stdout); std::fputs(escape, stdout);
@ -1254,7 +1254,7 @@ FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) {
std::fputs(RESET_COLOR, stdout); std::fputs(RESET_COLOR, stdout);
} }
FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) { FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
MemoryWriter w; MemoryWriter w;
printf(w, format, args); printf(w, format, args);
std::size_t size = w.size(); std::size_t size = w.size();
@ -1273,10 +1273,10 @@ template const char *fmt::BasicFormatter<char>::format(
const char *&format_str, const fmt::internal::Arg &arg); const char *&format_str, const fmt::internal::Arg &arg);
template void fmt::BasicFormatter<char>::format( template void fmt::BasicFormatter<char>::format(
BasicStringRef<char> format, const ArgList &args); CStringRef format, const ArgList &args);
template void fmt::internal::PrintfFormatter<char>::format( template void fmt::internal::PrintfFormatter<char>::format(
BasicWriter<char> &writer, BasicStringRef<char> format, const ArgList &args); BasicWriter<char> &writer, CStringRef format, const ArgList &args);
template int fmt::internal::CharTraits<char>::format_float( template int fmt::internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format, char *buffer, std::size_t size, const char *format,
@ -1294,10 +1294,10 @@ template const wchar_t *fmt::BasicFormatter<wchar_t>::format(
const wchar_t *&format_str, const fmt::internal::Arg &arg); const wchar_t *&format_str, const fmt::internal::Arg &arg);
template void fmt::BasicFormatter<wchar_t>::format( template void fmt::BasicFormatter<wchar_t>::format(
BasicStringRef<wchar_t> format, const ArgList &args); BasicCStringRef<wchar_t> format, const ArgList &args);
template void fmt::internal::PrintfFormatter<wchar_t>::format( template void fmt::internal::PrintfFormatter<wchar_t>::format(
BasicWriter<wchar_t> &writer, BasicStringRef<wchar_t> format, BasicWriter<wchar_t> &writer, WCStringRef format,
const ArgList &args); const ArgList &args);
template int fmt::internal::CharTraits<wchar_t>::format_float( template int fmt::internal::CharTraits<wchar_t>::format_float(

141
format.h
View File

@ -206,8 +206,7 @@ void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
/** /**
\rst \rst
A string reference. It can be constructed from a C string or A string reference. It can be constructed from a C string or ``std::string``.
``std::string``.
You can use one of the following typedefs for common character types: You can use one of the following typedefs for common character types:
@ -236,9 +235,7 @@ class BasicStringRef {
std::size_t size_; std::size_t size_;
public: public:
/** /** Constructs a string reference object from a C string and a size. */
Constructs a string reference object from a C string and a size.
*/
BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {} BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
/** /**
@ -264,17 +261,13 @@ class BasicStringRef {
\endrst \endrst
*/ */
std::basic_string<Char> to_string() const { std::basic_string<Char> to_string() const {
return std::basic_string<Char>(data_, size()); return std::basic_string<Char>(data_, size_);
} }
/** /** Returns the pointer to a C string. */
Returns the pointer to a C string. const Char *data() const { return data_; }
*/
const Char *c_str() const { return data_; }
/** /** Returns the string size. */
Returns the string size.
*/
std::size_t size() const { return size_; } std::size_t size() const { return size_; }
friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) { friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
@ -284,19 +277,69 @@ class BasicStringRef {
return lhs.data_ != rhs.data_; return lhs.data_ != rhs.data_;
} }
friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) { friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
return std::lexicographical_compare(lhs.data_, lhs.data_ + lhs.size_, rhs.data_, rhs.data_ + rhs.size_); return std::lexicographical_compare(
lhs.data_, lhs.data_ + lhs.size_, rhs.data_, rhs.data_ + rhs.size_);
} }
}; };
typedef BasicStringRef<char> StringRef; typedef BasicStringRef<char> StringRef;
typedef BasicStringRef<wchar_t> WStringRef; typedef BasicStringRef<wchar_t> WStringRef;
/**
\rst
A reference to a null terminated string. It can be constructed from a C
string or ``std::string``.
You can use one of the following typedefs for common character types:
+-------------+--------------------------+
| Type | Definition |
+=============+==========================+
| CStringRef | BasicCStringRef<char> |
+-------------+--------------------------+
| WCStringRef | BasicCStringRef<wchar_t> |
+-------------+--------------------------+
This class is most useful as a parameter type to allow passing
different types of strings to a function, for example::
template <typename... Args>
std::string format(CStringRef format_str, const Args & ... args);
format("{}", 42);
format(std::string("{}"), 42);
\endrst
*/
template <typename Char>
class BasicCStringRef {
private:
const Char *data_;
public:
/** Constructs a string reference object from a C string. */
BasicCStringRef(const Char *s) : data_(s) {}
/**
\rst
Constructs a string reference from an ``std::string`` object.
\endrst
*/
BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
/** Returns the pointer to a C string. */
const Char *c_str() const { return data_; }
};
typedef BasicCStringRef<char> CStringRef;
typedef BasicCStringRef<wchar_t> WCStringRef;
/** /**
A formatting error such as invalid format string. A formatting error such as invalid format string.
*/ */
class FormatError : public std::runtime_error { class FormatError : public std::runtime_error {
public: public:
explicit FormatError(StringRef message) explicit FormatError(CStringRef message)
: std::runtime_error(message.c_str()) {} : std::runtime_error(message.c_str()) {}
}; };
@ -874,12 +917,12 @@ class MakeValue : public Arg {
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported); MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
void set_string(StringRef str) { void set_string(StringRef str) {
string.value = str.c_str(); string.value = str.data();
string.size = str.size(); string.size = str.size();
} }
void set_string(WStringRef str) { void set_string(WStringRef str) {
wstring.value = str.c_str(); wstring.value = str.data();
wstring.size = str.size(); wstring.size = str.size();
} }
@ -895,10 +938,13 @@ class MakeValue : public Arg {
public: public:
MakeValue() {} MakeValue() {}
#define FMT_MAKE_VALUE(Type, field, TYPE) \ #define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
MakeValue(Type value) { field = value; } \ MakeValue(Type value) { field = rhs; } \
static uint64_t type(Type) { return Arg::TYPE; } static uint64_t type(Type) { return Arg::TYPE; }
#define FMT_MAKE_VALUE(Type, field, TYPE) \
FMT_MAKE_VALUE_(Type, field, TYPE, value)
FMT_MAKE_VALUE(bool, int_value, BOOL) FMT_MAKE_VALUE(bool, int_value, BOOL)
FMT_MAKE_VALUE(short, int_value, INT) FMT_MAKE_VALUE(short, int_value, INT)
FMT_MAKE_VALUE(unsigned short, uint_value, UINT) FMT_MAKE_VALUE(unsigned short, uint_value, UINT)
@ -952,6 +998,7 @@ class MakeValue : public Arg {
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING) FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
FMT_MAKE_STR_VALUE(const std::string &, STRING) FMT_MAKE_STR_VALUE(const std::string &, STRING)
FMT_MAKE_STR_VALUE(StringRef, STRING) FMT_MAKE_STR_VALUE(StringRef, STRING)
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \ #define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
MakeValue(typename WCharHelper<Type, Char>::Supported value) { \ MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
@ -1270,7 +1317,7 @@ class PrintfFormatter : private FormatterBase {
public: public:
void format(BasicWriter<Char> &writer, void format(BasicWriter<Char> &writer,
BasicStringRef<Char> format_str, const ArgList &args); BasicCStringRef<Char> format_str, const ArgList &args);
}; };
} // namespace internal } // namespace internal
@ -1301,7 +1348,7 @@ class BasicFormatter : private internal::FormatterBase {
BasicWriter<Char> &writer() { return writer_; } BasicWriter<Char> &writer() { return writer_; }
void format(BasicStringRef<Char> format_str, const ArgList &args); void format(BasicCStringRef<Char> format_str, const ArgList &args);
const Char *format(const Char *&format_str, const internal::Arg &arg); const Char *format(const Char *&format_str, const internal::Arg &arg);
}; };
@ -1729,7 +1776,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
*/ */
class SystemError : public internal::RuntimeError { class SystemError : public internal::RuntimeError {
private: private:
void init(int err_code, StringRef format_str, ArgList args); void init(int err_code, CStringRef format_str, ArgList args);
protected: protected:
int error_code_; int error_code_;
@ -1764,10 +1811,10 @@ class SystemError : public internal::RuntimeError {
throw fmt::SystemError(errno, "cannot open file '{}'", filename); throw fmt::SystemError(errno, "cannot open file '{}'", filename);
\endrst \endrst
*/ */
SystemError(int error_code, StringRef message) { SystemError(int error_code, CStringRef message) {
init(error_code, message, ArgList()); init(error_code, message, ArgList());
} }
FMT_VARIADIC_CTOR(SystemError, init, int, StringRef) FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
int error_code() const { return error_code_; } int error_code() const { return error_code_; }
}; };
@ -1942,10 +1989,10 @@ class BasicWriter {
See also :ref:`syntax`. See also :ref:`syntax`.
\endrst \endrst
*/ */
void write(BasicStringRef<Char> format, ArgList args) { void write(BasicCStringRef<Char> format, ArgList args) {
BasicFormatter<Char>(*this).format(format, args); BasicFormatter<Char>(*this).format(format, args);
} }
FMT_VARIADIC_VOID(write, BasicStringRef<Char>) FMT_VARIADIC_VOID(write, BasicCStringRef<Char>)
BasicWriter &operator<<(int value) { BasicWriter &operator<<(int value) {
return *this << IntFormatSpec<int>(value); return *this << IntFormatSpec<int>(value);
@ -2008,14 +2055,14 @@ class BasicWriter {
\endrst \endrst
*/ */
BasicWriter &operator<<(fmt::BasicStringRef<Char> value) { BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
const Char *str = value.c_str(); const Char *str = value.data();
buffer_.append(str, str + value.size()); buffer_.append(str, str + value.size());
return *this; return *this;
} }
BasicWriter &operator<<( BasicWriter &operator<<(
typename internal::WCharHelper<StringRef, Char>::Supported value) { typename internal::WCharHelper<StringRef, Char>::Supported value) {
const char *str = value.c_str(); const char *str = value.data();
buffer_.append(str, str + value.size()); buffer_.append(str, str + value.size());
return *this; return *this;
} }
@ -2561,7 +2608,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
Example: Example:
PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23; PrintColored(fmt::RED, "Elapsed time: {0:.2f} seconds") << 1.23;
*/ */
void print_colored(Color c, StringRef format, ArgList args); void print_colored(Color c, CStringRef format, ArgList args);
/** /**
\rst \rst
@ -2572,13 +2619,13 @@ void print_colored(Color c, StringRef format, ArgList args);
std::string message = format("The answer is {}", 42); std::string message = format("The answer is {}", 42);
\endrst \endrst
*/ */
inline std::string format(StringRef format_str, ArgList args) { inline std::string format(CStringRef format_str, ArgList args) {
MemoryWriter w; MemoryWriter w;
w.write(format_str, args); w.write(format_str, args);
return w.str(); return w.str();
} }
inline std::wstring format(WStringRef format_str, ArgList args) { inline std::wstring format(WCStringRef format_str, ArgList args) {
WMemoryWriter w; WMemoryWriter w;
w.write(format_str, args); w.write(format_str, args);
return w.str(); return w.str();
@ -2593,7 +2640,7 @@ inline std::wstring format(WStringRef format_str, ArgList args) {
print(stderr, "Don't {}!", "panic"); print(stderr, "Don't {}!", "panic");
\endrst \endrst
*/ */
void print(std::FILE *f, StringRef format_str, ArgList args); void print(std::FILE *f, CStringRef format_str, ArgList args);
/** /**
\rst \rst
@ -2604,7 +2651,7 @@ void print(std::FILE *f, StringRef format_str, ArgList args);
print("Elapsed time: {0:.2f} seconds", 1.23); print("Elapsed time: {0:.2f} seconds", 1.23);
\endrst \endrst
*/ */
void print(StringRef format_str, ArgList args); void print(CStringRef format_str, ArgList args);
/** /**
\rst \rst
@ -2615,10 +2662,10 @@ void print(StringRef format_str, ArgList args);
print(cerr, "Don't {}!", "panic"); print(cerr, "Don't {}!", "panic");
\endrst \endrst
*/ */
void print(std::ostream &os, StringRef format_str, ArgList args); void print(std::ostream &os, CStringRef format_str, ArgList args);
template <typename Char> template <typename Char>
void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args) { void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
internal::PrintfFormatter<Char>().format(w, format, args); internal::PrintfFormatter<Char>().format(w, format, args);
} }
@ -2631,7 +2678,7 @@ void printf(BasicWriter<Char> &w, BasicStringRef<Char> format, ArgList args) {
std::string message = fmt::sprintf("The answer is %d", 42); std::string message = fmt::sprintf("The answer is %d", 42);
\endrst \endrst
*/ */
inline std::string sprintf(StringRef format, ArgList args) { inline std::string sprintf(CStringRef format, ArgList args) {
MemoryWriter w; MemoryWriter w;
printf(w, format, args); printf(w, format, args);
return w.str(); return w.str();
@ -2646,7 +2693,7 @@ inline std::string sprintf(StringRef format, ArgList args) {
fmt::fprintf(stderr, "Don't %s!", "panic"); fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst \endrst
*/ */
int fprintf(std::FILE *f, StringRef format, ArgList args); int fprintf(std::FILE *f, CStringRef format, ArgList args);
/** /**
\rst \rst
@ -2657,7 +2704,7 @@ int fprintf(std::FILE *f, StringRef format, ArgList args);
fmt::printf("Elapsed time: %.2f seconds", 1.23); fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst \endrst
*/ */
inline int printf(StringRef format, ArgList args) { inline int printf(CStringRef format, ArgList args) {
return fprintf(stdout, format, args); return fprintf(stdout, format, args);
} }
@ -2918,15 +2965,15 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__) #define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
namespace fmt { namespace fmt {
FMT_VARIADIC(std::string, format, StringRef) FMT_VARIADIC(std::string, format, CStringRef)
FMT_VARIADIC_W(std::wstring, format, WStringRef) FMT_VARIADIC_W(std::wstring, format, WCStringRef)
FMT_VARIADIC(void, print, StringRef) FMT_VARIADIC(void, print, CStringRef)
FMT_VARIADIC(void, print, std::FILE *, StringRef) FMT_VARIADIC(void, print, std::FILE *, CStringRef)
FMT_VARIADIC(void, print, std::ostream &, StringRef) FMT_VARIADIC(void, print, std::ostream &, CStringRef)
FMT_VARIADIC(void, print_colored, Color, StringRef) FMT_VARIADIC(void, print_colored, Color, CStringRef)
FMT_VARIADIC(std::string, sprintf, StringRef) FMT_VARIADIC(std::string, sprintf, CStringRef)
FMT_VARIADIC(int, printf, StringRef) FMT_VARIADIC(int, printf, CStringRef)
FMT_VARIADIC(int, fprintf, std::FILE *, StringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
} }
// Restore warnings. // Restore warnings.

View File

@ -83,7 +83,8 @@ fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
fmt::report_system_error(errno, "cannot close file"); fmt::report_system_error(errno, "cannot close file");
} }
fmt::BufferedFile::BufferedFile(fmt::StringRef filename, fmt::StringRef mode) { fmt::BufferedFile::BufferedFile(
fmt::CStringRef filename, fmt::CStringRef mode) {
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0); FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
if (!file_) if (!file_)
throw SystemError(errno, "cannot open file {}", filename); throw SystemError(errno, "cannot open file {}", filename);
@ -108,7 +109,7 @@ int fmt::BufferedFile::fileno() const {
return fd; return fd;
} }
fmt::File::File(fmt::StringRef path, int oflag) { fmt::File::File(fmt::CStringRef path, int oflag) {
int mode = S_IRUSR | S_IWUSR; int mode = S_IRUSR | S_IWUSR;
#if defined(_WIN32) && !defined(__MINGW32__) #if defined(_WIN32) && !defined(__MINGW32__)
fd_ = -1; fd_ = -1;

10
posix.h
View File

@ -181,7 +181,7 @@ public:
#endif #endif
// Opens a file. // Opens a file.
BufferedFile(fmt::StringRef filename, fmt::StringRef mode); BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file. // Closes the file.
void close(); void close();
@ -193,10 +193,10 @@ public:
// of MinGW that define fileno as a macro. // of MinGW that define fileno as a macro.
int (fileno)() const; int (fileno)() const;
void print(fmt::StringRef format_str, const ArgList &args) { void print(CStringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args); fmt::print(file_, format_str, args);
} }
FMT_VARIADIC(void, print, fmt::StringRef) FMT_VARIADIC(void, print, CStringRef)
}; };
// A file. Closed file is represented by a File object with descriptor -1. // A file. Closed file is represented by a File object with descriptor -1.
@ -224,7 +224,7 @@ class File {
File() FMT_NOEXCEPT : fd_(-1) {} File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file. // Opens a file and constructs a File object representing this file.
File(fmt::StringRef path, int oflag); File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES #if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue // Emulate a move constructor and a move assignment operator if rvalue
@ -296,7 +296,7 @@ class File {
void close(); void close();
// Returns the file size. // Returns the file size.
fmt::LongLong size() const; LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer. // Attempts to read count bytes from the file into the specified buffer.
std::size_t read(void *buffer, std::size_t count); std::size_t read(void *buffer, std::size_t count);

View File

@ -66,6 +66,7 @@ using fmt::BasicWriter;
using fmt::format; using fmt::format;
using fmt::FormatError; using fmt::FormatError;
using fmt::StringRef; using fmt::StringRef;
using fmt::CStringRef;
using fmt::MemoryWriter; using fmt::MemoryWriter;
using fmt::WMemoryWriter; using fmt::WMemoryWriter;
using fmt::pad; using fmt::pad;
@ -136,6 +137,24 @@ struct WriteChecker {
EXPECT_PRED_FORMAT1(WriteChecker<wchar_t>(), value) EXPECT_PRED_FORMAT1(WriteChecker<wchar_t>(), value)
} // namespace } // namespace
TEST(StringRefTest, Ctor) {
EXPECT_STREQ("abc", StringRef("abc").data());
EXPECT_EQ(3u, StringRef("abc").size());
EXPECT_STREQ("defg", StringRef(std::string("defg")).data());
EXPECT_EQ(4u, StringRef(std::string("defg")).size());
}
TEST(StringRefTest, ConvertToString) {
std::string s = StringRef("abc").to_string();
EXPECT_EQ("abc", s);
}
TEST(CStringRefTest, Ctor) {
EXPECT_STREQ("abc", CStringRef("abc").c_str());
EXPECT_STREQ("defg", CStringRef(std::string("defg")).c_str());
}
class TestString { class TestString {
private: private:
std::string value_; std::string value_;
@ -583,7 +602,7 @@ TEST(FormatterTest, ArgErrors) {
template <int N> template <int N>
struct TestFormat { struct TestFormat {
template <typename... Args> template <typename... Args>
static std::string format(fmt::StringRef format_str, const Args & ... args) { static std::string format(fmt::CStringRef format_str, const Args & ... args) {
return TestFormat<N - 1>::format(format_str, N - 1, args...); return TestFormat<N - 1>::format(format_str, N - 1, args...);
} }
}; };
@ -591,7 +610,7 @@ struct TestFormat {
template <> template <>
struct TestFormat<0> { struct TestFormat<0> {
template <typename... Args> template <typename... Args>
static std::string format(fmt::StringRef format_str, const Args & ... args) { static std::string format(fmt::CStringRef format_str, const Args & ... args) {
return fmt::format(format_str, args...); return fmt::format(format_str, args...);
} }
}; };
@ -1372,6 +1391,10 @@ TEST(FormatterTest, FormatStringRef) {
EXPECT_EQ("test", format("{0}", StringRef("test"))); EXPECT_EQ("test", format("{0}", StringRef("test")));
} }
TEST(FormatterTest, FormatCStringRef) {
EXPECT_EQ("test", format("{0}", CStringRef("test")));
}
TEST(FormatterTest, FormatUsingIOStreams) { TEST(FormatterTest, FormatUsingIOStreams) {
EXPECT_EQ("a string", format("{0}", TestString("a string"))); EXPECT_EQ("a string", format("{0}", TestString("a string")));
std::string s = format("The date is {0}", Date(2012, 12, 9)); std::string s = format("The date is {0}", Date(2012, 12, 9));
@ -1440,19 +1463,6 @@ TEST(FormatterTest, FormatExamples) {
}, error_code, "Cannot open file 'nonexistent'"); }, error_code, "Cannot open file 'nonexistent'");
} }
TEST(StringRefTest, Ctor) {
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());
}
TEST(StringRefTest, ConvertToString) {
std::string s = StringRef("abc").to_string();
EXPECT_EQ("abc", s);
}
TEST(FormatterTest, Examples) { TEST(FormatterTest, Examples) {
EXPECT_EQ("First, thou shalt count to three", EXPECT_EQ("First, thou shalt count to three",
format("First, thou shalt count to {0}", "three")); format("First, thou shalt count to {0}", "three"));

View File

@ -207,7 +207,7 @@ int (test::fileno)(FILE *stream) {
# define EXPECT_EQ_POSIX(expected, actual) # define EXPECT_EQ_POSIX(expected, actual)
#endif #endif
void write_file(fmt::StringRef filename, fmt::StringRef content) { void write_file(fmt::CStringRef filename, fmt::StringRef content) {
fmt::BufferedFile f(filename, "w"); fmt::BufferedFile f(filename, "w");
f.print("{}", content); f.print("{}", content);
} }

View File

@ -64,7 +64,7 @@ File open_file() {
// Attempts to write a string to a file. // Attempts to write a string to a file.
void write(File &f, fmt::StringRef s) { void write(File &f, fmt::StringRef s) {
std::size_t num_chars_left = s.size(); std::size_t num_chars_left = s.size();
const char *ptr = s.c_str(); const char *ptr = s.data();
do { do {
std::streamsize count = f.write(ptr, num_chars_left); std::streamsize count = f.write(ptr, num_chars_left);
ptr += count; ptr += count;