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>
11using namespace boost::program_options;
12// We'll use po::value everywhere to workaround vc6 bug.
13namespace po = boost::program_options;
14
15#include <boost/function.hpp>
16using namespace boost;
17
18#include <sstream>
19using namespace std;
20
21#include "minitest.hpp"
22
23// Test that unicode input is forwarded to unicode option without
24// problems.
25void 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(x: 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(options: parsed, m&: 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.
49void 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(loc: 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(x: L"--foo=\x044F");
63
64 variables_map vm;
65 store(options: wcommand_line_parser(args).options(desc).run(), m&: vm);
66
67 BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
68}
69
70void 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(loc: 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(x: "--foo=\xD1\x8F");
84
85 variables_map vm;
86 store(options: command_line_parser(args).options(desc).run(), m&: vm);
87
88 BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
89}
90
91vector<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(x: array[i]);
96 return r;
97}
98
99void 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
106void 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(array: cmdline4_,
120 size: 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(option: a4[0], name: "foo", value: L"1\u0FF52");
127 check_value(option: a4[1], name: "foo", value: L"4");
128 check_value(option: a4[2], name: "bar", value: L"11");
129 check_value(option: a4[4], name: "qux", value: 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.
135void 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(loc: 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(options: parse_config_file(stream, desc), m&: vm);
151
152 BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
153}
154
155int 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

source code of boost/libs/program_options/test/unicode_test.cpp