• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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