From: Yedidya Feldblum Date: Sat, 24 May 2014 18:45:38 +0000 (-0700) Subject: Add shorthand functions to Format.h. X-Git-Tag: v0.22.0~526 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=4460753ff370dce64791167e2afd3824ea6a1c57;p=folly.git Add shorthand functions to Format.h. Summary: [Folly] Add shorthand functions to Format.h. This makes calling code simpler when it does not depend on the raw performance of writing to a stream. Test Plan: $ fbconfig -r folly/test $ fbmake runtests Reviewed By: tudorb@fb.com Subscribers: folly@lists, dougw FB internal diff: D1347353 Tasks: 4391110 --- diff --git a/folly/Format.h b/folly/Format.h index eb8b5f81..7cc83413 100644 --- a/folly/Format.h +++ b/folly/Format.h @@ -207,6 +207,15 @@ Formatter format(StringPiece fmt, Args&&... args) { fmt, std::forward(args)...); } +/** + * Like format(), but immediately returns the formatted string instead of an + * intermediate format object. + */ +template +inline std::string sformat(StringPiece fmt, Args&&... args) { + return format(fmt, std::forward(args)...).str(); +} + /** * Create a formatter object from a dynamic format string. * @@ -222,6 +231,15 @@ Formatter formatChecked(StringPiece fmt, Args&&... args) { return f; } +/** + * Like formatChecked(), but immediately returns the formatted string instead of + * an intermediate format object. + */ +template +inline std::string sformatChecked(StringPiece fmt, Args&&... args) { + return formatChecked(fmt, std::forward(args)...).str(); +} + /** * Create a formatter object that takes one argument (of container type) * and uses that container to get argument values from. @@ -241,6 +259,15 @@ Formatter vformat(StringPiece fmt, Container&& container) { fmt, std::forward(container)); } +/** + * Like vformat(), but immediately returns the formatted string instead of an + * intermediate format object. + */ +template +inline std::string svformat(StringPiece fmt, Container&& container) { + return vformat(fmt, std::forward(container)).str(); +} + /** * Create a formatter object from a dynamic format string. * @@ -257,6 +284,15 @@ Formatter vformatChecked(StringPiece fmt, return f; } +/** + * Like vformatChecked(), but immediately returns the formatted string instead + * of an intermediate format object. + */ +template +inline std::string svformatChecked(StringPiece fmt, Container&& container) { + return vformatChecked(fmt, std::forward(container)).str(); +} + /** * Wrap a sequence or associative container so that out-of-range lookups * return a default value rather than throwing an exception. diff --git a/folly/docs/Format.md b/folly/docs/Format.md index 2a16a84d..5696c8be 100644 --- a/folly/docs/Format.md +++ b/folly/docs/Format.md @@ -19,7 +19,9 @@ Here are some code samples to get started: ``` Cpp using folly::format; +using folly::sformat; using folly::vformat; +using folly::svformat; // Objects produced by format() can be streamed without creating // an intermediary string; {} yields the next argument using default @@ -27,6 +29,10 @@ using folly::vformat; std::cout << format("The answers are {} and {}", 23, 42); // => "The answers are 23 and 42" +// If you just want the string, though, you're covered. +std::string result = sformat("The answers are {} and {}", 23, 42); +// => "The answers are 23 and 42" + // To insert a literal '{' or '}', just double it. std::cout << format("{} {{}} {{{}}}", 23, 42); // => "23 {} {42}" @@ -54,6 +60,11 @@ std::cout << vformat("The only {what} is {value}", m); // same as std::cout << format("The only {0[what]} is {0[value]}", m); // => "The only answer is 42" +// And if you just want the string, +std::string result = svformat("The only {what} is {value}", m); +// => "The only answer is 42" +std::string result = svformat("The only {0[what]} is {0[value]}", m); +// => "The only answer is 42" // {} works for vformat too std::vector v {42, 23}; diff --git a/folly/test/FormatTest.cpp b/folly/test/FormatTest.cpp index 65d5c29e..3c27dc3e 100644 --- a/folly/test/FormatTest.cpp +++ b/folly/test/FormatTest.cpp @@ -27,26 +27,6 @@ using namespace folly; -template -std::string fstr(StringPiece fmt, Args&&... args) { - return format(fmt, std::forward(args)...).str(); -} - -template -std::string vstr(StringPiece fmt, const C& c) { - return vformat(fmt, c).str(); -} - -template -std::string fstrChecked(StringPiece fmt, Args&&... args) { - return formatChecked(fmt, std::forward(args)...).str(); -} - -template -std::string vstrChecked(StringPiece fmt, const C& c) { - return vformatChecked(fmt, c).str(); -} - template void compareOctal(Uint u) { char buf1[detail::kMaxOctalLength + 1]; @@ -110,97 +90,97 @@ TEST(Format, uintToBinary) { } TEST(Format, Simple) { - EXPECT_EQ("hello", fstr("hello")); - EXPECT_EQ("42", fstr("{}", 42)); - EXPECT_EQ("42 42", fstr("{0} {0}", 42)); - EXPECT_EQ("00042 23 42", fstr("{0:05} {1:3} {0:4}", 42, 23)); + EXPECT_EQ("hello", sformat("hello")); + EXPECT_EQ("42", sformat("{}", 42)); + EXPECT_EQ("42 42", sformat("{0} {0}", 42)); + EXPECT_EQ("00042 23 42", sformat("{0:05} {1:3} {0:4}", 42, 23)); EXPECT_EQ("hello world hello 42", - fstr("{0} {1} {0} {2}", "hello", "world", 42)); - EXPECT_EQ("XXhelloXX", fstr("{:X^9}", "hello")); - EXPECT_EQ("XXX42XXXX", fstr("{:X^9}", 42)); - EXPECT_EQ("-0xYYYY2a", fstr("{:Y=#9x}", -42)); - EXPECT_EQ("*", fstr("{}", '*')); - EXPECT_EQ("42", fstr("{}", 42)); - EXPECT_EQ("0042", fstr("{:04}", 42)); - - EXPECT_EQ("hello ", fstr("{:7}", "hello")); - EXPECT_EQ("hello ", fstr("{:<7}", "hello")); - EXPECT_EQ(" hello", fstr("{:>7}", "hello")); + sformat("{0} {1} {0} {2}", "hello", "world", 42)); + EXPECT_EQ("XXhelloXX", sformat("{:X^9}", "hello")); + EXPECT_EQ("XXX42XXXX", sformat("{:X^9}", 42)); + EXPECT_EQ("-0xYYYY2a", sformat("{:Y=#9x}", -42)); + EXPECT_EQ("*", sformat("{}", '*')); + EXPECT_EQ("42", sformat("{}", 42)); + EXPECT_EQ("0042", sformat("{:04}", 42)); + + EXPECT_EQ("hello ", sformat("{:7}", "hello")); + EXPECT_EQ("hello ", sformat("{:<7}", "hello")); + EXPECT_EQ(" hello", sformat("{:>7}", "hello")); std::vector v1 {10, 20, 30}; - EXPECT_EQ("0020", fstr("{0[1]:04}", v1)); - EXPECT_EQ("0020", vstr("{1:04}", v1)); - EXPECT_EQ("10 20", vstr("{} {}", v1)); + EXPECT_EQ("0020", sformat("{0[1]:04}", v1)); + EXPECT_EQ("0020", svformat("{1:04}", v1)); + EXPECT_EQ("10 20", svformat("{} {}", v1)); const std::vector v2 = v1; - EXPECT_EQ("0020", fstr("{0[1]:04}", v2)); - EXPECT_EQ("0020", vstr("{1:04}", v2)); - EXPECT_THROW(fstr("{0[3]:04}", v2), std::out_of_range); - EXPECT_THROW(vstr("{3:04}", v2), std::out_of_range); - EXPECT_EQ("0020", fstr("{0[1]:04}", defaulted(v2, 42))); - EXPECT_EQ("0020", vstr("{1:04}", defaulted(v2, 42))); - EXPECT_EQ("0042", fstr("{0[3]:04}", defaulted(v2, 42))); - EXPECT_EQ("0042", vstr("{3:04}", defaulted(v2, 42))); + EXPECT_EQ("0020", sformat("{0[1]:04}", v2)); + EXPECT_EQ("0020", svformat("{1:04}", v2)); + EXPECT_THROW(sformat("{0[3]:04}", v2), std::out_of_range); + EXPECT_THROW(svformat("{3:04}", v2), std::out_of_range); + EXPECT_EQ("0020", sformat("{0[1]:04}", defaulted(v2, 42))); + EXPECT_EQ("0020", svformat("{1:04}", defaulted(v2, 42))); + EXPECT_EQ("0042", sformat("{0[3]:04}", defaulted(v2, 42))); + EXPECT_EQ("0042", svformat("{3:04}", defaulted(v2, 42))); const int p[] = {10, 20, 30}; const int* q = p; - EXPECT_EQ("0020", fstr("{0[1]:04}", p)); - EXPECT_EQ("0020", vstr("{1:04}", p)); - EXPECT_EQ("0020", fstr("{0[1]:04}", q)); - EXPECT_EQ("0020", vstr("{1:04}", q)); - EXPECT_NE("", fstr("{}", q)); - - EXPECT_EQ("0x", fstr("{}", p).substr(0, 2)); - EXPECT_EQ("10", vstr("{}", p)); - EXPECT_EQ("0x", fstr("{}", q).substr(0, 2)); - EXPECT_EQ("10", vstr("{}", q)); + EXPECT_EQ("0020", sformat("{0[1]:04}", p)); + EXPECT_EQ("0020", svformat("{1:04}", p)); + EXPECT_EQ("0020", sformat("{0[1]:04}", q)); + EXPECT_EQ("0020", svformat("{1:04}", q)); + EXPECT_NE("", sformat("{}", q)); + + EXPECT_EQ("0x", sformat("{}", p).substr(0, 2)); + EXPECT_EQ("10", svformat("{}", p)); + EXPECT_EQ("0x", sformat("{}", q).substr(0, 2)); + EXPECT_EQ("10", svformat("{}", q)); q = nullptr; - EXPECT_EQ("(null)", fstr("{}", q)); + EXPECT_EQ("(null)", sformat("{}", q)); std::map m { {10, "hello"}, {20, "world"} }; - EXPECT_EQ("worldXX", fstr("{[20]:X<7}", m)); - EXPECT_EQ("worldXX", vstr("{20:X<7}", m)); - EXPECT_THROW(fstr("{[42]:X<7}", m), std::out_of_range); - EXPECT_THROW(vstr("{42:X<7}", m), std::out_of_range); - EXPECT_EQ("worldXX", fstr("{[20]:X<7}", defaulted(m, "meow"))); - EXPECT_EQ("worldXX", vstr("{20:X<7}", defaulted(m, "meow"))); - EXPECT_EQ("meowXXX", fstr("{[42]:X<7}", defaulted(m, "meow"))); - EXPECT_EQ("meowXXX", vstr("{42:X<7}", defaulted(m, "meow"))); + EXPECT_EQ("worldXX", sformat("{[20]:X<7}", m)); + EXPECT_EQ("worldXX", svformat("{20:X<7}", m)); + EXPECT_THROW(sformat("{[42]:X<7}", m), std::out_of_range); + EXPECT_THROW(svformat("{42:X<7}", m), std::out_of_range); + EXPECT_EQ("worldXX", sformat("{[20]:X<7}", defaulted(m, "meow"))); + EXPECT_EQ("worldXX", svformat("{20:X<7}", defaulted(m, "meow"))); + EXPECT_EQ("meowXXX", sformat("{[42]:X<7}", defaulted(m, "meow"))); + EXPECT_EQ("meowXXX", svformat("{42:X<7}", defaulted(m, "meow"))); std::map m2 { {"hello", "world"} }; - EXPECT_EQ("worldXX", fstr("{[hello]:X<7}", m2)); - EXPECT_EQ("worldXX", vstr("{hello:X<7}", m2)); - EXPECT_THROW(fstr("{[none]:X<7}", m2), std::out_of_range); - EXPECT_THROW(vstr("{none:X<7}", m2), std::out_of_range); - EXPECT_EQ("worldXX", fstr("{[hello]:X<7}", defaulted(m2, "meow"))); - EXPECT_EQ("worldXX", vstr("{hello:X<7}", defaulted(m2, "meow"))); - EXPECT_EQ("meowXXX", fstr("{[none]:X<7}", defaulted(m2, "meow"))); - EXPECT_EQ("meowXXX", vstr("{none:X<7}", defaulted(m2, "meow"))); + EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", m2)); + EXPECT_EQ("worldXX", svformat("{hello:X<7}", m2)); + EXPECT_THROW(sformat("{[none]:X<7}", m2), std::out_of_range); + EXPECT_THROW(svformat("{none:X<7}", m2), std::out_of_range); + EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", defaulted(m2, "meow"))); + EXPECT_EQ("worldXX", svformat("{hello:X<7}", defaulted(m2, "meow"))); + EXPECT_EQ("meowXXX", sformat("{[none]:X<7}", defaulted(m2, "meow"))); + EXPECT_EQ("meowXXX", svformat("{none:X<7}", defaulted(m2, "meow"))); // Test indexing in strings - EXPECT_EQ("61 62", fstr("{0[0]:x} {0[1]:x}", "abcde")); - EXPECT_EQ("61 62", vstr("{0:x} {1:x}", "abcde")); - EXPECT_EQ("61 62", fstr("{0[0]:x} {0[1]:x}", std::string("abcde"))); - EXPECT_EQ("61 62", vstr("{0:x} {1:x}", std::string("abcde"))); + EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", "abcde")); + EXPECT_EQ("61 62", svformat("{0:x} {1:x}", "abcde")); + EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", std::string("abcde"))); + EXPECT_EQ("61 62", svformat("{0:x} {1:x}", std::string("abcde"))); // Test booleans - EXPECT_EQ("true", fstr("{}", true)); - EXPECT_EQ("1", fstr("{:d}", true)); - EXPECT_EQ("false", fstr("{}", false)); - EXPECT_EQ("0", fstr("{:d}", false)); + EXPECT_EQ("true", sformat("{}", true)); + EXPECT_EQ("1", sformat("{:d}", true)); + EXPECT_EQ("false", sformat("{}", false)); + EXPECT_EQ("0", sformat("{:d}", false)); // Test pairs { std::pair p {42, "hello"}; - EXPECT_EQ(" 42 hello ", fstr("{0[0]:6} {0[1]:6}", p)); - EXPECT_EQ(" 42 hello ", vstr("{:6} {:6}", p)); + EXPECT_EQ(" 42 hello ", sformat("{0[0]:6} {0[1]:6}", p)); + EXPECT_EQ(" 42 hello ", svformat("{:6} {:6}", p)); } // Test tuples { std::tuple t { 42, "hello", 23 }; - EXPECT_EQ(" 42 hello 23", fstr("{0[0]:6} {0[1]:6} {0[2]:6}", t)); - EXPECT_EQ(" 42 hello 23", vstr("{:6} {:6} {:6}", t)); + EXPECT_EQ(" 42 hello 23", sformat("{0[0]:6} {0[1]:6} {0[2]:6}", t)); + EXPECT_EQ(" 42 hello 23", svformat("{:6} {:6} {:6}", t)); } // Test writing to stream @@ -237,26 +217,26 @@ TEST(Format, Simple) { TEST(Format, Float) { double d = 1; - EXPECT_EQ("1", fstr("{}", 1.0)); - EXPECT_EQ("0.1", fstr("{}", 0.1)); - EXPECT_EQ("0.01", fstr("{}", 0.01)); - EXPECT_EQ("0.001", fstr("{}", 0.001)); - EXPECT_EQ("0.0001", fstr("{}", 0.0001)); - EXPECT_EQ("1e-5", fstr("{}", 0.00001)); - EXPECT_EQ("1e-6", fstr("{}", 0.000001)); - - EXPECT_EQ("10", fstr("{}", 10.0)); - EXPECT_EQ("100", fstr("{}", 100.0)); - EXPECT_EQ("1000", fstr("{}", 1000.0)); - EXPECT_EQ("10000", fstr("{}", 10000.0)); - EXPECT_EQ("100000", fstr("{}", 100000.0)); - EXPECT_EQ("1e+6", fstr("{}", 1000000.0)); - EXPECT_EQ("1e+7", fstr("{}", 10000000.0)); - - EXPECT_EQ("1.00", fstr("{:.2f}", 1.0)); - EXPECT_EQ("0.10", fstr("{:.2f}", 0.1)); - EXPECT_EQ("0.01", fstr("{:.2f}", 0.01)); - EXPECT_EQ("0.00", fstr("{:.2f}", 0.001)); + EXPECT_EQ("1", sformat("{}", 1.0)); + EXPECT_EQ("0.1", sformat("{}", 0.1)); + EXPECT_EQ("0.01", sformat("{}", 0.01)); + EXPECT_EQ("0.001", sformat("{}", 0.001)); + EXPECT_EQ("0.0001", sformat("{}", 0.0001)); + EXPECT_EQ("1e-5", sformat("{}", 0.00001)); + EXPECT_EQ("1e-6", sformat("{}", 0.000001)); + + EXPECT_EQ("10", sformat("{}", 10.0)); + EXPECT_EQ("100", sformat("{}", 100.0)); + EXPECT_EQ("1000", sformat("{}", 1000.0)); + EXPECT_EQ("10000", sformat("{}", 10000.0)); + EXPECT_EQ("100000", sformat("{}", 100000.0)); + EXPECT_EQ("1e+6", sformat("{}", 1000000.0)); + EXPECT_EQ("1e+7", sformat("{}", 10000000.0)); + + EXPECT_EQ("1.00", sformat("{:.2f}", 1.0)); + EXPECT_EQ("0.10", sformat("{:.2f}", 0.1)); + EXPECT_EQ("0.01", sformat("{:.2f}", 0.01)); + EXPECT_EQ("0.00", sformat("{:.2f}", 0.001)); } TEST(Format, MultiLevel) { @@ -266,7 +246,7 @@ TEST(Format, MultiLevel) { }, }; - EXPECT_EQ("world", fstr("{[0.hello]}", v)); + EXPECT_EQ("world", sformat("{[0.hello]}", v)); } TEST(Format, dynamic) { @@ -277,24 +257,24 @@ TEST(Format, dynamic) { " \"y\": {\"a\" : 42}\n" "}"); - EXPECT_EQ("world", fstr("{0[hello]}", dyn)); - EXPECT_THROW(fstr("{0[none]}", dyn), std::out_of_range); - EXPECT_EQ("world", fstr("{0[hello]}", defaulted(dyn, "meow"))); - EXPECT_EQ("meow", fstr("{0[none]}", defaulted(dyn, "meow"))); + EXPECT_EQ("world", sformat("{0[hello]}", dyn)); + EXPECT_THROW(sformat("{0[none]}", dyn), std::out_of_range); + EXPECT_EQ("world", sformat("{0[hello]}", defaulted(dyn, "meow"))); + EXPECT_EQ("meow", sformat("{0[none]}", defaulted(dyn, "meow"))); - EXPECT_EQ("20", fstr("{0[x.0]}", dyn)); - EXPECT_THROW(fstr("{0[x.2]}", dyn), std::out_of_range); + EXPECT_EQ("20", sformat("{0[x.0]}", dyn)); + EXPECT_THROW(sformat("{0[x.2]}", dyn), std::out_of_range); // No support for "deep" defaulting (dyn["x"] is not defaulted) auto v = dyn.at("x"); - EXPECT_EQ("20", fstr("{0[0]}", v)); - EXPECT_THROW(fstr("{0[2]}", v), std::out_of_range); - EXPECT_EQ("20", fstr("{0[0]}", defaulted(v, 42))); - EXPECT_EQ("42", fstr("{0[2]}", defaulted(v, 42))); + EXPECT_EQ("20", sformat("{0[0]}", v)); + EXPECT_THROW(sformat("{0[2]}", v), std::out_of_range); + EXPECT_EQ("20", sformat("{0[0]}", defaulted(v, 42))); + EXPECT_EQ("42", sformat("{0[2]}", defaulted(v, 42))); - EXPECT_EQ("42", fstr("{0[y.a]}", dyn)); + EXPECT_EQ("42", sformat("{0[y.a]}", dyn)); - EXPECT_EQ("(null)", fstr("{}", dynamic(nullptr))); + EXPECT_EQ("(null)", sformat("{}", dynamic(nullptr))); } namespace { @@ -328,13 +308,13 @@ template <> class FormatValue { TEST(Format, Custom) { KeyValue kv { "hello", 42 }; - EXPECT_EQ("", fstr("{}", kv)); - EXPECT_EQ("", fstr("{:10}", kv)); - EXPECT_EQ("XX", fstr("{:X<23}", kv)); - EXPECT_EQ("XX", fstr("{:X>23}", kv)); - EXPECT_EQ("", fstr("{0[0]}", &kv)); - EXPECT_NE("", fstr("{}", &kv)); + EXPECT_EQ("", sformat("{}", kv)); + EXPECT_EQ("", sformat("{:10}", kv)); + EXPECT_EQ("XX", sformat("{:X<23}", kv)); + EXPECT_EQ("XX", sformat("{:X>23}", kv)); + EXPECT_EQ("", sformat("{0[0]}", &kv)); + EXPECT_NE("", sformat("{}", &kv)); } namespace { @@ -347,56 +327,56 @@ struct Opaque { TEST(Format, Unformatted) { Opaque o; - EXPECT_NE("", fstr("{}", &o)); - EXPECT_DEATH(fstr("{0[0]}", &o), "No formatter available for this type"); - EXPECT_THROW(fstrChecked("{0[0]}", &o), std::invalid_argument); + EXPECT_NE("", sformat("{}", &o)); + EXPECT_DEATH(sformat("{0[0]}", &o), "No formatter available for this type"); + EXPECT_THROW(sformatChecked("{0[0]}", &o), std::invalid_argument); } TEST(Format, Nested) { - EXPECT_EQ("1 2 3 4", fstr("{} {} {}", 1, 2, format("{} {}", 3, 4))); + EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, format("{} {}", 3, 4))); // // not copyable, must hold temporary in scope instead. auto&& saved = format("{} {}", 3, 4); - EXPECT_EQ("1 2 3 4", fstr("{} {} {}", 1, 2, saved)); + EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, saved)); } TEST(Format, OutOfBounds) { std::vector ints{1, 2, 3, 4, 5}; - EXPECT_EQ("1 3 5", fstr("{0[0]} {0[2]} {0[4]}", ints)); - EXPECT_THROW(fstr("{[5]}", ints), std::out_of_range); - EXPECT_THROW(fstrChecked("{[5]}", ints), std::out_of_range); + EXPECT_EQ("1 3 5", sformat("{0[0]} {0[2]} {0[4]}", ints)); + EXPECT_THROW(sformat("{[5]}", ints), std::out_of_range); + EXPECT_THROW(sformatChecked("{[5]}", ints), std::out_of_range); std::map map{{"hello", 0}, {"world", 1}}; - EXPECT_EQ("hello = 0", fstr("hello = {[hello]}", map)); - EXPECT_THROW(fstr("{[nope]}", map), std::out_of_range); - EXPECT_THROW(vstr("{nope}", map), std::out_of_range); - EXPECT_THROW(vstrChecked("{nope}", map), std::out_of_range); + EXPECT_EQ("hello = 0", sformat("hello = {[hello]}", map)); + EXPECT_THROW(sformat("{[nope]}", map), std::out_of_range); + EXPECT_THROW(svformat("{nope}", map), std::out_of_range); + EXPECT_THROW(svformatChecked("{nope}", map), std::out_of_range); } TEST(Format, BogusFormatString) { // format() will crash the program if the format string is invalid. - EXPECT_DEATH(fstr("}"), "single '}' in format string"); - EXPECT_DEATH(fstr("foo}bar"), "single '}' in format string"); - EXPECT_DEATH(fstr("foo{bar"), "missing ending '}'"); - EXPECT_DEATH(fstr("{[test]"), "missing ending '}'"); - EXPECT_DEATH(fstr("{-1.3}"), "argument index must be non-negative"); - EXPECT_DEATH(fstr("{1.3}", 0, 1, 2), "index not allowed"); - EXPECT_DEATH(fstr("{0} {} {1}", 0, 1, 2), + EXPECT_DEATH(sformat("}"), "single '}' in format string"); + EXPECT_DEATH(sformat("foo}bar"), "single '}' in format string"); + EXPECT_DEATH(sformat("foo{bar"), "missing ending '}'"); + EXPECT_DEATH(sformat("{[test]"), "missing ending '}'"); + EXPECT_DEATH(sformat("{-1.3}"), "argument index must be non-negative"); + EXPECT_DEATH(sformat("{1.3}", 0, 1, 2), "index not allowed"); + EXPECT_DEATH(sformat("{0} {} {1}", 0, 1, 2), "may not have both default and explicit arg indexes"); // formatChecked() should throw exceptions rather than crashing the program - EXPECT_THROW(fstrChecked("}"), std::invalid_argument); - EXPECT_THROW(fstrChecked("foo}bar"), std::invalid_argument); - EXPECT_THROW(fstrChecked("foo{bar"), std::invalid_argument); - EXPECT_THROW(fstrChecked("{[test]"), std::invalid_argument); - EXPECT_THROW(fstrChecked("{-1.3}"), std::invalid_argument); - EXPECT_THROW(fstrChecked("{1.3}", 0, 1, 2), std::invalid_argument); - EXPECT_THROW(fstrChecked("{0} {} {1}", 0, 1, 2), std::invalid_argument); + EXPECT_THROW(sformatChecked("}"), std::invalid_argument); + EXPECT_THROW(sformatChecked("foo}bar"), std::invalid_argument); + EXPECT_THROW(sformatChecked("foo{bar"), std::invalid_argument); + EXPECT_THROW(sformatChecked("{[test]"), std::invalid_argument); + EXPECT_THROW(sformatChecked("{-1.3}"), std::invalid_argument); + EXPECT_THROW(sformatChecked("{1.3}", 0, 1, 2), std::invalid_argument); + EXPECT_THROW(sformatChecked("{0} {} {1}", 0, 1, 2), std::invalid_argument); // This one fails in detail::enforceWhitespace(), which throws // std::range_error - EXPECT_DEATH(fstr("{0[test}"), "Non-whitespace: \\["); - EXPECT_THROW(fstrChecked("{0[test}"), std::exception); + EXPECT_DEATH(sformat("{0[test}"), "Non-whitespace: \\["); + EXPECT_THROW(sformatChecked("{0[test}"), std::exception); } int main(int argc, char *argv[]) {