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>
17#include <cassert>
18
19#include "test_macros.h"
20
21#if TEST_STD_VER > 11
22
23template <class CharT, class Traits>
24bool is_skipws ( const std::basic_istream<CharT, Traits>& is ) {
25    return ( is.flags() & std::ios_base::skipws ) != 0;
26    }
27
28template <class CharT, class Traits = std::char_traits<CharT>>
29void both_ways ( const CharT *p ) {
30    std::basic_string<CharT, Traits> str(p);
31    auto q = std::quoted(str);
32
33    std::basic_stringstream<CharT, Traits> ss;
34    bool skippingws = is_skipws ( ss );
35    ((void)skippingws); // Prevent unused warning
36    ss << q;
37    ss >> q;
38    }
39
40template <class CharT, class Traits = std::char_traits<CharT>>
41void round_trip ( const CharT *p ) {
42    std::basic_stringstream<CharT, Traits> ss;
43    bool skippingws = is_skipws ( ss );
44
45    ss << std::quoted(p);
46    std::basic_string<CharT, Traits> s;
47    ss >> std::quoted(s);
48    assert ( s == p );
49    assert ( skippingws == is_skipws ( ss ));
50    }
51
52
53template <class CharT, class Traits = std::char_traits<CharT>>
54void round_trip_ws ( const CharT *p ) {
55    std::basic_stringstream<CharT, Traits> ss;
56    std::noskipws ( ss );
57    bool skippingws = is_skipws ( ss );
58
59    ss << std::quoted(p);
60    std::basic_string<CharT, Traits> s;
61    ss >> std::quoted(s);
62    assert ( s == p );
63    assert ( skippingws == is_skipws ( ss ));
64    }
65
66template <class CharT, class Traits = std::char_traits<CharT>>
67void round_trip_d ( const CharT *p, char delim ) {
68    std::basic_stringstream<CharT, Traits> ss;
69    CharT d(delim);
70
71    ss << std::quoted(p, d);
72    std::basic_string<CharT, Traits> s;
73    ss >> std::quoted(s, d);
74    assert ( s == p );
75    }
76
77template <class CharT, class Traits = std::char_traits<CharT>>
78void round_trip_e ( const CharT *p, char escape ) {
79    std::basic_stringstream<CharT, Traits> ss;
80    CharT e(escape);
81
82    ss << std::quoted(p, CharT('"'), e );
83    std::basic_string<CharT, Traits> s;
84    ss >> std::quoted(s, CharT('"'), e );
85    assert ( s == p );
86    }
87
88
89template <class CharT, class Traits = std::char_traits<CharT>>
90std::basic_string<CharT, Traits> quote ( const CharT *p, char delim='"', char escape='\\' ) {
91    std::basic_stringstream<CharT, Traits> ss;
92    CharT d(delim);
93    CharT e(escape);
94    ss << std::quoted(p, d, e);
95    std::basic_string<CharT, Traits> s;
96    ss >> s;    // no quote
97    return s;
98}
99
100template <class CharT, class Traits = std::char_traits<CharT>>
101std::basic_string<CharT, Traits> unquote ( const CharT *p, char delim='"', char escape='\\' ) {
102    std::basic_stringstream<CharT, Traits> ss;
103    ss << p;
104
105    CharT d(delim);
106    CharT e(escape);
107    std::basic_string<CharT, Traits> s;
108    ss >> std::quoted(s, d, e);
109    return s;
110}
111
112void test_padding () {
113    {
114    std::stringstream ss;
115    ss << std::left << std::setw(10) << std::setfill('!') << std::quoted("abc", '`');
116    assert ( ss.str() == "`abc`!!!!!" );
117    }
118
119    {
120    std::stringstream ss;
121    ss << std::right << std::setw(10) << std::setfill('!') << std::quoted("abc", '`');
122    assert ( ss.str() == "!!!!!`abc`" );
123    }
124}
125
126
127int main()
128{
129    both_ways ( "" );   // This is a compilation check
130
131    round_trip    (  "" );
132    round_trip_ws (  "" );
133    round_trip_d  (  "", 'q' );
134    round_trip_e  (  "", 'q' );
135
136    round_trip    ( L"" );
137    round_trip_ws ( L"" );
138    round_trip_d  ( L"", 'q' );
139    round_trip_e  ( L"", 'q' );
140
141    round_trip    (  "Hi" );
142    round_trip_ws (  "Hi" );
143    round_trip_d  (  "Hi", '!' );
144    round_trip_e  (  "Hi", '!' );
145    assert ( quote ( "Hi", '!' ) == "!Hi!" );
146    assert ( quote ( "Hi!", '!' ) == R"(!Hi\!!)" );
147
148    round_trip    ( L"Hi" );
149    round_trip_ws ( L"Hi" );
150    round_trip_d  ( L"Hi", '!' );
151    round_trip_e  ( L"Hi", '!' );
152    assert ( quote ( L"Hi", '!' )  == L"!Hi!" );
153    assert ( quote ( L"Hi!", '!' ) == LR"(!Hi\!!)" );
154
155    round_trip    (  "Hi Mom" );
156    round_trip_ws (  "Hi Mom" );
157    round_trip    ( L"Hi Mom" );
158    round_trip_ws ( L"Hi Mom" );
159
160    assert ( quote (  "" )  ==  "\"\"" );
161    assert ( quote ( L"" )  == L"\"\"" );
162    assert ( quote (  "a" ) ==  "\"a\"" );
163    assert ( quote ( L"a" ) == L"\"a\"" );
164
165//  missing end quote - must not hang
166    assert ( unquote (  "\"abc" ) ==  "abc" );
167    assert ( unquote ( L"\"abc" ) == L"abc" );
168
169    assert ( unquote (  "abc" ) == "abc" ); // no delimiter
170    assert ( unquote ( L"abc" ) == L"abc" ); // no delimiter
171    assert ( unquote (  "abc def" ) ==  "abc" ); // no delimiter
172    assert ( unquote ( L"abc def" ) == L"abc" ); // no delimiter
173
174    assert ( unquote (  "" ) ==  "" ); // nothing there
175    assert ( unquote ( L"" ) == L"" ); // nothing there
176    test_padding ();
177    }
178
179#else
180int main() {}
181#endif
182