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