test_locale.hpp 4.1 KB

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