Test MakeArg and fix formatting.

This commit is contained in:
Victor Zverovich
2014-07-03 08:50:57 -07:00
parent 43a873f7ff
commit 4e260e8599
4 changed files with 68 additions and 59 deletions

View File

@@ -191,9 +191,16 @@ class BasicStringRef {
Returns the string size. Returns the string size.
*/ */
std::size_t size() const { std::size_t size() const {
if (size_ == 0) size_ = std::char_traits<Char>::length(data_); if (size_ == 0 && data_) size_ = std::char_traits<Char>::length(data_);
return size_; return size_;
} }
friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
return lhs.data_ == rhs.data_;
}
friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
return lhs.data_ != rhs.data_;
}
}; };
typedef BasicStringRef<char> StringRef; typedef BasicStringRef<char> StringRef;
@@ -611,16 +618,28 @@ struct Arg {
template <typename Char> template <typename Char>
class MakeArg : public Arg { class MakeArg : public Arg {
private: private:
// This method is private to disallow formatting of arbitrary pointers. // The following two methods are private to disallow formatting of
// If you want to output a pointer cast it to const void*. Do not implement! // arbitrary pointers. If you want to output a pointer cast it to
// "void *" or "const void *". In particular, this forbids formatting
// of "[const] volatile char *" which is printed as bool by iostreams.
// Do not implement!
template <typename T> template <typename T>
MakeArg(const T *value); MakeArg(const T *value);
// This method is private to disallow formatting of arbitrary pointers.
// If you want to output a pointer cast it to void*. Do not implement!
template <typename T> template <typename T>
MakeArg(T *value); MakeArg(T *value);
void SetString(StringRef str) {
type = STRING;
string.value = str.c_str();
string.size = str.size();
}
void SetString(WStringRef str) {
type = WSTRING;
wstring.value = str.c_str();
wstring.size = str.size();
}
public: public:
MakeArg() {} MakeArg() {}
MakeArg(bool value) { type = INT; int_value = value; } MakeArg(bool value) { type = INT; int_value = value; }
@@ -629,6 +648,8 @@ class MakeArg : public Arg {
MakeArg(int value) { type = INT; int_value = value; } MakeArg(int value) { type = INT; int_value = value; }
MakeArg(unsigned value) { type = UINT; uint_value = value; } MakeArg(unsigned value) { type = UINT; uint_value = value; }
MakeArg(long value) { MakeArg(long value) {
// To minimize the number of types we need to deal with, long is
// translated either to int or to long long depending on its size.
if (sizeof(long) == sizeof(int)) { if (sizeof(long) == sizeof(int)) {
type = INT; type = INT;
int_value = static_cast<int>(value); int_value = static_cast<int>(value);
@@ -659,38 +680,18 @@ class MakeArg : public Arg {
int_value = internal::CharTraits<Char>::ConvertChar(value); int_value = internal::CharTraits<Char>::ConvertChar(value);
} }
MakeArg(const char *value) { MakeArg(char *value) { SetString(value); }
type = STRING; MakeArg(const char *value) { SetString(value); }
string.value = value; MakeArg(const std::string &value) { SetString(value); }
string.size = 0; MakeArg(StringRef value) { SetString(value); }
}
MakeArg(const wchar_t *value) { MakeArg(wchar_t *value) { SetString(value); }
type = WSTRING; MakeArg(const wchar_t *value) { SetString(value); }
wstring.value = value; MakeArg(const std::wstring &value) { SetString(value); }
wstring.size = 0; MakeArg(WStringRef value) { SetString(value); }
}
MakeArg(Char *value) {
type = STRING;
string.value = value;
string.size = 0;
}
MakeArg(const void *value) { type = POINTER; pointer_value = value; }
MakeArg(void *value) { type = POINTER; pointer_value = value; } MakeArg(void *value) { type = POINTER; pointer_value = value; }
MakeArg(const void *value) { type = POINTER; pointer_value = value; }
MakeArg(const std::basic_string<Char> &value) {
type = STRING;
string.value = value.c_str();
string.size = value.size();
}
MakeArg(BasicStringRef<Char> value) {
type = STRING;
string.value = value.c_str();
string.size = value.size();
}
template <typename T> template <typename T>
MakeArg(const T &value) { MakeArg(const T &value) {

View File

@@ -29,9 +29,12 @@ expect_compile_error("fmt::internal::Array<char, 5> a, b; b = a;")
expect_compile_error("const fmt::Writer a, b(a);") expect_compile_error("const fmt::Writer a, b(a);")
expect_compile_error("fmt::Writer a, b; b = a;") expect_compile_error("fmt::Writer a, b; b = a;")
# Formatter is not copyable from a temporary. # MakeArg doesn't accept [const] volatile char *.
expect_compile_error("fmt::Formatter<> a(fmt::Formatter<>(\"a\"));") expect_compile_error("volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
expect_compile_error("fmt::Formatter<> b(\"a\"); b = fmt::Formatter<>(\"b\");") expect_compile_error("const volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
# MakeArg<char> doesn't accept wchar_t.
expect_compile_error("fmt::internal::MakeArg<char>(L'a');")
# Writing a wide character to a character stream Writer is forbidden. # Writing a wide character to a character stream Writer is forbidden.
expect_compile_error("fmt::Writer() << L'a';") expect_compile_error("fmt::Writer() << L'a';")
@@ -39,7 +42,4 @@ expect_compile_error("fmt::Writer() << fmt::pad(\"abc\", 5, L' ');")
expect_compile_error("fmt::Writer() << fmt::pad(42, 5, L' ');") expect_compile_error("fmt::Writer() << fmt::pad(42, 5, L' ');")
# Formatting a wide character with a narrow format string is forbidden. # Formatting a wide character with a narrow format string is forbidden.
expect_compile_error("fmt::Format(\"{}\") << L'a';") expect_compile_error("fmt::format(\"{}\", L'a';")
# There is no implicit conversion from FILE* to FileSink.
expect_compile_error("fmt::FileSink fs = 0;")

View File

@@ -73,7 +73,7 @@ TEST(UtilTest, Increment) {
} }
#define EXPECT_ARG_(Char, type_code, Type, field, value) { \ #define EXPECT_ARG_(Char, type_code, Type, field, value) { \
Type expected_value = value; \ Type expected_value = static_cast<Type>(value); \
fmt::internal::Arg arg = \ fmt::internal::Arg arg = \
fmt::internal::MakeArg<Char>(expected_value); \ fmt::internal::MakeArg<Char>(expected_value); \
EXPECT_EQ(fmt::internal::Arg::type_code, arg.type); \ EXPECT_EQ(fmt::internal::Arg::type_code, arg.type); \
@@ -91,17 +91,17 @@ TEST(UtilTest, MakeArg) {
EXPECT_ARG(INT, bool, int_value, true); EXPECT_ARG(INT, bool, int_value, true);
// Test char. // Test char.
EXPECT_ARG(CHAR, signed char, int_value, 42); EXPECT_ARG(CHAR, signed char, int_value, 'a');
EXPECT_ARG(CHAR, signed char, int_value, SCHAR_MIN); EXPECT_ARG(CHAR, signed char, int_value, SCHAR_MIN);
EXPECT_ARG(CHAR, signed char, int_value, SCHAR_MAX); EXPECT_ARG(CHAR, signed char, int_value, SCHAR_MAX);
EXPECT_ARG(CHAR, unsigned char, int_value, 42); EXPECT_ARG(CHAR, unsigned char, int_value, 'a');
EXPECT_ARG(CHAR, unsigned char, int_value, UCHAR_MAX ); EXPECT_ARG(CHAR, unsigned char, int_value, UCHAR_MAX );
EXPECT_ARG(CHAR, char, int_value, 'a'); EXPECT_ARG(CHAR, char, int_value, 'a');
EXPECT_ARG(CHAR, char, int_value, CHAR_MIN); EXPECT_ARG(CHAR, char, int_value, CHAR_MIN);
EXPECT_ARG(CHAR, char, int_value, CHAR_MAX); EXPECT_ARG(CHAR, char, int_value, CHAR_MAX);
// Test wchar_t. // Test wchar_t.
EXPECT_ARGW(CHAR, wchar_t, int_value, 42); EXPECT_ARGW(CHAR, wchar_t, int_value, L'a');
EXPECT_ARGW(CHAR, wchar_t, int_value, WCHAR_MIN); EXPECT_ARGW(CHAR, wchar_t, int_value, WCHAR_MIN);
EXPECT_ARGW(CHAR, wchar_t, int_value, WCHAR_MAX); EXPECT_ARGW(CHAR, wchar_t, int_value, WCHAR_MAX);
@@ -163,9 +163,17 @@ TEST(UtilTest, MakeArg) {
char STR[] = "test"; char STR[] = "test";
EXPECT_ARG(STRING, char*, string.value, STR); EXPECT_ARG(STRING, char*, string.value, STR);
EXPECT_ARG(STRING, const char*, string.value, STR); EXPECT_ARG(STRING, const char*, string.value, STR);
//EXPECT_ARG(STRING, volatile char*, string.value, STR); EXPECT_ARG(STRING, std::string, string.value, STR);
EXPECT_ARG(STRING, fmt::StringRef, string.value, STR);
// TODO: test pointers // Test wide string.
wchar_t WSTR[] = L"test";
EXPECT_ARGW(WSTRING, wchar_t*, wstring.value, WSTR);
EXPECT_ARGW(WSTRING, const wchar_t*, wstring.value, WSTR);
EXPECT_ARGW(WSTRING, std::wstring, wstring.value, WSTR);
EXPECT_ARGW(WSTRING, fmt::WStringRef, wstring.value, WSTR);
// TODO: test that wide string is rejected by MakeArg<char>
} }
// Tests fmt::internal::CountDigits for integer type Int. // Tests fmt::internal::CountDigits for integer type Int.