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)64inline 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)93std::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