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