1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_iterators.cpp
3 
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #include <vector>
10 #include <cstdlib> // for rand
11 #include <functional>
12 #include <sstream> // used to test stream iterators
13 #include <clocale>
14 #include <iterator> // begin
15 #include <locale> // setlocale
16 
17 #include <boost/config.hpp>
18 #ifdef BOOST_NO_STDC_NAMESPACE
19 namespace std{
20     using ::rand;
21 }
22 #endif
23 
24 #include <boost/detail/workaround.hpp>
25 #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
26 #include <boost/archive/dinkumware.hpp>
27 #endif
28 
29 #ifndef BOOST_NO_CWCHAR
30 #include <boost/archive/iterators/mb_from_wchar.hpp>
31 #include <boost/archive/iterators/wchar_from_mb.hpp>
32 #endif
33 #include <boost/archive/iterators/xml_escape.hpp>
34 #include <boost/archive/iterators/xml_unescape.hpp>
35 #include <boost/archive/iterators/transform_width.hpp>
36 #include <boost/archive/iterators/istream_iterator.hpp>
37 #include <boost/archive/iterators/ostream_iterator.hpp>
38 
39 #include "test_tools.hpp"
40 
41 #ifndef BOOST_NO_CWCHAR
42 
test_wchar_from_mb(const wchar_t * la,const char * a,const unsigned int size)43 void test_wchar_from_mb(const wchar_t *la, const char * a, const unsigned int size){
44     typedef boost::archive::iterators::wchar_from_mb<const char *> translator;
45     BOOST_CHECK((
46         std::equal(
47             translator(a),
48             translator(a + size),
49             la
50         )
51     ));
52 }
53 
test_mb_from_wchar(const char * a,const wchar_t * la,const unsigned int size)54 void test_mb_from_wchar(const char * a, const wchar_t *la, const unsigned int size){
55     typedef boost::archive::iterators::mb_from_wchar<const wchar_t *> translator;
56     BOOST_CHECK(
57         std::equal(
58             translator(la),
59             translator(la + size),
60             a
61         )
62     );
63 }
64 
test_roundtrip(const wchar_t * la)65 void test_roundtrip(const wchar_t * la){
66     std::size_t s = std::wcslen(la);
67     std::vector<char> a;
68     {
69         typedef boost::archive::iterators::mb_from_wchar<const wchar_t *> translator;
70         std::copy(
71             translator(la),
72             translator(la + s),
73             std::back_inserter(a)
74         );
75         // note: wchar_from_mb NEEDS a termination null in order to function!
76         a.push_back(static_cast<char>(0));
77     }
78     BOOST_CHECK(a.size() > 0);
79     std::vector<wchar_t> la2;
80     {
81         typedef boost::archive::iterators::wchar_from_mb<std::vector<char>::const_iterator> translator;
82         std::copy(
83             translator(a.begin()),
84             translator(),
85             std::back_inserter(la2)
86         );
87     }
88     BOOST_CHECK(la2.size() == s);
89     BOOST_CHECK(std::equal(la, la + s, la2.begin()));
90 }
91 #endif
92 
93 template<class CharType>
test_xml_escape(const CharType * xml_escaped,const CharType * xml,unsigned int size)94 void test_xml_escape(
95     const CharType * xml_escaped,
96     const CharType * xml,
97     unsigned int size
98 ){
99     typedef boost::archive::iterators::xml_escape<const CharType *> translator;
100 
101     BOOST_CHECK(
102         std::equal(
103             translator(xml),
104             translator(xml + size),
105             xml_escaped
106         )
107     );
108 }
109 
110 template<class CharType>
test_xml_unescape(const CharType * xml,const CharType * xml_escaped,unsigned int size)111 void test_xml_unescape(
112     const CharType * xml,
113     const CharType * xml_escaped,
114     unsigned int size
115 ){
116 
117     // test xml_unescape
118     typedef boost::archive::iterators::xml_unescape<const CharType *> translator;
119 
120     BOOST_CHECK(
121         std::equal(
122             translator(xml_escaped),
123             translator(xml_escaped + size),
124             xml
125         )
126     );
127 }
128 
129 template<int BitsOut, int BitsIn>
test_transform_width(unsigned int size)130 void test_transform_width(unsigned int size){
131     // test transform_width
132     char rawdata[8];
133 
134     char * rptr;
135     for(rptr = rawdata + size; rptr-- > rawdata;)
136         *rptr = static_cast<char>(0xff & std::rand());
137 
138     // convert 8 to 6 bit characters
139     typedef boost::archive::iterators::transform_width<
140         char *, BitsOut, BitsIn
141     > translator1;
142 
143     std::vector<char> vout;
144 
145     std::copy(
146         translator1(static_cast<char *>(rawdata)),
147         translator1(rawdata + size),
148         std::back_inserter(vout)
149     );
150 
151     // check to see we got the expected # of characters out
152     if(0 ==  size)
153         BOOST_CHECK(vout.size() == 0);
154     else
155         BOOST_CHECK(vout.size() == (size * BitsIn - 1 ) / BitsOut + 1);
156 
157     typedef boost::archive::iterators::transform_width<
158         std::vector<char>::iterator, BitsIn, BitsOut
159     > translator2;
160 
161     std::vector<char> vin;
162     std::copy(
163         translator2(vout.begin()),
164         translator2(vout.end()),
165         std::back_inserter(vin)
166     );
167 
168     // check to see we got the expected # of characters out
169     BOOST_CHECK(vin.size() == size);
170 
171     BOOST_CHECK(
172         std::equal(
173             rawdata,
174             rawdata + size,
175             vin.begin()
176         )
177     );
178 }
179 
180 template<class CharType>
test_stream_iterators(const CharType * test_data,unsigned int size)181 void test_stream_iterators(
182     const CharType * test_data,
183     unsigned int size
184 ){
185     std::basic_stringstream<CharType> ss;
186     boost::archive::iterators::ostream_iterator<CharType> osi =
187         boost::archive::iterators::ostream_iterator<CharType>(ss);
188     std::copy(test_data, test_data + size, osi);
189 
190     BOOST_CHECK(size == ss.str().size());
191 
192     boost::archive::iterators::istream_iterator<CharType> isi =
193         boost::archive::iterators::istream_iterator<CharType>(ss);
194     BOOST_CHECK(std::equal(test_data, test_data + size,isi));
195 }
196 
197 int
test_main(int,char * [])198 test_main(int /* argc */, char* /* argv */ [] )
199 {
200     const char xml[] = "<+>+&+\"+'";
201     const char xml_escaped[] = "&lt;+&gt;+&amp;+&quot;+&apos;";
202     test_xml_escape<const char>(
203         xml_escaped,
204         xml,
205         sizeof(xml) / sizeof(char) - 1
206     );
207     test_xml_unescape<const char>(
208         xml,
209         xml_escaped,
210         sizeof(xml_escaped) / sizeof(char) - 1
211     );
212 
213 
214     #ifndef BOOST_NO_CWCHAR
215     const wchar_t wxml[] = L"<+>+&+\"+'";
216     const wchar_t wxml_escaped[] = L"&lt;+&gt;+&amp;+&quot;+&apos;";
217     test_xml_escape<const wchar_t>(
218         wxml_escaped,
219         wxml,
220         sizeof(wxml) / sizeof(wchar_t) - 1
221     );
222     test_xml_unescape<const wchar_t>(
223         wxml,
224         wxml_escaped,
225         sizeof(wxml_escaped) / sizeof(wchar_t) - 1
226     );
227 
228     const char b[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
229     const wchar_t lb[] = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
230     test_mb_from_wchar(b, lb, sizeof(lb) / sizeof(wchar_t) - 1);
231     test_wchar_from_mb(lb, b, sizeof(b) / sizeof(char) - 1);
232 
233     const char a[] = "abcdefghijklmnopqrstuvwxyz";
234     const wchar_t la[] = L"abcdefghijklmnopqrstuvwxyz";
235     test_mb_from_wchar(a, la, sizeof(la) / sizeof(wchar_t) - 1);
236     test_wchar_from_mb(la, a, sizeof(a) / sizeof(char) - 1);
237 
238     test_roundtrip(L"z\u00df\u6c34\U0001f34c");
239 
240     test_stream_iterators<wchar_t>(la, sizeof(la)/sizeof(wchar_t) - 1);
241     #endif
242 
243     test_stream_iterators<char>(a, sizeof(a) - 1);
244 
245     test_transform_width<6, 8>(0);
246     test_transform_width<6, 8>(1);
247     test_transform_width<6, 8>(2);
248     test_transform_width<6, 8>(3);
249     test_transform_width<6, 8>(4);
250     test_transform_width<6, 8>(5);
251     test_transform_width<6, 8>(6);
252     test_transform_width<6, 8>(7);
253     test_transform_width<6, 8>(8);
254 
255     return EXIT_SUCCESS;
256 }
257