1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11
10 // UNSUPPORTED: no-localization
11 // UNSUPPORTED: !stdlib=libc++ && c++14
12 
13 // <iomanip>
14 
15 // quoted
16 
17 #include <iomanip>
18 #include <sstream>
19 #include <string_view>
20 #include <cassert>
21 
22 #include "test_macros.h"
23 
is_skipws(const std::istream * is)24 bool is_skipws(const std::istream* is) { return (is->flags() & std::ios_base::skipws) != 0; }
25 
26 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
is_skipws(const std::wistream * is)27 bool is_skipws(const std::wistream* is) { return (is->flags() & std::ios_base::skipws) != 0; }
28 #endif
29 
round_trip(const char * p)30 void round_trip(const char* p) {
31   std::stringstream ss;
32   bool skippingws = is_skipws(&ss);
33   std::string_view sv{p};
34 
35   ss << std::quoted(sv);
36   std::string s;
37   ss >> std::quoted(s);
38   assert(s == sv);
39   assert(skippingws == is_skipws(&ss));
40 }
41 
round_trip_ws(const char * p)42 void round_trip_ws(const char* p) {
43   std::stringstream ss;
44   std::noskipws(ss);
45   bool skippingws = is_skipws(&ss);
46   std::string_view sv{p};
47 
48   ss << std::quoted(sv);
49   std::string s;
50   ss >> std::quoted(s);
51   assert(s == sv);
52   assert(skippingws == is_skipws(&ss));
53 }
54 
round_trip_d(const char * p,char delim)55 void round_trip_d(const char* p, char delim) {
56   std::stringstream ss;
57   std::string_view sv{p};
58 
59   ss << std::quoted(sv, delim);
60   std::string s;
61   ss >> std::quoted(s, delim);
62   assert(s == sv);
63 }
64 
round_trip_e(const char * p,char escape)65 void round_trip_e(const char* p, char escape) {
66   std::stringstream ss;
67   std::string_view sv{p};
68 
69   ss << std::quoted(sv, '"', escape);
70   std::string s;
71   ss >> std::quoted(s, '"', escape);
72   assert(s == sv);
73 }
74 
quote(const char * p,char delim='"',char escape='\\\\')75 std::string quote(const char* p, char delim = '"', char escape = '\\') {
76   std::stringstream ss;
77   ss << std::quoted(p, delim, escape);
78   std::string s;
79   ss >> s; // no quote
80   return s;
81 }
82 
unquote(const char * p,char delim='"',char escape='\\\\')83 std::string unquote(const char* p, char delim = '"', char escape = '\\') {
84   std::stringstream ss;
85   ss << p;
86   std::string s;
87   ss >> std::quoted(s, delim, escape);
88   return s;
89 }
90 
91 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
round_trip(const wchar_t * p)92 void round_trip(const wchar_t* p) {
93   std::wstringstream ss;
94   bool skippingws = is_skipws(&ss);
95   std::wstring_view sv{p};
96 
97   ss << std::quoted(sv);
98   std::wstring s;
99   ss >> std::quoted(s);
100   assert(s == sv);
101   assert(skippingws == is_skipws(&ss));
102 }
103 
round_trip_ws(const wchar_t * p)104 void round_trip_ws(const wchar_t* p) {
105   std::wstringstream ss;
106   std::noskipws(ss);
107   bool skippingws = is_skipws(&ss);
108   std::wstring_view sv{p};
109 
110   ss << std::quoted(sv);
111   std::wstring s;
112   ss >> std::quoted(s);
113   assert(s == sv);
114   assert(skippingws == is_skipws(&ss));
115 }
116 
round_trip_d(const wchar_t * p,wchar_t delim)117 void round_trip_d(const wchar_t* p, wchar_t delim) {
118   std::wstringstream ss;
119   std::wstring_view sv{p};
120 
121   ss << std::quoted(sv, delim);
122   std::wstring s;
123   ss >> std::quoted(s, delim);
124   assert(s == sv);
125 }
126 
round_trip_e(const wchar_t * p,wchar_t escape)127 void round_trip_e(const wchar_t* p, wchar_t escape) {
128   std::wstringstream ss;
129   std::wstring_view sv{p};
130 
131   ss << std::quoted(sv, wchar_t('"'), escape);
132   std::wstring s;
133   ss >> std::quoted(s, wchar_t('"'), escape);
134   assert(s == sv);
135 }
136 
quote(const wchar_t * p,wchar_t delim='"',wchar_t escape='\\\\')137 std::wstring quote(const wchar_t* p, wchar_t delim = '"', wchar_t escape = '\\') {
138   std::wstringstream ss;
139   std::wstring_view sv{p};
140 
141   ss << std::quoted(sv, delim, escape);
142   std::wstring s;
143   ss >> s; // no quote
144   return s;
145 }
146 
unquote(const wchar_t * p,wchar_t delim='"',wchar_t escape='\\\\')147 std::wstring unquote(const wchar_t* p, wchar_t delim = '"', wchar_t escape = '\\') {
148   std::wstringstream ss;
149   std::wstring_view sv{p};
150 
151   ss << sv;
152   std::wstring s;
153   ss >> std::quoted(s, delim, escape);
154   return s;
155 }
156 #endif // TEST_HAS_NO_WIDE_CHARACTERS
157 
main(int,char **)158 int main(int, char**) {
159   round_trip("");
160   round_trip_ws("");
161   round_trip_d("", 'q');
162   round_trip_e("", 'q');
163 
164 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
165   round_trip(L"");
166   round_trip_ws(L"");
167   round_trip_d(L"", 'q');
168   round_trip_e(L"", 'q');
169 #endif
170 
171   round_trip("Hi");
172   round_trip_ws("Hi");
173   round_trip_d("Hi", '!');
174   round_trip_e("Hi", '!');
175   assert(quote("Hi", '!') == "!Hi!");
176   assert(quote("Hi!", '!') == R"(!Hi\!!)");
177 
178 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
179   round_trip(L"Hi");
180   round_trip_ws(L"Hi");
181   round_trip_d(L"Hi", '!');
182   round_trip_e(L"Hi", '!');
183   assert(quote(L"Hi", '!') == L"!Hi!");
184   assert(quote(L"Hi!", '!') == LR"(!Hi\!!)");
185 #endif
186 
187   round_trip("Hi Mom");
188   round_trip_ws("Hi Mom");
189 
190 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
191   round_trip(L"Hi Mom");
192   round_trip_ws(L"Hi Mom");
193 #endif
194 
195   assert(quote("") == "\"\"");
196   assert(quote("a") == "\"a\"");
197 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
198   assert(quote(L"") == L"\"\"");
199   assert(quote(L"a") == L"\"a\"");
200 #endif
201 
202   // missing end quote - must not hang
203   assert(unquote("\"abc") == "abc");
204   assert(unquote("abc") == "abc");     // no delimiter
205   assert(unquote("abc def") == "abc"); // no delimiter
206   assert(unquote("") == "");           // nothing there
207 
208 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
209   assert(unquote(L"\"abc") == L"abc");
210   assert(unquote(L"abc") == L"abc");     // no delimiter
211   assert(unquote(L"abc def") == L"abc"); // no delimiter
212   assert(unquote(L"") == L"");           // nothing there
213 #endif
214 
215   return 0;
216 }
217