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