unicode_test.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright Vladimir Prus 2002-2004.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include <boost/program_options/variables_map.hpp>
  6. #include <boost/program_options/options_description.hpp>
  7. #include <boost/program_options/parsers.hpp>
  8. #include <boost/program_options/detail/utf8_codecvt_facet.hpp>
  9. using namespace boost::program_options;
  10. // We'll use po::value everywhere to workaround vc6 bug.
  11. namespace po = boost::program_options;
  12. #include <boost/function.hpp>
  13. using namespace boost;
  14. #include <sstream>
  15. using namespace std;
  16. #include "minitest.hpp"
  17. // Test that unicode input is forwarded to unicode option without
  18. // problems.
  19. void test_unicode_to_unicode()
  20. {
  21. options_description desc;
  22. desc.add_options()
  23. ("foo", po::wvalue<wstring>(), "unicode option")
  24. ;
  25. vector<wstring> args;
  26. args.push_back(L"--foo=\x044F");
  27. variables_map vm;
  28. basic_parsed_options<wchar_t> parsed =
  29. wcommand_line_parser(args).options(desc).run();
  30. store(parsed, vm);
  31. BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
  32. BOOST_CHECK(parsed.options[0].original_tokens.size() == 1);
  33. BOOST_CHECK(parsed.options[0].original_tokens[0] == L"--foo=\x044F");
  34. }
  35. // Test that unicode input is property converted into
  36. // local 8 bit string. To test this, make local 8 bit encoding
  37. // be utf8.
  38. void test_unicode_to_native()
  39. {
  40. std::codecvt<wchar_t, char, mbstate_t>* facet =
  41. new boost::program_options::detail::utf8_codecvt_facet;
  42. locale::global(locale(locale(), facet));
  43. options_description desc;
  44. desc.add_options()
  45. ("foo", po::value<string>(), "unicode option")
  46. ;
  47. vector<wstring> args;
  48. args.push_back(L"--foo=\x044F");
  49. variables_map vm;
  50. store(wcommand_line_parser(args).options(desc).run(), vm);
  51. BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
  52. }
  53. void test_native_to_unicode()
  54. {
  55. std::codecvt<wchar_t, char, mbstate_t>* facet =
  56. new boost::program_options::detail::utf8_codecvt_facet;
  57. locale::global(locale(locale(), facet));
  58. options_description desc;
  59. desc.add_options()
  60. ("foo", po::wvalue<wstring>(), "unicode option")
  61. ;
  62. vector<string> args;
  63. args.push_back("--foo=\xD1\x8F");
  64. variables_map vm;
  65. store(command_line_parser(args).options(desc).run(), vm);
  66. BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
  67. }
  68. vector<wstring> sv(const wchar_t* array[], unsigned size)
  69. {
  70. vector<wstring> r;
  71. for (unsigned i = 0; i < size; ++i)
  72. r.push_back(array[i]);
  73. return r;
  74. }
  75. void check_value(const woption& option, const char* name, const wchar_t* value)
  76. {
  77. BOOST_CHECK(option.string_key == name);
  78. BOOST_REQUIRE(option.value.size() == 1);
  79. BOOST_CHECK(option.value.front() == value);
  80. }
  81. void test_command_line()
  82. {
  83. options_description desc;
  84. desc.add_options()
  85. ("foo,f", new untyped_value(), "")
  86. // Explicit qualification is a workaround for vc6
  87. ("bar,b", po::value<std::string>(), "")
  88. ("baz", new untyped_value())
  89. ("qux,plug*", new untyped_value())
  90. ;
  91. const wchar_t* cmdline4_[] = { L"--foo=1\u0FF52", L"-f4", L"--bar=11",
  92. L"-b4", L"--plug3=10"};
  93. vector<wstring> cmdline4 = sv(cmdline4_,
  94. sizeof(cmdline4_)/sizeof(cmdline4_[0]));
  95. vector<woption> a4 =
  96. wcommand_line_parser(cmdline4).options(desc).run().options;
  97. BOOST_REQUIRE(a4.size() == 5);
  98. check_value(a4[0], "foo", L"1\u0FF52");
  99. check_value(a4[1], "foo", L"4");
  100. check_value(a4[2], "bar", L"11");
  101. check_value(a4[4], "qux", L"10");
  102. }
  103. // Since we've already tested conversion between parser encoding and
  104. // option encoding, all we need to check for config file is that
  105. // when reading wistream, it generates proper UTF8 data.
  106. void test_config_file()
  107. {
  108. std::codecvt<wchar_t, char, mbstate_t>* facet =
  109. new boost::program_options::detail::utf8_codecvt_facet;
  110. locale::global(locale(locale(), facet));
  111. options_description desc;
  112. desc.add_options()
  113. ("foo", po::value<string>(), "unicode option")
  114. ;
  115. std::wstringstream stream(L"foo = \x044F");
  116. variables_map vm;
  117. store(parse_config_file(stream, desc), vm);
  118. BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
  119. }
  120. int main(int, char* [])
  121. {
  122. test_unicode_to_unicode();
  123. test_unicode_to_native();
  124. test_native_to_unicode();
  125. test_command_line();
  126. test_config_file();
  127. return 0;
  128. }