First version
This commit is contained in:
Vendored
+167
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_ARGS_HPP_INCLUDED
|
||||
#define NOWIDE_ARGS_HPP_INCLUDED
|
||||
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
#ifdef NOWIDE_WINDOWS
|
||||
#include <nowide/windows.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
|
||||
class args {
|
||||
public:
|
||||
args(int &,char **&) {}
|
||||
args(int &,char **&,char **&){}
|
||||
~args() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under
|
||||
/// Microsoft Windows.
|
||||
///
|
||||
/// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW()
|
||||
/// in order to obtain the information. It does not relates to actual values of argc,argv and env
|
||||
/// under Windows.
|
||||
///
|
||||
/// It restores the original values in its destructor
|
||||
///
|
||||
/// \note the class owns the memory of the newly allocated strings
|
||||
///
|
||||
class args {
|
||||
public:
|
||||
|
||||
///
|
||||
/// Fix command line agruments
|
||||
///
|
||||
args(int &argc,char **&argv) :
|
||||
old_argc_(argc),
|
||||
old_argv_(argv),
|
||||
old_env_(0),
|
||||
old_argc_ptr_(&argc),
|
||||
old_argv_ptr_(&argv),
|
||||
old_env_ptr_(0)
|
||||
{
|
||||
fix_args(argc,argv);
|
||||
}
|
||||
///
|
||||
/// Fix command line agruments and environment
|
||||
///
|
||||
args(int &argc,char **&argv,char **&en) :
|
||||
old_argc_(argc),
|
||||
old_argv_(argv),
|
||||
old_env_(en),
|
||||
old_argc_ptr_(&argc),
|
||||
old_argv_ptr_(&argv),
|
||||
old_env_ptr_(&en)
|
||||
{
|
||||
fix_args(argc,argv);
|
||||
fix_env(en);
|
||||
}
|
||||
///
|
||||
/// Restore original argc,argv,env values, if changed
|
||||
///
|
||||
~args()
|
||||
{
|
||||
if(old_argc_ptr_)
|
||||
*old_argc_ptr_ = old_argc_;
|
||||
if(old_argv_ptr_)
|
||||
*old_argv_ptr_ = old_argv_;
|
||||
if(old_env_ptr_)
|
||||
*old_env_ptr_ = old_env_;
|
||||
}
|
||||
private:
|
||||
void fix_args(int &argc,char **&argv)
|
||||
{
|
||||
int wargc;
|
||||
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc);
|
||||
if(!wargv) {
|
||||
argc = 0;
|
||||
static char *dummy = 0;
|
||||
argv = &dummy;
|
||||
return;
|
||||
}
|
||||
try{
|
||||
args_.resize(wargc+1,0);
|
||||
arg_values_.resize(wargc);
|
||||
for(int i=0;i<wargc;i++) {
|
||||
if(!arg_values_[i].convert(wargv[i])) {
|
||||
wargc = i;
|
||||
break;
|
||||
}
|
||||
args_[i] = arg_values_[i].c_str();
|
||||
}
|
||||
argc = wargc;
|
||||
argv = &args_[0];
|
||||
}
|
||||
catch(...) {
|
||||
LocalFree(wargv);
|
||||
throw;
|
||||
}
|
||||
LocalFree(wargv);
|
||||
}
|
||||
void fix_env(char **&en)
|
||||
{
|
||||
static char *dummy = 0;
|
||||
en = &dummy;
|
||||
wchar_t *wstrings = GetEnvironmentStringsW();
|
||||
if(!wstrings)
|
||||
return;
|
||||
try {
|
||||
wchar_t *wstrings_end = 0;
|
||||
int count = 0;
|
||||
for(wstrings_end = wstrings;*wstrings_end;wstrings_end+=wcslen(wstrings_end)+1)
|
||||
count++;
|
||||
if(env_.convert(wstrings,wstrings_end)) {
|
||||
envp_.resize(count+1,0);
|
||||
char *p=env_.c_str();
|
||||
int pos = 0;
|
||||
for(int i=0;i<count;i++) {
|
||||
if(*p!='=')
|
||||
envp_[pos++] = p;
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
en = &envp_[0];
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
throw;
|
||||
}
|
||||
FreeEnvironmentStringsW(wstrings);
|
||||
|
||||
}
|
||||
|
||||
std::vector<char *> args_;
|
||||
std::vector<short_stackstring> arg_values_;
|
||||
stackstring env_;
|
||||
std::vector<char *> envp_;
|
||||
|
||||
int old_argc_;
|
||||
char **old_argv_;
|
||||
char **old_env_;
|
||||
|
||||
int *old_argc_ptr_;
|
||||
char ***old_argv_ptr_;
|
||||
char ***old_env_ptr_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // nowide
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+126
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CENV_H_INCLUDED
|
||||
#define NOWIDE_CENV_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/stackstring.hpp>
|
||||
#include <vector>
|
||||
|
||||
#ifdef NOWIDE_WINDOWS
|
||||
#include <nowide/windows.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
|
||||
using ::getenv;
|
||||
using ::setenv;
|
||||
using ::unsetenv;
|
||||
using ::putenv;
|
||||
#else
|
||||
///
|
||||
/// \brief UTF-8 aware getenv. Returns 0 if the variable is not set.
|
||||
///
|
||||
/// This function is not thread safe or reenterable as defined by the standard library
|
||||
///
|
||||
inline char *getenv(char const *key)
|
||||
{
|
||||
static stackstring value;
|
||||
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return 0;
|
||||
|
||||
static const size_t buf_size = 64;
|
||||
wchar_t buf[buf_size];
|
||||
std::vector<wchar_t> tmp;
|
||||
wchar_t *ptr = buf;
|
||||
size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size);
|
||||
if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND
|
||||
return 0;
|
||||
if(n >= buf_size) {
|
||||
tmp.resize(n+1,L'\0');
|
||||
n = GetEnvironmentVariableW(name.c_str(),&tmp[0],static_cast<unsigned>(tmp.size() - 1));
|
||||
// The size may have changed
|
||||
if(n >= tmp.size() - 1)
|
||||
return 0;
|
||||
ptr = &tmp[0];
|
||||
}
|
||||
if(!value.convert(ptr))
|
||||
return 0;
|
||||
return value.c_str();
|
||||
}
|
||||
///
|
||||
/// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value,
|
||||
///
|
||||
/// if override is not 0, that the old value is always overridded, otherwise,
|
||||
/// if the variable exists it remains unchanged
|
||||
///
|
||||
inline int setenv(char const *key,char const *value,int override)
|
||||
{
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return -1;
|
||||
if(!override) {
|
||||
wchar_t unused[2];
|
||||
if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND
|
||||
return 0;
|
||||
}
|
||||
wstackstring wval;
|
||||
if(!wval.convert(value))
|
||||
return -1;
|
||||
if(SetEnvironmentVariableW(name.c_str(),wval.c_str()))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
///
|
||||
/// \brief Remove enviroment variable \a key
|
||||
///
|
||||
inline int unsetenv(char const *key)
|
||||
{
|
||||
wshort_stackstring name;
|
||||
if(!name.convert(key))
|
||||
return -1;
|
||||
if(SetEnvironmentVariableW(name.c_str(),0))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
///
|
||||
/// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE
|
||||
///
|
||||
inline int putenv(char *string)
|
||||
{
|
||||
char const *key = string;
|
||||
char const *key_end = string;
|
||||
while(*key_end!='=' && key_end!='\0')
|
||||
key_end++;
|
||||
if(*key_end == '\0')
|
||||
return -1;
|
||||
wshort_stackstring wkey;
|
||||
if(!wkey.convert(key,key_end))
|
||||
return -1;
|
||||
|
||||
wstackstring wvalue;
|
||||
if(!wvalue.convert(key_end+1))
|
||||
return -1;
|
||||
|
||||
if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str()))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
} // nowide
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CONFIG_H_INCLUDED
|
||||
#define NOWIDE_CONFIG_H_INCLUDED
|
||||
|
||||
|
||||
#if (defined(__WIN32) || defined(_WIN32) || defined(WIN32)) && !defined(__CYGWIN__)
|
||||
#define NOWIDE_WINDOWS
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define NOWIDE_MSVC
|
||||
#endif
|
||||
|
||||
#ifdef NOWIDE_WINDOWS
|
||||
# if defined(DLL_EXPORT) || defined(NOWIDE_EXPORT)
|
||||
# ifdef NOWIDE_SOURCE
|
||||
# define NOWIDE_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define NOWIDE_DECL __declspec(dllimport)
|
||||
# endif //NOWIDE_SOURCE
|
||||
# endif // DYN_LINK
|
||||
#endif
|
||||
|
||||
#ifndef NOWIDE_DECL
|
||||
# define NOWIDE_DECL
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+154
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CONVERT_H_INCLUDED
|
||||
#define NOWIDE_CONVERT_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <nowide/encoding_utf.hpp>
|
||||
|
||||
|
||||
namespace nowide {
|
||||
///
|
||||
/// \brief Template function that converts a buffer of UTF sequence in range [source_begin,source_end)
|
||||
/// to the output \a buffer of size \a buffer_size.
|
||||
///
|
||||
/// In case of success a NUL terminated string returned (buffer), otherwise 0 is returned.
|
||||
///
|
||||
/// If there is not enough room in the buffer or the source sequence contains invalid UTF
|
||||
/// 0 is returned, and the contend of the buffer is undefined.
|
||||
///
|
||||
template<typename CharOut,typename CharIn>
|
||||
CharOut *basic_convert(CharOut *buffer,size_t buffer_size,CharIn const *source_begin,CharIn const *source_end)
|
||||
{
|
||||
CharOut *rv = buffer;
|
||||
if(buffer_size == 0)
|
||||
return 0;
|
||||
buffer_size --;
|
||||
while(source_begin!=source_end) {
|
||||
using namespace nowide::utf;
|
||||
code_point c = utf_traits<CharIn>::template decode<CharIn const *>(source_begin,source_end);
|
||||
if(c==illegal || c==incomplete) {
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
size_t width = utf_traits<CharOut>::width(c);
|
||||
if(buffer_size < width) {
|
||||
rv=0;
|
||||
break;
|
||||
}
|
||||
buffer = utf_traits<CharOut>::template encode<CharOut *>(c,buffer);
|
||||
buffer_size -= width;
|
||||
}
|
||||
*buffer++ = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/// \cond INTERNAL
|
||||
namespace details {
|
||||
//
|
||||
// wcslen defined only in C99... So we will not use it
|
||||
//
|
||||
template<typename Char>
|
||||
Char const *basic_strend(Char const *s)
|
||||
{
|
||||
while(*s)
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// Convert NUL terminated UTF source string to NUL terminated \a output string of size at
|
||||
/// most output_size (including NUL)
|
||||
///
|
||||
/// In case of surcess output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline char *narrow(char *output,size_t output_size,wchar_t const *source)
|
||||
{
|
||||
return basic_convert(output,output_size,source,details::basic_strend(source));
|
||||
}
|
||||
///
|
||||
/// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at
|
||||
/// most output_size (including NUL)
|
||||
///
|
||||
/// In case of surcess output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline char *narrow(char *output,size_t output_size,wchar_t const *begin,wchar_t const *end)
|
||||
{
|
||||
return basic_convert(output,output_size,begin,end);
|
||||
}
|
||||
///
|
||||
/// Convert NUL terminated UTF source string to NUL terminated \a output string of size at
|
||||
/// most output_size (including NUL)
|
||||
///
|
||||
/// In case of surcess output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline wchar_t *widen(wchar_t *output,size_t output_size,char const *source)
|
||||
{
|
||||
return basic_convert(output,output_size,source,details::basic_strend(source));
|
||||
}
|
||||
///
|
||||
/// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at
|
||||
/// most output_size (including NUL)
|
||||
///
|
||||
/// In case of surcess output is returned, if the input sequence is illegal,
|
||||
/// or there is not enough room NULL is returned
|
||||
///
|
||||
inline wchar_t *widen(wchar_t *output,size_t output_size,char const *begin,char const *end)
|
||||
{
|
||||
return basic_convert(output,output_size,begin,end);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert between Wide - UTF-16/32 string and UTF-8 string.
|
||||
///
|
||||
/// nowide::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::string narrow(wchar_t const *s)
|
||||
{
|
||||
return nowide::conv::utf_to_utf<char>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform
|
||||
///
|
||||
/// nowide::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::wstring widen(char const *s)
|
||||
{
|
||||
return nowide::conv::utf_to_utf<wchar_t>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between Wide - UTF-16/32 string and UTF-8 string
|
||||
///
|
||||
/// nowide::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::string narrow(std::wstring const &s)
|
||||
{
|
||||
return nowide::conv::utf_to_utf<char>(s);
|
||||
}
|
||||
///
|
||||
/// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform
|
||||
///
|
||||
/// nowide::conv::conversion_error is thrown in a case of a error
|
||||
///
|
||||
inline std::wstring widen(std::string const &s)
|
||||
{
|
||||
return nowide::conv::utf_to_utf<wchar_t>(s);
|
||||
}
|
||||
|
||||
} // nowide
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+101
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CSTDIO_H_INCLUDED
|
||||
#define NOWIDE_CSTDIO_H_INCLUDED
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/convert.hpp>
|
||||
#include <nowide/stackstring.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
|
||||
using std::fopen;
|
||||
using std::freopen;
|
||||
using std::remove;
|
||||
using std::rename;
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief Same as freopen but file_name and mode are UTF-8 strings
|
||||
///
|
||||
/// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL
|
||||
///
|
||||
inline FILE *freopen(char const *file_name,char const *mode,FILE *stream)
|
||||
{
|
||||
wstackstring wname;
|
||||
wshort_stackstring wmode;
|
||||
if(!wname.convert(file_name) || !wmode.convert(mode)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
return _wfreopen(wname.c_str(),wmode.c_str(),stream);
|
||||
}
|
||||
///
|
||||
/// \brief Same as fopen but file_name and mode are UTF-8 strings
|
||||
///
|
||||
/// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL
|
||||
///
|
||||
inline FILE *fopen(char const *file_name,char const *mode)
|
||||
{
|
||||
wstackstring wname;
|
||||
wshort_stackstring wmode;
|
||||
if(!wname.convert(file_name) || !wmode.convert(mode)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
return _wfopen(wname.c_str(),wmode.c_str());
|
||||
}
|
||||
///
|
||||
/// \brief Same as rename but old_name and new_name are UTF-8 strings
|
||||
///
|
||||
/// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL
|
||||
///
|
||||
inline int rename(char const *old_name,char const *new_name)
|
||||
{
|
||||
wstackstring wold,wnew;
|
||||
if(!wold.convert(old_name) || !wnew.convert(new_name)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wrename(wold.c_str(),wnew.c_str());
|
||||
}
|
||||
///
|
||||
/// \brief Same as rename but name is UTF-8 string
|
||||
///
|
||||
/// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL
|
||||
///
|
||||
inline int remove(char const *name)
|
||||
{
|
||||
wstackstring wname;
|
||||
if(!wname.convert(name)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wremove(wname.c_str());
|
||||
}
|
||||
#endif
|
||||
} // nowide
|
||||
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CSTDLIB_HPP_INCLUDED
|
||||
#define NOWIDE_CSTDLIB_HPP_INCLUDED
|
||||
|
||||
#include <nowide/cenv.hpp>
|
||||
#include <nowide/system.hpp>
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_ENCODING_ERRORS_HPP_INCLUDED
|
||||
#define NOWIDE_ENCODING_ERRORS_HPP_INCLUDED
|
||||
|
||||
#include <nowide/config.hpp>
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4275 4251 4231 4660)
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
|
||||
namespace nowide {
|
||||
namespace conv {
|
||||
///
|
||||
/// \addtogroup codepage
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief The excepton that is thrown in case of conversion error
|
||||
///
|
||||
class conversion_error : public std::runtime_error {
|
||||
public:
|
||||
conversion_error() : std::runtime_error("Conversion failed") {}
|
||||
};
|
||||
|
||||
///
|
||||
/// enum that defines conversion policy
|
||||
///
|
||||
typedef enum {
|
||||
skip = 0, ///< Skip illegal/unconvertable characters
|
||||
stop = 1, ///< Stop conversion and throw conversion_error
|
||||
default_method = skip ///< Default method - skip
|
||||
} method_type;
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
} // conv
|
||||
|
||||
} // nowide
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_ENCODING_UTF_HPP_INCLUDED
|
||||
#define NOWIDE_ENCODING_UTF_HPP_INCLUDED
|
||||
|
||||
#include <nowide/utf.hpp>
|
||||
#include <nowide/encoding_errors.hpp>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4275 4251 4231 4660)
|
||||
#endif
|
||||
|
||||
|
||||
namespace nowide{
|
||||
namespace conv {
|
||||
///
|
||||
/// Convert a Unicode text in range [begin,end) to other Unicode encoding
|
||||
///
|
||||
template<typename CharOut,typename CharIn>
|
||||
std::basic_string<CharOut>
|
||||
utf_to_utf(CharIn const *begin,CharIn const *end,method_type how = default_method)
|
||||
{
|
||||
std::basic_string<CharOut> result;
|
||||
result.reserve(end-begin);
|
||||
typedef std::back_insert_iterator<std::basic_string<CharOut> > inserter_type;
|
||||
inserter_type inserter(result);
|
||||
utf::code_point c;
|
||||
while(begin!=end) {
|
||||
c=utf::utf_traits<CharIn>::template decode<CharIn const *>(begin,end);
|
||||
if(c==utf::illegal || c==utf::incomplete) {
|
||||
if(how==stop)
|
||||
throw conversion_error();
|
||||
}
|
||||
else {
|
||||
utf::utf_traits<CharOut>::template encode<inserter_type>(c,inserter);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
///
|
||||
/// Convert a Unicode NUL terminated string \a str other Unicode encoding
|
||||
///
|
||||
template<typename CharOut,typename CharIn>
|
||||
std::basic_string<CharOut>
|
||||
utf_to_utf(CharIn const *str,method_type how = default_method)
|
||||
{
|
||||
CharIn const *end = str;
|
||||
while(*end)
|
||||
end++;
|
||||
return utf_to_utf<CharOut,CharIn>(str,end,how);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert a Unicode string \a str other Unicode encoding
|
||||
///
|
||||
template<typename CharOut,typename CharIn>
|
||||
std::basic_string<CharOut>
|
||||
utf_to_utf(std::basic_string<CharIn> const &str,method_type how = default_method)
|
||||
{
|
||||
return utf_to_utf<CharOut,CharIn>(str.c_str(),str.c_str()+str.size(),how);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // conv
|
||||
} // nowide
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
Vendored
+408
@@ -0,0 +1,408 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_FILEBUF_HPP
|
||||
#define NOWIDE_FILEBUF_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/stackstring.hpp>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4996 4244)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_FSTREAM_TESTS) && !defined(NOWIDE_DOXYGEN)
|
||||
using std::basic_filebuf;
|
||||
using std::filebuf;
|
||||
#else // Windows
|
||||
|
||||
///
|
||||
/// \brief This forward declaration defined the basic_filebuf type.
|
||||
///
|
||||
/// it is implemented and specialized for CharType = char, it behaves
|
||||
/// implements std::filebuf over standard C I/O
|
||||
///
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_filebuf;
|
||||
|
||||
///
|
||||
/// \brief This is implementation of std::filebuf
|
||||
///
|
||||
/// it is implemented and specialized for CharType = char, it behaves
|
||||
/// implements std::filebuf over standard C I/O
|
||||
///
|
||||
template<>
|
||||
class basic_filebuf<char> : public std::basic_streambuf<char> {
|
||||
public:
|
||||
///
|
||||
/// Creates new filebuf
|
||||
///
|
||||
basic_filebuf() :
|
||||
buffer_size_(4),
|
||||
buffer_(0),
|
||||
file_(0),
|
||||
own_(true),
|
||||
mode_(std::ios::in | std::ios::out)
|
||||
{
|
||||
setg(0,0,0);
|
||||
setp(0,0);
|
||||
}
|
||||
|
||||
virtual ~basic_filebuf()
|
||||
{
|
||||
if(file_) {
|
||||
::fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
if(own_ && buffer_)
|
||||
delete [] buffer_;
|
||||
}
|
||||
|
||||
///
|
||||
/// Same as std::filebuf::open but s is UTF-8 string
|
||||
///
|
||||
basic_filebuf *open(std::string const &s,std::ios_base::openmode mode)
|
||||
{
|
||||
return open(s.c_str(),mode);
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::open but s is UTF-8 string
|
||||
///
|
||||
basic_filebuf *open(char const *s,std::ios_base::openmode mode)
|
||||
{
|
||||
if(file_) {
|
||||
sync();
|
||||
::fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
wchar_t const *smode = get_mode(mode);
|
||||
if(!smode)
|
||||
return 0;
|
||||
wstackstring name;
|
||||
if(!name.convert(s))
|
||||
return 0;
|
||||
#ifdef NOWIDE_FSTREAM_TESTS
|
||||
FILE *f = ::fopen(s,nowide::convert(smode).c_str());
|
||||
#else
|
||||
FILE *f = ::_wfopen(name.c_str(),smode);
|
||||
#endif
|
||||
if(!f)
|
||||
return 0;
|
||||
file_ = f;
|
||||
return this;
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::close()
|
||||
///
|
||||
basic_filebuf *close()
|
||||
{
|
||||
bool res = sync() == 0;
|
||||
if(file_) {
|
||||
if(::fclose(file_)!=0)
|
||||
res = false;
|
||||
file_ = 0;
|
||||
}
|
||||
return res ? this : 0;
|
||||
}
|
||||
///
|
||||
/// Same as std::filebuf::is_open()
|
||||
///
|
||||
bool is_open() const
|
||||
{
|
||||
return file_ != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void make_buffer()
|
||||
{
|
||||
if(buffer_)
|
||||
return;
|
||||
if(buffer_size_ > 0) {
|
||||
buffer_ = new char [buffer_size_];
|
||||
own_ = true;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
|
||||
virtual std::streambuf *setbuf(char *s,std::streamsize n)
|
||||
{
|
||||
if(!buffer_ && n>=0) {
|
||||
buffer_ = s;
|
||||
buffer_size_ = n;
|
||||
own_ = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
#ifdef NOWIDE_DEBUG_FILEBUF
|
||||
|
||||
void print_buf(char *b,char *p,char *e)
|
||||
{
|
||||
std::cerr << "-- Is Null: " << (b==0) << std::endl;;
|
||||
if(b==0)
|
||||
return;
|
||||
if(e != 0)
|
||||
std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl;
|
||||
else
|
||||
std::cerr << "-- Total: " << p - b << std::endl;
|
||||
|
||||
std::cerr << "-- [";
|
||||
for(char *ptr = b;ptr<p;ptr++)
|
||||
std::cerr << *ptr;
|
||||
if(e!=0) {
|
||||
std::cerr << "|";
|
||||
for(char *ptr = p;ptr<e;ptr++)
|
||||
std::cerr << *ptr;
|
||||
}
|
||||
std::cerr << "]" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void print_state()
|
||||
{
|
||||
std::cerr << "- Output:" << std::endl;
|
||||
print_buf(pbase(),pptr(),0);
|
||||
std::cerr << "- Input:" << std::endl;
|
||||
print_buf(eback(),gptr(),egptr());
|
||||
std::cerr << "- fpos: " << (file_ ? ftell(file_) : -1L) << std::endl;
|
||||
}
|
||||
|
||||
struct print_guard
|
||||
{
|
||||
print_guard(basic_filebuf *p,char const *func)
|
||||
{
|
||||
self = p;
|
||||
f=func;
|
||||
std::cerr << "In: " << f << std::endl;
|
||||
self->print_state();
|
||||
}
|
||||
~print_guard()
|
||||
{
|
||||
std::cerr << "Out: " << f << std::endl;
|
||||
self->print_state();
|
||||
}
|
||||
basic_filebuf *self;
|
||||
char const *f;
|
||||
};
|
||||
#else
|
||||
#endif
|
||||
|
||||
int overflow(int c)
|
||||
{
|
||||
#ifdef NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
|
||||
if(fixg() < 0)
|
||||
return EOF;
|
||||
|
||||
size_t n = pptr() - pbase();
|
||||
if(n > 0) {
|
||||
if(::fwrite(pbase(),1,n,file_) < n)
|
||||
return -1;
|
||||
fflush(file_);
|
||||
}
|
||||
|
||||
if(buffer_size_ > 0) {
|
||||
make_buffer();
|
||||
setp(buffer_,buffer_+buffer_size_);
|
||||
if(c!=EOF)
|
||||
sputc(c);
|
||||
}
|
||||
else if(c!=EOF) {
|
||||
if(::fputc(c,file_)==EOF)
|
||||
return EOF;
|
||||
fflush(file_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sync()
|
||||
{
|
||||
return overflow(EOF);
|
||||
}
|
||||
|
||||
int underflow()
|
||||
{
|
||||
#ifdef NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
if(fixp() < 0)
|
||||
return EOF;
|
||||
if(buffer_size_ == 0) {
|
||||
int c = ::fgetc(file_);
|
||||
if(c==EOF) {
|
||||
return EOF;
|
||||
}
|
||||
last_char_ = c;
|
||||
setg(&last_char_,&last_char_,&last_char_ + 1);
|
||||
return c;
|
||||
}
|
||||
make_buffer();
|
||||
size_t n = ::fread(buffer_,1,buffer_size_,file_);
|
||||
setg(buffer_,buffer_,buffer_+n);
|
||||
if(n == 0)
|
||||
return EOF;
|
||||
return std::char_traits<char>::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
int pbackfail(int)
|
||||
{
|
||||
return pubseekoff(-1,std::ios::cur);
|
||||
}
|
||||
|
||||
std::streampos seekoff(std::streamoff off,
|
||||
std::ios_base::seekdir seekdir,
|
||||
std::ios_base::openmode /*m*/)
|
||||
{
|
||||
#ifdef NOWIDE_DEBUG_FILEBUF
|
||||
print_guard g(this,__FUNCTION__);
|
||||
#endif
|
||||
if(!file_)
|
||||
return EOF;
|
||||
if(fixp() < 0 || fixg() < 0)
|
||||
return EOF;
|
||||
if(seekdir == std::ios_base::cur) {
|
||||
if( ::fseek(file_,off,SEEK_CUR) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else if(seekdir == std::ios_base::beg) {
|
||||
if( ::fseek(file_,off,SEEK_SET) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else if(seekdir == std::ios_base::end) {
|
||||
if( ::fseek(file_,off,SEEK_END) < 0)
|
||||
return EOF;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
return ftell(file_);
|
||||
}
|
||||
std::streampos seekpos(std::streampos off,std::ios_base::openmode m)
|
||||
{
|
||||
return seekoff(std::streamoff(off),std::ios_base::beg,m);
|
||||
}
|
||||
private:
|
||||
int fixg()
|
||||
{
|
||||
if(gptr()!=egptr()) {
|
||||
std::streamsize off = gptr() - egptr();
|
||||
setg(0,0,0);
|
||||
if(fseek(file_,off,SEEK_CUR) != 0)
|
||||
return -1;
|
||||
}
|
||||
setg(0,0,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fixp()
|
||||
{
|
||||
if(pptr()!=0) {
|
||||
int r = sync();
|
||||
setp(0,0);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset(FILE *f = 0)
|
||||
{
|
||||
sync();
|
||||
if(file_) {
|
||||
fclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
file_ = f;
|
||||
}
|
||||
|
||||
|
||||
static wchar_t const *get_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
//
|
||||
// done according to n2914 table 106 27.9.1.4
|
||||
//
|
||||
|
||||
// note can't use switch case as overload operator can't be used
|
||||
// in constant expression
|
||||
if(mode == (std::ios_base::out))
|
||||
return L"w";
|
||||
if(mode == (std::ios_base::out | std::ios_base::app))
|
||||
return L"a";
|
||||
if(mode == (std::ios_base::app))
|
||||
return L"a";
|
||||
if(mode == (std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w";
|
||||
if(mode == (std::ios_base::in))
|
||||
return L"r";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out))
|
||||
return L"r+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
||||
return L"a+";
|
||||
if(mode == (std::ios_base::in | std::ios_base::app))
|
||||
return L"a+";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out))
|
||||
return L"wb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
|
||||
return L"ab";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::app))
|
||||
return L"ab";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"wb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in))
|
||||
return L"rb";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
|
||||
return L"r+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
||||
return L"w+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
||||
return L"a+b";
|
||||
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
|
||||
return L"a+b";
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t buffer_size_;
|
||||
char *buffer_;
|
||||
FILE *file_;
|
||||
bool own_;
|
||||
char last_char_;
|
||||
std::ios::openmode mode_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Convinience typedef
|
||||
///
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
|
||||
#endif // windows
|
||||
|
||||
} // nowide
|
||||
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+248
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_FSTREAM_INCLUDED_HPP
|
||||
#define NOWIDE_FSTREAM_INCLUDED_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/convert.hpp>
|
||||
#include <nowide/scoped_ptr.hpp>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <nowide/filebuf.hpp>
|
||||
|
||||
|
||||
///
|
||||
/// \brief This namespace includes implementation of the standard library functios
|
||||
/// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias
|
||||
/// of std namespace (i.e. not on Windows)
|
||||
///
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_FSTREAM_TESTS) && !defined(NOWIDE_DOXYGEN)
|
||||
|
||||
using std::basic_ifstream;
|
||||
using std::basic_ofstream;
|
||||
using std::basic_fstream;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::fstream;
|
||||
|
||||
#else
|
||||
///
|
||||
/// \brief Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ifstream : public std::basic_istream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_istream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_ifstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
|
||||
explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
if(!buf_->open(file_name,mode | std::ios_base::in)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_ifstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
nowide::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_ofstream : public std::basic_ostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_ostream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_ofstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
|
||||
{
|
||||
if(!buf_->open(file_name,mode | std::ios_base::out)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_ofstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
nowide::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
|
||||
///
|
||||
|
||||
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
||||
class basic_fstream : public std::basic_iostream<CharType,Traits>
|
||||
{
|
||||
public:
|
||||
typedef basic_filebuf<CharType,Traits> internal_buffer_type;
|
||||
typedef std::basic_iostream<CharType,Traits> internal_stream_type;
|
||||
|
||||
basic_fstream() :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
}
|
||||
explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
|
||||
internal_stream_type(0)
|
||||
{
|
||||
buf_.reset(new internal_buffer_type());
|
||||
std::ios::rdbuf(buf_.get());
|
||||
open(file_name,mode);
|
||||
}
|
||||
void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
|
||||
{
|
||||
if(!buf_->open(file_name,mode)) {
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
bool is_open()
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
bool is_open() const
|
||||
{
|
||||
return buf_->is_open();
|
||||
}
|
||||
void close()
|
||||
{
|
||||
if(!buf_->close())
|
||||
this->setstate(std::ios_base::failbit);
|
||||
else
|
||||
this->clear();
|
||||
}
|
||||
|
||||
internal_buffer_type *rdbuf() const
|
||||
{
|
||||
return buf_.get();
|
||||
}
|
||||
~basic_fstream()
|
||||
{
|
||||
buf_->close();
|
||||
}
|
||||
|
||||
private:
|
||||
nowide::scoped_ptr<internal_buffer_type> buf_;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Same as std::filebuf but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
///
|
||||
/// Same as std::ifstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ifstream<char> ifstream;
|
||||
///
|
||||
/// Same as std::ofstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_ofstream<char> ofstream;
|
||||
///
|
||||
/// Same as std::fstream but accepts UTF-8 strings under Windows
|
||||
///
|
||||
typedef basic_fstream<char> fstream;
|
||||
|
||||
#endif
|
||||
} // nowide
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+99
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_IOSTREAM_HPP_INCLUDED
|
||||
#define NOWIDE_IOSTREAM_HPP_INCLUDED
|
||||
|
||||
#include <nowide/config.hpp>
|
||||
#include <nowide/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace nowide {
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::cin;
|
||||
using std::clog;
|
||||
#else
|
||||
|
||||
/// \cond INTERNAL
|
||||
namespace details {
|
||||
class console_output_buffer;
|
||||
class console_input_buffer;
|
||||
|
||||
class NOWIDE_DECL winconsole_ostream : public std::ostream {
|
||||
winconsole_ostream(winconsole_ostream const &);
|
||||
void operator=(winconsole_ostream const &);
|
||||
public:
|
||||
winconsole_ostream(int fd);
|
||||
~winconsole_ostream();
|
||||
private:
|
||||
nowide::scoped_ptr<console_output_buffer> d;
|
||||
};
|
||||
|
||||
class NOWIDE_DECL winconsole_istream : public std::istream {
|
||||
winconsole_istream(winconsole_istream const &);
|
||||
void operator=(winconsole_istream const &);
|
||||
public:
|
||||
|
||||
winconsole_istream();
|
||||
~winconsole_istream();
|
||||
private:
|
||||
struct data;
|
||||
nowide::scoped_ptr<console_input_buffer> d;
|
||||
};
|
||||
} // details
|
||||
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// \brief Same as std::cin, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern NOWIDE_DECL details::winconsole_istream cin;
|
||||
///
|
||||
/// \brief Same as std::cout, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern NOWIDE_DECL details::winconsole_ostream cout;
|
||||
///
|
||||
/// \brief Same as std::cerr, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern NOWIDE_DECL details::winconsole_ostream cerr;
|
||||
///
|
||||
/// \brief Same as std::clog, but uses UTF-8
|
||||
///
|
||||
/// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio
|
||||
///
|
||||
extern NOWIDE_DECL details::winconsole_ostream clog;
|
||||
|
||||
#endif
|
||||
|
||||
} // nowide
|
||||
|
||||
|
||||
#ifdef NOWIDE_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+93
@@ -0,0 +1,93 @@
|
||||
#ifndef NOWIDE_SCOPED_PTR_HPP
|
||||
#define NOWIDE_SCOPED_PTR_HPP
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov,
|
||||
// Copyright (C) 2012 Artyom Beilis
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace nowide
|
||||
{
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||
|
||||
template<class T> class scoped_ptr // noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
T * px;
|
||||
|
||||
scoped_ptr(scoped_ptr const &);
|
||||
scoped_ptr & operator=(scoped_ptr const &);
|
||||
|
||||
typedef scoped_ptr<T> this_type;
|
||||
|
||||
void operator==( scoped_ptr const& ) const;
|
||||
void operator!=( scoped_ptr const& ) const;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_ptr() // never throws
|
||||
{
|
||||
delete px;
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
assert( p == 0 || p != px ); // catch self-reset errors
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
T & operator*() const // never throws
|
||||
{
|
||||
assert( px != 0 );
|
||||
return *px;
|
||||
}
|
||||
|
||||
T * operator->() const // never throws
|
||||
{
|
||||
assert( px != 0 );
|
||||
return px;
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return px!=0;
|
||||
}
|
||||
|
||||
void swap(scoped_ptr & b) // never throws
|
||||
{
|
||||
T * tmp = b.px;
|
||||
b.px = px;
|
||||
px = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace nowide
|
||||
|
||||
#endif
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
Vendored
+154
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_DETAILS_WIDESTR_H_INCLUDED
|
||||
#define NOWIDE_DETAILS_WIDESTR_H_INCLUDED
|
||||
#include <nowide/convert.hpp>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace nowide {
|
||||
|
||||
///
|
||||
/// \brief A class that allows to create a temporary wide or narrow UTF strings from
|
||||
/// wide or narrow UTF source.
|
||||
///
|
||||
/// It uses on stack buffer of the string is short enough
|
||||
/// and allocated a buffer on the heap if the size of the buffer is too small
|
||||
///
|
||||
template<typename CharOut=wchar_t,typename CharIn = char,size_t BufferSize = 256>
|
||||
class basic_stackstring {
|
||||
public:
|
||||
|
||||
static const size_t buffer_size = BufferSize;
|
||||
typedef CharOut output_char;
|
||||
typedef CharIn input_char;
|
||||
|
||||
basic_stackstring(basic_stackstring const &other) :
|
||||
mem_buffer_(0)
|
||||
{
|
||||
clear();
|
||||
if(other.mem_buffer_) {
|
||||
size_t len = 0;
|
||||
while(other.mem_buffer_[len])
|
||||
len ++;
|
||||
mem_buffer_ = new output_char[len + 1];
|
||||
memcpy(mem_buffer_,other.mem_buffer_,sizeof(output_char) * (len+1));
|
||||
}
|
||||
else {
|
||||
memcpy(buffer_,other.buffer_,buffer_size * sizeof(output_char));
|
||||
}
|
||||
}
|
||||
|
||||
void swap(basic_stackstring &other)
|
||||
{
|
||||
std::swap(mem_buffer_,other.mem_buffer_);
|
||||
for(size_t i=0;i<buffer_size;i++)
|
||||
std::swap(buffer_[i],other.buffer_[i]);
|
||||
}
|
||||
basic_stackstring &operator=(basic_stackstring const &other)
|
||||
{
|
||||
if(this != &other) {
|
||||
basic_stackstring tmp(other);
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_stackstring() : mem_buffer_(0)
|
||||
{
|
||||
}
|
||||
bool convert(input_char const *input)
|
||||
{
|
||||
return convert(input,details::basic_strend(input));
|
||||
}
|
||||
bool convert(input_char const *begin,input_char const *end)
|
||||
{
|
||||
clear();
|
||||
|
||||
size_t space = get_space(sizeof(input_char),sizeof(output_char),end - begin) + 1;
|
||||
if(space <= buffer_size) {
|
||||
if(basic_convert(buffer_,buffer_size,begin,end))
|
||||
return true;
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
mem_buffer_ = new output_char[space];
|
||||
if(!basic_convert(mem_buffer_,space,begin,end)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
output_char *c_str()
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
output_char const *c_str() const
|
||||
{
|
||||
if(mem_buffer_)
|
||||
return mem_buffer_;
|
||||
return buffer_;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
if(mem_buffer_) {
|
||||
delete [] mem_buffer_;
|
||||
mem_buffer_=0;
|
||||
}
|
||||
buffer_[0] = 0;
|
||||
}
|
||||
~basic_stackstring()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
private:
|
||||
static size_t get_space(size_t insize,size_t outsize,size_t in)
|
||||
{
|
||||
if(insize <= outsize)
|
||||
return in;
|
||||
else if(insize == 2 && outsize == 1)
|
||||
return 3 * in;
|
||||
else if(insize == 4 && outsize == 1)
|
||||
return 4 * in;
|
||||
else // if(insize == 4 && outsize == 2)
|
||||
return 2 * in;
|
||||
}
|
||||
output_char buffer_[buffer_size];
|
||||
output_char *mem_buffer_;
|
||||
}; //basic_stackstring
|
||||
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,256> wstackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,256> stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<wchar_t,char,16> wshort_stackstring;
|
||||
///
|
||||
/// Convinience typedef
|
||||
///
|
||||
typedef basic_stackstring<char,wchar_t,16> short_stackstring;
|
||||
|
||||
|
||||
} // nowide
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_CSTDLIB_HPP
|
||||
#define NOWIDE_CSTDLIB_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <nowide/stackstring.hpp>
|
||||
|
||||
namespace nowide {
|
||||
|
||||
#if !defined(NOWIDE_WINDOWS) && !defined(NOWIDE_DOXYGEN)
|
||||
|
||||
using ::system;
|
||||
|
||||
#else // Windows
|
||||
|
||||
///
|
||||
/// Same as std::system but cmd is UTF-8.
|
||||
///
|
||||
/// If the input is not valid UTF-8, -1 returned and errno set to EINVAL
|
||||
///
|
||||
inline int system(char const *cmd)
|
||||
{
|
||||
if(!cmd)
|
||||
return _wsystem(0);
|
||||
wstackstring wcmd;
|
||||
if(!wcmd.convert(cmd)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _wsystem(wcmd.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
} // nowide
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Vendored
+469
@@ -0,0 +1,469 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_UTF_HPP_INCLUDED
|
||||
#define NOWIDE_UTF_HPP_INCLUDED
|
||||
|
||||
#include <nowide/config.hpp>
|
||||
|
||||
#ifndef NOWIDE_MSVC
|
||||
namespace nowide {
|
||||
namespace utf {
|
||||
typedef unsigned uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
namespace nowide {
|
||||
///
|
||||
/// \brief Namespace that holds basic operations on UTF encoded sequences
|
||||
///
|
||||
/// All functions defined in this namespace do not require linking with Boost.Locale library
|
||||
///
|
||||
namespace utf {
|
||||
/// \cond INTERNAL
|
||||
#ifdef __GNUC__
|
||||
# define NOWIDE_LIKELY(x) __builtin_expect((x),1)
|
||||
# define NOWIDE_UNLIKELY(x) __builtin_expect((x),0)
|
||||
#else
|
||||
# define NOWIDE_LIKELY(x) (x)
|
||||
# define NOWIDE_UNLIKELY(x) (x)
|
||||
#endif
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// \brief The integral type type that can hold a Unicode code point
|
||||
///
|
||||
typedef uint32_t code_point;
|
||||
|
||||
///
|
||||
/// \brief Special constant that defines illegal code point
|
||||
///
|
||||
static const code_point illegal = 0xFFFFFFFFu;
|
||||
|
||||
///
|
||||
/// \brief Special constant that defines incomplete code point
|
||||
///
|
||||
static const code_point incomplete = 0xFFFFFFFEu;
|
||||
|
||||
///
|
||||
/// \brief the function checks if \a v is a valid code point
|
||||
///
|
||||
inline bool is_valid_codepoint(code_point v)
|
||||
{
|
||||
if(v>0x10FFFF)
|
||||
return false;
|
||||
if(0xD800 <=v && v<= 0xDFFF) // surragates
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef NOWIDE_DOXYGEN
|
||||
///
|
||||
/// \brief UTF Traits class - functions to convert UTF sequences to and from Unicode code points
|
||||
///
|
||||
template<typename CharType,int size=sizeof(CharType)>
|
||||
struct utf_traits {
|
||||
///
|
||||
/// The type of the character
|
||||
///
|
||||
typedef CharType char_type;
|
||||
///
|
||||
/// Read one code point from the range [p,e) and return it.
|
||||
///
|
||||
/// - If the sequence that was read is incomplete sequence returns \ref incomplete,
|
||||
/// - If illegal sequence detected returns \ref illegal
|
||||
///
|
||||
/// Requirements
|
||||
///
|
||||
/// - Iterator is valid input iterator
|
||||
///
|
||||
/// Postconditions
|
||||
///
|
||||
/// - p points to the last consumed character
|
||||
///
|
||||
template<typename Iterator>
|
||||
static code_point decode(Iterator &p,Iterator e);
|
||||
|
||||
///
|
||||
/// Maximal width of valid sequence in the code units:
|
||||
///
|
||||
/// - UTF-8 - 4
|
||||
/// - UTF-16 - 2
|
||||
/// - UTF-32 - 1
|
||||
///
|
||||
static const int max_width;
|
||||
///
|
||||
/// The width of specific code point in the code units.
|
||||
///
|
||||
/// Requirement: value is a valid Unicode code point
|
||||
/// Returns value in range [1..max_width]
|
||||
///
|
||||
static int width(code_point value);
|
||||
|
||||
///
|
||||
/// Get the size of the trail part of variable length encoded sequence.
|
||||
///
|
||||
/// Returns -1 if C is not valid lead character
|
||||
///
|
||||
static int trail_length(char_type c);
|
||||
///
|
||||
/// Returns true if c is trail code unit, always false for UTF-32
|
||||
///
|
||||
static bool is_trail(char_type c);
|
||||
///
|
||||
/// Returns true if c is lead code unit, always true of UTF-32
|
||||
///
|
||||
static bool is_lead(char_type c);
|
||||
|
||||
///
|
||||
/// Convert valid Unicode code point \a value to the UTF sequence.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// - \a value is valid code point
|
||||
/// - \a out is an output iterator should be able to accept at least width(value) units
|
||||
///
|
||||
/// Returns the iterator past the last written code unit.
|
||||
///
|
||||
template<typename Iterator>
|
||||
static Iterator encode(code_point value,Iterator out);
|
||||
///
|
||||
/// Decodes valid UTF sequence that is pointed by p into code point.
|
||||
///
|
||||
/// If the sequence is invalid or points to end the behavior is undefined
|
||||
///
|
||||
template<typename Iterator>
|
||||
static code_point decode_valid(Iterator &p);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename CharType,int size=sizeof(CharType)>
|
||||
struct utf_traits;
|
||||
|
||||
template<typename CharType>
|
||||
struct utf_traits<CharType,1> {
|
||||
|
||||
typedef CharType char_type;
|
||||
|
||||
static int trail_length(char_type ci)
|
||||
{
|
||||
unsigned char c = ci;
|
||||
if(c < 128)
|
||||
return 0;
|
||||
if(NOWIDE_UNLIKELY(c < 194))
|
||||
return -1;
|
||||
if(c < 224)
|
||||
return 1;
|
||||
if(c < 240)
|
||||
return 2;
|
||||
if(NOWIDE_LIKELY(c <=244))
|
||||
return 3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const int max_width = 4;
|
||||
|
||||
static int width(code_point value)
|
||||
{
|
||||
if(value <=0x7F) {
|
||||
return 1;
|
||||
}
|
||||
else if(value <=0x7FF) {
|
||||
return 2;
|
||||
}
|
||||
else if(NOWIDE_LIKELY(value <=0xFFFF)) {
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_trail(char_type ci)
|
||||
{
|
||||
unsigned char c=ci;
|
||||
return (c & 0xC0)==0x80;
|
||||
}
|
||||
|
||||
static bool is_lead(char_type ci)
|
||||
{
|
||||
return !is_trail(ci);
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
static code_point decode(Iterator &p,Iterator e)
|
||||
{
|
||||
if(NOWIDE_UNLIKELY(p==e))
|
||||
return incomplete;
|
||||
|
||||
unsigned char lead = *p++;
|
||||
|
||||
// First byte is fully validated here
|
||||
int trail_size = trail_length(lead);
|
||||
|
||||
if(NOWIDE_UNLIKELY(trail_size < 0))
|
||||
return illegal;
|
||||
|
||||
//
|
||||
// Ok as only ASCII may be of size = 0
|
||||
// also optimize for ASCII text
|
||||
//
|
||||
if(trail_size == 0)
|
||||
return lead;
|
||||
|
||||
code_point c = lead & ((1<<(6-trail_size))-1);
|
||||
|
||||
// Read the rest
|
||||
unsigned char tmp;
|
||||
switch(trail_size) {
|
||||
case 3:
|
||||
if(NOWIDE_UNLIKELY(p==e))
|
||||
return incomplete;
|
||||
tmp = *p++;
|
||||
if (!is_trail(tmp))
|
||||
return illegal;
|
||||
c = (c << 6) | ( tmp & 0x3F);
|
||||
case 2:
|
||||
if(NOWIDE_UNLIKELY(p==e))
|
||||
return incomplete;
|
||||
tmp = *p++;
|
||||
if (!is_trail(tmp))
|
||||
return illegal;
|
||||
c = (c << 6) | ( tmp & 0x3F);
|
||||
case 1:
|
||||
if(NOWIDE_UNLIKELY(p==e))
|
||||
return incomplete;
|
||||
tmp = *p++;
|
||||
if (!is_trail(tmp))
|
||||
return illegal;
|
||||
c = (c << 6) | ( tmp & 0x3F);
|
||||
}
|
||||
|
||||
// Check code point validity: no surrogates and
|
||||
// valid range
|
||||
if(NOWIDE_UNLIKELY(!is_valid_codepoint(c)))
|
||||
return illegal;
|
||||
|
||||
// make sure it is the most compact representation
|
||||
if(NOWIDE_UNLIKELY(width(c)!=trail_size + 1))
|
||||
return illegal;
|
||||
|
||||
return c;
|
||||
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
static code_point decode_valid(Iterator &p)
|
||||
{
|
||||
unsigned char lead = *p++;
|
||||
if(lead < 192)
|
||||
return lead;
|
||||
|
||||
int trail_size;
|
||||
|
||||
if(lead < 224)
|
||||
trail_size = 1;
|
||||
else if(NOWIDE_LIKELY(lead < 240)) // non-BMP rare
|
||||
trail_size = 2;
|
||||
else
|
||||
trail_size = 3;
|
||||
|
||||
code_point c = lead & ((1<<(6-trail_size))-1);
|
||||
|
||||
switch(trail_size) {
|
||||
case 3:
|
||||
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
|
||||
case 2:
|
||||
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
|
||||
case 1:
|
||||
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Iterator>
|
||||
static Iterator encode(code_point value,Iterator out)
|
||||
{
|
||||
if(value <= 0x7F) {
|
||||
*out++ = static_cast<char_type>(value);
|
||||
}
|
||||
else if(value <= 0x7FF) {
|
||||
*out++ = static_cast<char_type>((value >> 6) | 0xC0);
|
||||
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
|
||||
}
|
||||
else if(NOWIDE_LIKELY(value <= 0xFFFF)) {
|
||||
*out++ = static_cast<char_type>((value >> 12) | 0xE0);
|
||||
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
|
||||
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
|
||||
}
|
||||
else {
|
||||
*out++ = static_cast<char_type>((value >> 18) | 0xF0);
|
||||
*out++ = static_cast<char_type>(((value >> 12) & 0x3F) | 0x80);
|
||||
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
|
||||
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}; // utf8
|
||||
|
||||
template<typename CharType>
|
||||
struct utf_traits<CharType,2> {
|
||||
typedef CharType char_type;
|
||||
|
||||
// See RFC 2781
|
||||
static bool is_first_surrogate(uint16_t x)
|
||||
{
|
||||
return 0xD800 <=x && x<= 0xDBFF;
|
||||
}
|
||||
static bool is_second_surrogate(uint16_t x)
|
||||
{
|
||||
return 0xDC00 <=x && x<= 0xDFFF;
|
||||
}
|
||||
static code_point combine_surrogate(uint16_t w1,uint16_t w2)
|
||||
{
|
||||
return ((code_point(w1 & 0x3FF) << 10) | (w2 & 0x3FF)) + 0x10000;
|
||||
}
|
||||
static int trail_length(char_type c)
|
||||
{
|
||||
if(is_first_surrogate(c))
|
||||
return 1;
|
||||
if(is_second_surrogate(c))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
///
|
||||
/// Returns true if c is trail code unit, always false for UTF-32
|
||||
///
|
||||
static bool is_trail(char_type c)
|
||||
{
|
||||
return is_second_surrogate(c);
|
||||
}
|
||||
///
|
||||
/// Returns true if c is lead code unit, always true of UTF-32
|
||||
///
|
||||
static bool is_lead(char_type c)
|
||||
{
|
||||
return !is_second_surrogate(c);
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
static code_point decode(It ¤t,It last)
|
||||
{
|
||||
if(NOWIDE_UNLIKELY(current == last))
|
||||
return incomplete;
|
||||
uint16_t w1=*current++;
|
||||
if(NOWIDE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) {
|
||||
return w1;
|
||||
}
|
||||
if(w1 > 0xDBFF)
|
||||
return illegal;
|
||||
if(current==last)
|
||||
return incomplete;
|
||||
uint16_t w2=*current++;
|
||||
if(w2 < 0xDC00 || 0xDFFF < w2)
|
||||
return illegal;
|
||||
return combine_surrogate(w1,w2);
|
||||
}
|
||||
template<typename It>
|
||||
static code_point decode_valid(It ¤t)
|
||||
{
|
||||
uint16_t w1=*current++;
|
||||
if(NOWIDE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) {
|
||||
return w1;
|
||||
}
|
||||
uint16_t w2=*current++;
|
||||
return combine_surrogate(w1,w2);
|
||||
}
|
||||
|
||||
static const int max_width = 2;
|
||||
static int width(code_point u)
|
||||
{
|
||||
return u>=0x10000 ? 2 : 1;
|
||||
}
|
||||
template<typename It>
|
||||
static It encode(code_point u,It out)
|
||||
{
|
||||
if(NOWIDE_LIKELY(u<=0xFFFF)) {
|
||||
*out++ = static_cast<char_type>(u);
|
||||
}
|
||||
else {
|
||||
u -= 0x10000;
|
||||
*out++ = static_cast<char_type>(0xD800 | (u>>10));
|
||||
*out++ = static_cast<char_type>(0xDC00 | (u & 0x3FF));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}; // utf16;
|
||||
|
||||
|
||||
template<typename CharType>
|
||||
struct utf_traits<CharType,4> {
|
||||
typedef CharType char_type;
|
||||
static int trail_length(char_type c)
|
||||
{
|
||||
if(is_valid_codepoint(c))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
static bool is_trail(char_type /*c*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static bool is_lead(char_type /*c*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
static code_point decode_valid(It ¤t)
|
||||
{
|
||||
return *current++;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
static code_point decode(It ¤t,It last)
|
||||
{
|
||||
if(NOWIDE_UNLIKELY(current == last))
|
||||
return nowide::utf::incomplete;
|
||||
code_point c=*current++;
|
||||
if(NOWIDE_UNLIKELY(!is_valid_codepoint(c)))
|
||||
return nowide::utf::illegal;
|
||||
return c;
|
||||
}
|
||||
static const int max_width = 1;
|
||||
static int width(code_point /*u*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
template<typename It>
|
||||
static It encode(code_point u,It out)
|
||||
{
|
||||
*out++ = static_cast<char_type>(u);
|
||||
return out;
|
||||
}
|
||||
|
||||
}; // utf32
|
||||
|
||||
#endif
|
||||
|
||||
} // utf
|
||||
} // nowide
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#ifndef NOWIDE_WINDOWS_HPP_INCLUDED
|
||||
#define NOWIDE_WINDOWS_HPP_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef NOWIDE_USE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
//
|
||||
// These are function prototypes... Allow to to include windows.h
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
__declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void);
|
||||
__declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t *);
|
||||
__declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void);
|
||||
__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(wchar_t const *,int *);
|
||||
__declspec(dllimport) unsigned long __stdcall GetLastError();
|
||||
__declspec(dllimport) void* __stdcall LocalFree(void *);
|
||||
__declspec(dllimport) int __stdcall SetEnvironmentVariableW(wchar_t const *,wchar_t const *);
|
||||
__declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(wchar_t const *,wchar_t *,unsigned long);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
///
|
||||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
Reference in New Issue
Block a user