1 //
2 //  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See
5 //  accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #ifndef BOOST_LOCALE_TEST_H
10 #define BOOST_LOCALE_TEST_H
11 #include <stdexcept>
12 #include <sstream>
13 #include <iostream>
14 #include <iomanip>
15 #include <cstdlib>
16 #include <string>
17 
18 int error_counter=0;
19 int test_counter=0;
20 
21 #ifndef BOOST_LOCALE_ERROR_LIMIT
22 #define BOOST_LOCALE_ERROR_LIMIT 20
23 #endif
24 
25 
26 #define THROW_IF_TOO_BIG(X)                                                     \
27 do {                                                                            \
28     if((X) > BOOST_LOCALE_ERROR_LIMIT)                                          \
29         throw std::runtime_error("Error limits reached, stopping unit test");   \
30 }while(0)
31 
32 #define TEST(X)                                                         \
33     do {                                                                \
34         test_counter++;                                                 \
35         if(X) break;                                                    \
36         std::cerr << "Error in line:"<<__LINE__ << " "#X  << std::endl; \
37         THROW_IF_TOO_BIG(error_counter++);                              \
38     }while(0)
39 #endif
40 
41 #define TEST_THROWS(X,E)                                                \
42     do {                                                                \
43         test_counter++;                                                 \
44         try { X; } catch(E const &/*e*/ ) {break;} catch(...){}         \
45         std::cerr << "Error in line:"<<__LINE__ << " "#X  << std::endl; \
46         THROW_IF_TOO_BIG(error_counter++);                              \
47     }while(0)
48 
49 #define FINALIZE()                                                      \
50     do {                                                                \
51         int passed=test_counter - error_counter;                        \
52         std::cout << std::endl;                                         \
53         std::cout << "Passed "<<passed<<" tests" << std::endl;          \
54         if(error_counter >0 ) {                                         \
55             std::cout << "Failed "<<error_counter<<" tests"<<std::endl; \
56         }                                                               \
57         std::cout <<" "<< std::fixed << std::setprecision(1)            \
58                 << std::setw(5) << 100.0 * passed / test_counter <<     \
59                 "% of tests completed sucsessefully" << std::endl;      \
60         return error_counter == 0 ? EXIT_SUCCESS : EXIT_FAILURE ;       \
61     }while(0)
62 
63 
utf8_next(std::string const & s,unsigned & pos)64 inline unsigned utf8_next(std::string const &s,unsigned &pos)
65 {
66     unsigned c=(unsigned char)s[pos++];
67     if( (unsigned char)(c - 0xc0) >= 0x35)
68         return c;
69     unsigned l;
70     if(c < 192)
71         l = 0;
72     else if(c < 224)
73         l = 1;
74     else if(c < 240)
75         l = 2;
76     else
77         l = 3;
78 
79     c&=(1<<(6-l))-1;
80 
81     switch(l) {
82     case 3:
83         c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F);
84     case 2:
85         c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F);
86     case 1:
87         c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F);
88     }
89     return c;
90 }
91 
92 template<typename Char>
to(std::string const & utf8)93 std::basic_string<Char> to(std::string const &utf8)
94 {
95     std::basic_string<Char> out;
96     unsigned i=0;
97     while(i<utf8.size()) {
98         unsigned point;
99         unsigned prev=i;
100         point = utf8_next(utf8,i);
101         if(sizeof(Char)==1 && point > 255) {
102             std::ostringstream ss;
103             ss << "Can't convert codepoint U" << std::hex << point <<"(" <<std::string(utf8.begin()+prev,utf8.begin()+i)<<") to Latin1";
104             throw std::runtime_error(ss.str());
105         }
106         else if(sizeof(Char)==2 && point >0xFFFF) { // Deal with surragates
107             point-=0x10000;
108             out+=static_cast<Char>(0xD800 | (point>>10));
109             out+=static_cast<Char>(0xDC00 | (point & 0x3FF));
110             continue;
111         }
112         out+=static_cast<Char>(point);
113     }
114     return out;
115 }
116 
117 
118 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
119