Skip to content

Commit f46a707

Browse files
authored
Merge pull request #29 from DDRBoxman/unicode
Fix building under OSX after unicode file handling broke it
2 parents ebcb12f + 4f12df3 commit f46a707

18 files changed

+2308
-9
lines changed

nowide/args.hpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
//
2+
// Copyright (c) 2012 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 NOWIDE_ARGS_HPP_INCLUDED
9+
#define NOWIDE_ARGS_HPP_INCLUDED
10+
11+
#include <nowide/config.hpp>
12+
#include <nowide/stackstring.hpp>
13+
#include <vector>
14+
#ifdef NOWIDE_WINDOWS
15+
#include <nowide/windows.hpp>
16+
#endif
17+
18+
19+
namespace nowide {
20+
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
21+
class args {
22+
public:
23+
args(int &,char **&) {}
24+
args(int &,char **&,char **&){}
25+
~args() {}
26+
};
27+
28+
#else
29+
30+
///
31+
/// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under
32+
/// Microsoft Windows.
33+
///
34+
/// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW()
35+
/// in order to obtain the information. It does not relates to actual values of argc,argv and env
36+
/// under Windows.
37+
///
38+
/// It restores the original values in its destructor
39+
///
40+
/// \note the class owns the memory of the newly allocated strings
41+
///
42+
class args {
43+
public:
44+
45+
///
46+
/// Fix command line agruments
47+
///
48+
args(int &argc,char **&argv) :
49+
old_argc_(argc),
50+
old_argv_(argv),
51+
old_env_(0),
52+
old_argc_ptr_(&argc),
53+
old_argv_ptr_(&argv),
54+
old_env_ptr_(0)
55+
{
56+
fix_args(argc,argv);
57+
}
58+
///
59+
/// Fix command line agruments and environment
60+
///
61+
args(int &argc,char **&argv,char **&en) :
62+
old_argc_(argc),
63+
old_argv_(argv),
64+
old_env_(en),
65+
old_argc_ptr_(&argc),
66+
old_argv_ptr_(&argv),
67+
old_env_ptr_(&en)
68+
{
69+
fix_args(argc,argv);
70+
fix_env(en);
71+
}
72+
///
73+
/// Restore original argc,argv,env values, if changed
74+
///
75+
~args()
76+
{
77+
if(old_argc_ptr_)
78+
*old_argc_ptr_ = old_argc_;
79+
if(old_argv_ptr_)
80+
*old_argv_ptr_ = old_argv_;
81+
if(old_env_ptr_)
82+
*old_env_ptr_ = old_env_;
83+
}
84+
private:
85+
void fix_args(int &argc,char **&argv)
86+
{
87+
int wargc;
88+
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc);
89+
if(!wargv) {
90+
argc = 0;
91+
static char *dummy = 0;
92+
argv = &dummy;
93+
return;
94+
}
95+
try{
96+
args_.resize(wargc+1,0);
97+
arg_values_.resize(wargc);
98+
for(int i=0;i<wargc;i++) {
99+
if(!arg_values_[i].convert(wargv[i])) {
100+
wargc = i;
101+
break;
102+
}
103+
args_[i] = arg_values_[i].c_str();
104+
}
105+
argc = wargc;
106+
argv = &args_[0];
107+
}
108+
catch(...) {
109+
LocalFree(wargv);
110+
throw;
111+
}
112+
LocalFree(wargv);
113+
}
114+
void fix_env(char **&en)
115+
{
116+
static char *dummy = 0;
117+
en = &dummy;
118+
wchar_t *wstrings = GetEnvironmentStringsW();
119+
if(!wstrings)
120+
return;
121+
try {
122+
wchar_t *wstrings_end = 0;
123+
int count = 0;
124+
for(wstrings_end = wstrings;*wstrings_end;wstrings_end+=wcslen(wstrings_end)+1)
125+
count++;
126+
if(env_.convert(wstrings,wstrings_end)) {
127+
envp_.resize(count+1,0);
128+
char *p=env_.c_str();
129+
int pos = 0;
130+
for(int i=0;i<count;i++) {
131+
if(*p!='=')
132+
envp_[pos++] = p;
133+
p+=strlen(p)+1;
134+
}
135+
en = &envp_[0];
136+
}
137+
}
138+
catch(...) {
139+
FreeEnvironmentStringsW(wstrings);
140+
throw;
141+
}
142+
FreeEnvironmentStringsW(wstrings);
143+
144+
}
145+
146+
std::vector<char *> args_;
147+
std::vector<short_stackstring> arg_values_;
148+
stackstring env_;
149+
std::vector<char *> envp_;
150+
151+
int old_argc_;
152+
char **old_argv_;
153+
char **old_env_;
154+
155+
int *old_argc_ptr_;
156+
char ***old_argv_ptr_;
157+
char ***old_env_ptr_;
158+
};
159+
160+
#endif
161+
162+
} // nowide
163+
164+
#endif
165+
166+
///
167+
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

