1 // Formatting library for C++ - scanning API test
2 //
3 // Copyright (c) 2019 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #include "scan.h"
9
10 #include <time.h>
11
12 #include <climits>
13
14 #include "gmock.h"
15 #include "gtest-extra.h"
16
TEST(ScanTest,ReadText)17 TEST(ScanTest, ReadText) {
18 fmt::string_view s = "foo";
19 auto end = fmt::scan(s, "foo");
20 EXPECT_EQ(end, s.end());
21 EXPECT_THROW_MSG(fmt::scan("fob", "foo"), fmt::format_error, "invalid input");
22 }
23
TEST(ScanTest,ReadInt)24 TEST(ScanTest, ReadInt) {
25 int n = 0;
26 fmt::scan("42", "{}", n);
27 EXPECT_EQ(n, 42);
28 fmt::scan("-42", "{}", n);
29 EXPECT_EQ(n, -42);
30 }
31
TEST(ScanTest,ReadLongLong)32 TEST(ScanTest, ReadLongLong) {
33 long long n = 0;
34 fmt::scan("42", "{}", n);
35 EXPECT_EQ(n, 42);
36 fmt::scan("-42", "{}", n);
37 EXPECT_EQ(n, -42);
38 }
39
TEST(ScanTest,ReadUInt)40 TEST(ScanTest, ReadUInt) {
41 unsigned n = 0;
42 fmt::scan("42", "{}", n);
43 EXPECT_EQ(n, 42);
44 EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
45 "invalid input");
46 }
47
TEST(ScanTest,ReadULongLong)48 TEST(ScanTest, ReadULongLong) {
49 unsigned long long n = 0;
50 fmt::scan("42", "{}", n);
51 EXPECT_EQ(n, 42);
52 EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
53 "invalid input");
54 }
55
TEST(ScanTest,ReadString)56 TEST(ScanTest, ReadString) {
57 std::string s;
58 fmt::scan("foo", "{}", s);
59 EXPECT_EQ(s, "foo");
60 }
61
TEST(ScanTest,ReadStringView)62 TEST(ScanTest, ReadStringView) {
63 fmt::string_view s;
64 fmt::scan("foo", "{}", s);
65 EXPECT_EQ(s, "foo");
66 }
67
68 #ifndef _WIN32
69 namespace fmt {
70 template <> struct scanner<tm> {
71 std::string format;
72
parsefmt::scanner73 scan_parse_context::iterator parse(scan_parse_context& ctx) {
74 auto it = ctx.begin();
75 if (it != ctx.end() && *it == ':') ++it;
76 auto end = it;
77 while (end != ctx.end() && *end != '}') ++end;
78 format.reserve(detail::to_unsigned(end - it + 1));
79 format.append(it, end);
80 format.push_back('\0');
81 return end;
82 }
83
84 template <class ScanContext>
scanfmt::scanner85 typename ScanContext::iterator scan(tm& t, ScanContext& ctx) {
86 auto result = strptime(ctx.begin(), format.c_str(), &t);
87 if (!result) throw format_error("failed to parse time");
88 return result;
89 }
90 };
91 } // namespace fmt
92
TEST(ScanTest,ReadCustom)93 TEST(ScanTest, ReadCustom) {
94 const char* input = "Date: 1985-10-25";
95 auto t = tm();
96 fmt::scan(input, "Date: {0:%Y-%m-%d}", t);
97 EXPECT_EQ(t.tm_year, 85);
98 EXPECT_EQ(t.tm_mon, 9);
99 EXPECT_EQ(t.tm_mday, 25);
100 }
101 #endif
102
TEST(ScanTest,InvalidFormat)103 TEST(ScanTest, InvalidFormat) {
104 EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error,
105 "argument index out of range");
106 EXPECT_THROW_MSG(fmt::scan("", "{"), fmt::format_error,
107 "invalid format string");
108 }
109
TEST(ScanTest,Example)110 TEST(ScanTest, Example) {
111 std::string key;
112 int value;
113 fmt::scan("answer = 42", "{} = {}", key, value);
114 EXPECT_EQ(key, "answer");
115 EXPECT_EQ(value, 42);
116 }
117