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