nowide/cenv.hpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Copyright (c) 2012 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 NOWIDE_CENV_H_INCLUDED
9+
#define NOWIDE_CENV_H_INCLUDED
10+
11+
#include <string>
12+
#include <stdexcept>
13+
#include <stdlib.h>
14+
#include <nowide/config.hpp>
15+
#include <nowide/stackstring.hpp>
16+
#include <vector>
17+
18+
#ifdef NOWIDE_WINDOWS
19+
#include <nowide/windows.hpp>
20+
#endif
21+
22+
23+
namespace nowide {
24+
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
25+
using ::getenv;
26+
using ::setenv;
27+
using ::unsetenv;
28+
using ::putenv;
29+
#else
30+
///
31+
/// \brief UTF-8 aware getenv. Returns 0 if the variable is not set.
32+
///
33+
/// This function is not thread safe or reenterable as defined by the standard library
34+
///
35+
inline char *getenv(char const *key)
36+
{
37+
static stackstring value;
38+
39+
wshort_stackstring name;
40+
if(!name.convert(key))
41+
return 0;
42+
43+
static const size_t buf_size = 64;
44+
wchar_t buf[buf_size];
45+
std::vector<wchar_t> tmp;
46+
wchar_t *ptr = buf;
47+
size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size);
48+
if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND
49+
return 0;
50+
if(n >= buf_size) {
51+
tmp.resize(n+1,L'\0');
52+
n = GetEnvironmentVariableW(name.c_str(),&tmp[0],static_cast<unsigned>(tmp.size() - 1));
53+
// The size may have changed
54+
if(n >= tmp.size() - 1)
55+
return 0;
56+
ptr = &tmp[0];
57+
}
58+
if(!value.convert(ptr))
59+
return 0;
60+
return value.c_str();
61+
}
62+
///
63+
/// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value,
64+
///
65+
/// if override is not 0, that the old value is always overridded, otherwise,
66+
/// if the variable exists it remains unchanged
67+
///
68+
inline int setenv(char const *key,char const *value,int override)
69+
{
70+
wshort_stackstring name;
71+
if(!name.convert(key))
72+
return -1;
73+
if(!override) {
74+
wchar_t unused[2];
75+
if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND
76+
return 0;
77+
}
78+
wstackstring wval;
79+
if(!wval.convert(value))
80+
return -1;
81+
if(SetEnvironmentVariableW(name.c_str(),wval.c_str()))
82+
return 0;
83+
return -1;
84+
}
85+
///
86+
/// \brief Remove enviroment variable \a key
87+
///
88+
inline int unsetenv(char const *key)
89+
{
90+
wshort_stackstring name;
91+
if(!name.convert(key))
92+
return -1;
93+
if(SetEnvironmentVariableW(name.c_str(),0))
94+
return 0;
95+
return -1;
96+
}
97+
///
98+
/// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE
99+
///
100+
inline int putenv(char *string)
101+
{
102+
char const *key = string;
103+
char const *key_end = string;
104+
while(*key_end!='=' && key_end!='\0')
105+
key_end++;
106+
if(*key_end == '\0')
107+
return -1;
108+
wshort_stackstring wkey;
109+
if(!wkey.convert(key,key_end))
110+
return -1;
111+
112+
wstackstring wvalue;
113+
if(!wvalue.convert(key_end+1))
114+
return -1;
115+
116+
if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str()))
117+
return 0;
118+
return -1;
119+
}
120+
#endif
121+
} // nowide
122+
123+
124+
#endif
125+
///
126+
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

nowide/config.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Copyright (c) 2012 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 NOWIDE_CONFIG_H_INCLUDED
9+
#define NOWIDE_CONFIG_H_INCLUDED
10+
11+
12+
#if (defined(__WIN32) || defined(_WIN32) || defined(WIN32)) && !defined(__CYGWIN__)
13+
#define NOWIDE_WINDOWS
14+
#endif
15+
16+
#ifdef _MSC_VER
17+
#define NOWIDE_MSVC
18+
#endif
19+
20+
#ifdef NOWIDE_WINDOWS
21+
# if defined(DLL_EXPORT) || defined(NOWIDE_EXPORT)
22+
# ifdef NOWIDE_SOURCE
23+
# define NOWIDE_DECL __declspec(dllexport)
24+
# else
25+
# define NOWIDE_DECL __declspec(dllimport)
26+
# endif //NOWIDE_SOURCE
27+
# endif // DYN_LINK
28+
#endif
29+
30+
#ifndef NOWIDE_DECL
31+
# define NOWIDE_DECL
32+
#endif
33+
34+
35+
#endif
36+
///
37+
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

0 commit comments

Comments
 (0)