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