From c61e098066de255286659c72fc214d4531400637 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 14 Jun 2017 16:24:49 +0200 Subject: [PATCH] Integrated the not yet accepted boost::nowide library, thanks @alexrj. --- xs/MANIFEST | 15 + xs/src/boost/nowide/args.hpp | 167 ++++++ xs/src/boost/nowide/cenv.hpp | 126 +++++ xs/src/boost/nowide/config.hpp | 54 ++ xs/src/boost/nowide/convert.hpp | 154 ++++++ xs/src/boost/nowide/cstdio.hpp | 101 ++++ xs/src/boost/nowide/cstdlib.hpp | 16 + xs/src/boost/nowide/filebuf.hpp | 415 +++++++++++++++ xs/src/boost/nowide/fstream.hpp | 283 ++++++++++ .../boost/nowide/integration/filesystem.hpp | 28 + xs/src/boost/nowide/iostream.cpp | 261 +++++++++ xs/src/boost/nowide/iostream.hpp | 99 ++++ xs/src/boost/nowide/stackstring.hpp | 154 ++++++ xs/src/boost/nowide/system.hpp | 46 ++ xs/src/boost/nowide/utf8_codecvt.hpp | 499 ++++++++++++++++++ xs/src/boost/nowide/windows.hpp | 39 ++ 16 files changed, 2457 insertions(+) create mode 100644 xs/src/boost/nowide/args.hpp create mode 100644 xs/src/boost/nowide/cenv.hpp create mode 100644 xs/src/boost/nowide/config.hpp create mode 100644 xs/src/boost/nowide/convert.hpp create mode 100644 xs/src/boost/nowide/cstdio.hpp create mode 100644 xs/src/boost/nowide/cstdlib.hpp create mode 100644 xs/src/boost/nowide/filebuf.hpp create mode 100644 xs/src/boost/nowide/fstream.hpp create mode 100644 xs/src/boost/nowide/integration/filesystem.hpp create mode 100644 xs/src/boost/nowide/iostream.cpp create mode 100644 xs/src/boost/nowide/iostream.hpp create mode 100644 xs/src/boost/nowide/stackstring.hpp create mode 100644 xs/src/boost/nowide/system.hpp create mode 100644 xs/src/boost/nowide/utf8_codecvt.hpp create mode 100644 xs/src/boost/nowide/windows.hpp diff --git a/xs/MANIFEST b/xs/MANIFEST index ce172ec0d..182a0814a 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -8,6 +8,21 @@ src/admesh/stl.h src/admesh/stl_io.c src/admesh/stlinit.c src/admesh/util.c +src/boost/nowide/args.hpp +src/boost/nowide/cenv.hpp +src/boost/nowide/config.hpp +src/boost/nowide/convert.hpp +src/boost/nowide/cstdio.hpp +src/boost/nowide/cstdlib.hpp +src/boost/nowide/filebuf.hpp +src/boost/nowide/fstream.hpp +src/boost/nowide/integration/filesystem.hpp +src/boost/nowide/iostream.cpp +src/boost/nowide/iostream.hpp +src/boost/nowide/stackstring.hpp +src/boost/nowide/system.hpp +src/boost/nowide/utf8_codecvt.hpp +src/boost/nowide/windows.hpp src/clipper.cpp src/clipper.hpp src/eigen/COPYING.README diff --git a/xs/src/boost/nowide/args.hpp b/xs/src/boost/nowide/args.hpp new file mode 100644 index 000000000..bb806d02e --- /dev/null +++ b/xs/src/boost/nowide/args.hpp @@ -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 BOOST_NOWIDE_ARGS_HPP_INCLUDED +#define BOOST_NOWIDE_ARGS_HPP_INCLUDED + +#include +#include +#include +#ifdef BOOST_WINDOWS +#include +#endif + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_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 args_; + std::vector arg_values_; + stackstring env_; + std::vector envp_; + + int old_argc_; + char **old_argv_; + char **old_env_; + + int *old_argc_ptr_; + char ***old_argv_ptr_; + char ***old_env_ptr_; + }; + + #endif + +} // nowide +} // namespace boost +#endif + +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cenv.hpp b/xs/src/boost/nowide/cenv.hpp new file mode 100644 index 000000000..5f6d084af --- /dev/null +++ b/xs/src/boost/nowide/cenv.hpp @@ -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 BOOST_NOWIDE_CENV_H_INCLUDED +#define BOOST_NOWIDE_CENV_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_WINDOWS +#include +#endif + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_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 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(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 +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/config.hpp b/xs/src/boost/nowide/config.hpp new file mode 100644 index 000000000..d983109f3 --- /dev/null +++ b/xs/src/boost/nowide/config.hpp @@ -0,0 +1,54 @@ +// +// 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 BOOST_NOWIDE_CONFIG_HPP_INCLUDED +#define BOOST_NOWIDE_CONFIG_HPP_INCLUDED + +#include + +#ifndef BOOST_SYMBOL_VISIBLE +# define BOOST_SYMBOL_VISIBLE +#endif + +#ifdef BOOST_HAS_DECLSPEC +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) +# ifdef BOOST_NOWIDE_SOURCE +# define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT +# endif // BOOST_NOWIDE_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC + +#ifndef BOOST_NOWIDE_DECL +# define BOOST_NOWIDE_DECL +#endif + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NOWIDE_NO_LIB) && !defined(BOOST_NOWIDE_SOURCE) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_nowide +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + + +#endif // boost/nowide/config.hpp +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 \ No newline at end of file diff --git a/xs/src/boost/nowide/convert.hpp b/xs/src/boost/nowide/convert.hpp new file mode 100644 index 000000000..89b8871d0 --- /dev/null +++ b/xs/src/boost/nowide/convert.hpp @@ -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 BOOST_NOWIDE_CONVERT_H_INCLUDED +#define BOOST_NOWIDE_CONVERT_H_INCLUDED + +#include +#include + +namespace boost { +namespace nowide { + /// + /// \brief Template function that converts a buffer of UTF sequences in range [source_begin,source_end) + /// to the output \a buffer of size \a buffer_size. + /// + /// In case of success a NULL terminated string is 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 contents of the buffer are undefined. + /// + template + 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 boost::locale::utf; + code_point c = utf_traits::template decode(source_begin,source_end); + if(c==illegal || c==incomplete) { + rv = 0; + break; + } + size_t width = utf_traits::width(c); + if(buffer_size < width) { + rv=0; + break; + } + buffer = utf_traits::template encode(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 + Char const *basic_strend(Char const *s) + { + while(*s) + s++; + return s; + } + } + /// \endcond + + /// + /// Convert NULL terminated UTF source string to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success 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 NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success 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 NULL terminated UTF source string to NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success 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 NULL terminated \a output string of size at + /// most output_size (including NULL) + /// + /// In case of success 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. + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(wchar_t const *s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(char const *s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between Wide - UTF-16/32 string and UTF-8 string + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::string narrow(std::wstring const &s) + { + return boost::locale::conv::utf_to_utf(s); + } + /// + /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform + /// + /// boost::locale::conv::conversion_error is thrown in a case of a error + /// + inline std::wstring widen(std::string const &s) + { + return boost::locale::conv::utf_to_utf(s); + } + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cstdio.hpp b/xs/src/boost/nowide/cstdio.hpp new file mode 100644 index 000000000..d0bda97a0 --- /dev/null +++ b/xs/src/boost/nowide/cstdio.hpp @@ -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 BOOST_NOWIDE_CSTDIO_H_INCLUDED +#define BOOST_NOWIDE_CSTDIO_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4996) +#endif + + +namespace boost { +namespace nowide { +#if !defined(BOOST_WINDOWS) && !defined(BOOST_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 +/// +/// If 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 +/// +/// If 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 +/// +/// If 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 +/// +/// If 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 +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/cstdlib.hpp b/xs/src/boost/nowide/cstdlib.hpp new file mode 100644 index 000000000..27e20610a --- /dev/null +++ b/xs/src/boost/nowide/cstdlib.hpp @@ -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 BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED +#define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED + +#include +#include + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/filebuf.hpp b/xs/src/boost/nowide/filebuf.hpp new file mode 100644 index 000000000..2d6f4a443 --- /dev/null +++ b/xs/src/boost/nowide/filebuf.hpp @@ -0,0 +1,415 @@ +// +// 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 BOOST_NOWIDE_FILEBUF_HPP +#define BOOST_NOWIDE_FILEBUF_HPP + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4996 4244 4800) +#endif + + +namespace boost { +namespace nowide { +#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_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 > + 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 : public std::basic_streambuf { + 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; + } + bool ate = bool(mode & std::ios_base::ate); + if(ate) + mode = mode ^ std::ios_base::ate; + wchar_t const *smode = get_mode(mode); + if(!smode) + return 0; + wstackstring name; + if(!name.convert(s)) + return 0; + #ifdef BOOST_NOWIDE_FSTREAM_TESTS + FILE *f = ::fopen(s,boost::nowide::convert(smode).c_str()); + #else + FILE *f = ::_wfopen(name.c_str(),smode); + #endif + if(!f) + return 0; + if(ate && fseek(f,0,SEEK_END)!=0) { + fclose(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 BOOST_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;ptrprint_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 BOOST_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 BOOST_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::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 BOOST_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 filebuf; + + #endif // windows + +} // nowide +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/fstream.hpp b/xs/src/boost/nowide/fstream.hpp new file mode 100644 index 000000000..b0824a51b --- /dev/null +++ b/xs/src/boost/nowide/fstream.hpp @@ -0,0 +1,283 @@ +// +// 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 BOOST_NOWIDE_FSTREAM_INCLUDED_HPP +#define BOOST_NOWIDE_FSTREAM_INCLUDED_HPP + +//#include +#include +#include +#include +#include +#include +#include + +namespace boost { +/// +/// \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(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_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 but accepts UTF-8 strings under Windows + /// + template > + class basic_ifstream : public std::basic_istream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_istream 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); + } + + explicit basic_ifstream(std::string 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(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in) + { + open(file_name.c_str(),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: + boost::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_ofstream : public std::basic_ostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_ostream 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); + } + explicit basic_ofstream(std::string 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(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out) + { + open(file_name.c_str(),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: + boost::scoped_ptr buf_; + }; + + /// + /// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows + /// + + template > + class basic_fstream : public std::basic_iostream + { + public: + typedef basic_filebuf internal_buffer_type; + typedef std::basic_iostream 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); + } + explicit basic_fstream(std::string 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(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) + { + open(file_name.c_str(),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: + boost::scoped_ptr buf_; + }; + + + /// + /// \brief Same as std::filebuf but accepts UTF-8 strings under Windows + /// + typedef basic_filebuf filebuf; + /// + /// Same as std::ifstream but accepts UTF-8 strings under Windows + /// + typedef basic_ifstream ifstream; + /// + /// Same as std::ofstream but accepts UTF-8 strings under Windows + /// + typedef basic_ofstream ofstream; + /// + /// Same as std::fstream but accepts UTF-8 strings under Windows + /// + typedef basic_fstream fstream; + +#endif +} // nowide +} // namespace boost + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/integration/filesystem.hpp b/xs/src/boost/nowide/integration/filesystem.hpp new file mode 100644 index 000000000..c2a44b4ee --- /dev/null +++ b/xs/src/boost/nowide/integration/filesystem.hpp @@ -0,0 +1,28 @@ +// +// 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 BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED +#define BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED + +#include +#include +namespace boost { + namespace nowide { + /// + /// Instal utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8 strings + /// + inline void nowide_filesystem() + { + std::locale tmp = std::locale(std::locale(),new boost::nowide::utf8_codecvt()); + boost::filesystem::path::imbue(tmp); + } + } // nowide +} // boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/iostream.cpp b/xs/src/boost/nowide/iostream.cpp new file mode 100644 index 000000000..6b9099110 --- /dev/null +++ b/xs/src/boost/nowide/iostream.cpp @@ -0,0 +1,261 @@ +// +// 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) +// +#define BOOST_NOWIDE_SOURCE +#include +#include +#include +#include + +#ifdef BOOST_WINDOWS + +#ifndef NOMINMAX +# define NOMINMAX +#endif + + +#include + +namespace boost { +namespace nowide { +namespace details { + class console_output_buffer : public std::streambuf { + public: + console_output_buffer(HANDLE h) : + handle_(h), + isatty_(false) + { + if(handle_) { + DWORD dummy; + isatty_ = GetConsoleMode(handle_,&dummy) == TRUE; + } + } + protected: + int sync() + { + return overflow(EOF); + } + int overflow(int c) + { + if(!handle_) + return -1; + int n = pptr() - pbase(); + int r = 0; + + if(n > 0 && (r=write(pbase(),n)) < 0) + return -1; + if(r < n) { + memmove(pbase(),pbase() + r,n-r); + } + setp(buffer_, buffer_ + buffer_size); + pbump(n-r); + if(c!=EOF) + sputc(c); + return 0; + } + private: + + int write(char const *p,int n) + { + namespace uf = boost::locale::utf; + char const *b = p; + char const *e = p+n; + DWORD size=0; + if(!isatty_) { + if(!WriteFile(handle_,p,n,&size,0) || static_cast(size) != n) + return -1; + return n; + } + if(n > buffer_size) + return -1; + wchar_t *out = wbuffer_; + uf::code_point c; + size_t decoded = 0; + while(p < e && (c = uf::utf_traits::decode(p,e))!=uf::illegal && c!=uf::incomplete) { + out = uf::utf_traits::encode(c,out); + decoded = p-b; + } + if(c==uf::illegal) + return -1; + if(!WriteConsoleW(handle_,wbuffer_,out - wbuffer_,&size,0)) + return -1; + return decoded; + } + + static const int buffer_size = 1024; + char buffer_[buffer_size]; + wchar_t wbuffer_[buffer_size]; // for null + HANDLE handle_; + bool isatty_; + }; + + class console_input_buffer: public std::streambuf { + public: + console_input_buffer(HANDLE h) : + handle_(h), + isatty_(false), + wsize_(0) + { + if(handle_) { + DWORD dummy; + isatty_ = GetConsoleMode(handle_,&dummy) == TRUE; + } + } + + protected: + int pbackfail(int c) + { + if(c==EOF) + return EOF; + + if(gptr()!=eback()) { + gbump(-1); + *gptr() = c; + return 0; + } + + if(pback_buffer_.empty()) { + pback_buffer_.resize(4); + char *b = &pback_buffer_[0]; + char *e = b + pback_buffer_.size(); + setg(b,e-1,e); + *gptr() = c; + } + else { + size_t n = pback_buffer_.size(); + std::vector tmp; + tmp.resize(n*2); + memcpy(&tmp[n],&pback_buffer_[0],n); + tmp.swap(pback_buffer_); + char *b = &pback_buffer_[0]; + char *e = b + n * 2; + char *p = b+n-1; + *p = c; + setg(b,p,e); + } + + return 0; + } + + int underflow() + { + if(!handle_) + return -1; + if(!pback_buffer_.empty()) + pback_buffer_.clear(); + + size_t n = read(); + setg(buffer_,buffer_,buffer_+n); + if(n == 0) + return EOF; + return std::char_traits::to_int_type(*gptr()); + } + + private: + + size_t read() + { + namespace uf = boost::locale::utf; + if(!isatty_) { + DWORD read_bytes = 0; + if(!ReadFile(handle_,buffer_,buffer_size,&read_bytes,0)) + return 0; + return read_bytes; + } + DWORD read_wchars = 0; + size_t n = wbuffer_size - wsize_; + if(!ReadConsoleW(handle_,wbuffer_,n,&read_wchars,0)) + return 0; + wsize_ += read_wchars; + char *out = buffer_; + wchar_t *b = wbuffer_; + wchar_t *e = b + wsize_; + wchar_t *p = b; + uf::code_point c; + wsize_ = e-p; + while(p < e && (c = uf::utf_traits::decode(p,e))!=uf::illegal && c!=uf::incomplete) { + out = uf::utf_traits::encode(c,out); + wsize_ = e-p; + } + + if(c==uf::illegal) + return -1; + + + if(c==uf::incomplete) { + memmove(b,e-wsize_,sizeof(wchar_t)*wsize_); + } + + return out - buffer_; + } + + static const size_t buffer_size = 1024 * 3; + static const size_t wbuffer_size = 1024; + char buffer_[buffer_size]; + wchar_t wbuffer_[buffer_size]; // for null + HANDLE handle_; + bool isatty_; + int wsize_; + std::vector pback_buffer_; + }; + + winconsole_ostream::winconsole_ostream(int fd) : std::ostream(0) + { + HANDLE h = 0; + switch(fd) { + case 1: + h = GetStdHandle(STD_OUTPUT_HANDLE); + break; + case 2: + h = GetStdHandle(STD_ERROR_HANDLE); + break; + } + d.reset(new console_output_buffer(h)); + std::ostream::rdbuf(d.get()); + } + + winconsole_ostream::~winconsole_ostream() + { + } + + winconsole_istream::winconsole_istream() : std::istream(0) + { + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + d.reset(new console_input_buffer(h)); + std::istream::rdbuf(d.get()); + } + + winconsole_istream::~winconsole_istream() + { + } + +} // details + +BOOST_NOWIDE_DECL details::winconsole_istream cin; +BOOST_NOWIDE_DECL details::winconsole_ostream cout(1); +BOOST_NOWIDE_DECL details::winconsole_ostream cerr(2); +BOOST_NOWIDE_DECL details::winconsole_ostream clog(2); + +namespace { + struct initialize { + initialize() + { + boost::nowide::cin.tie(&boost::nowide::cout); + boost::nowide::cerr.tie(&boost::nowide::cout); + boost::nowide::clog.tie(&boost::nowide::cout); + } + } inst; +} + + + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/iostream.hpp b/xs/src/boost/nowide/iostream.hpp new file mode 100644 index 000000000..6ab004a25 --- /dev/null +++ b/xs/src/boost/nowide/iostream.hpp @@ -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 BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED +#define BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251) +#endif + + +namespace boost { +namespace nowide { + #if !defined(BOOST_WINDOWS) && !defined(BOOST_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 BOOST_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: + boost::scoped_ptr d; + }; + + class BOOST_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; + boost::scoped_ptr 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 BOOST_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 BOOST_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 BOOST_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 BOOST_NOWIDE_DECL details::winconsole_ostream clog; + + #endif + +} // nowide +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/stackstring.hpp b/xs/src/boost/nowide/stackstring.hpp new file mode 100644 index 000000000..948a22f7f --- /dev/null +++ b/xs/src/boost/nowide/stackstring.hpp @@ -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 BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#define BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED +#include +#include +#include + +namespace boost { +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 +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 wstackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring wshort_stackstring; +/// +/// Convinience typedef +/// +typedef basic_stackstring short_stackstring; + + +} // nowide +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/system.hpp b/xs/src/boost/nowide/system.hpp new file mode 100644 index 000000000..a1fc97505 --- /dev/null +++ b/xs/src/boost/nowide/system.hpp @@ -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 BOOST_NOWIDE_CSTDLIB_HPP +#define BOOST_NOWIDE_CSTDLIB_HPP + +#include +#include +#include +namespace boost { +namespace nowide { + +#if !defined(BOOST_WINDOWS) && !defined(BOOST_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 +} // namespace boost + +#endif +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/xs/src/boost/nowide/utf8_codecvt.hpp b/xs/src/boost/nowide/utf8_codecvt.hpp new file mode 100644 index 000000000..cc5046fc8 --- /dev/null +++ b/xs/src/boost/nowide/utf8_codecvt.hpp @@ -0,0 +1,499 @@ +// +// Copyright (c) 2015 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 BOOST_NOWIDE_UTF8_CODECVT_HPP +#define BOOST_NOWIDE_UTF8_CODECVT_HPP + +#include +#include +#include +#include + +namespace boost { +namespace nowide { + +// +// Make sure that mbstate can keep 16 bit of UTF-16 sequence +// +BOOST_STATIC_ASSERT(sizeof(std::mbstate_t)>=2); + +#ifdef _MSC_VER +// MSVC do_length is non-standard it counts wide characters instead of narrow and does not change mbstate +#define BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST +#endif + +template +class utf8_codecvt; + +template +class utf8_codecvt : public std::codecvt +{ +public: + utf8_codecvt(size_t refs = 0) : std::codecvt(refs) + { + } +protected: + + typedef CharType uchar; + + virtual std::codecvt_base::result do_unshift(std::mbstate_t &s,char *from,char * /*to*/,char *&next) const + { + boost::uint16_t &state = *reinterpret_cast(&s); +#ifdef DEBUG_CODECVT + std::cout << "Entering unshift " << std::hex << state << std::dec << std::endl; +#endif + if(state != 0) + return std::codecvt_base::error; + next=from; + return std::codecvt_base::ok; + } + virtual int do_encoding() const throw() + { + return 0; + } + virtual int do_max_length() const throw() + { + return 4; + } + virtual bool do_always_noconv() const throw() + { + return false; + } + + virtual int + do_length( std::mbstate_t + #ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + const + #endif + &std_state, + char const *from, + char const *from_end, + size_t max) const + { + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + char const *save_from = from; + boost::uint16_t &state = *reinterpret_cast(&std_state); + #else + size_t save_max = max; + boost::uint16_t state = *reinterpret_cast(&std_state); + #endif + while(max > 0 && from < from_end){ + char const *prev_from = from; + boost::uint32_t ch=boost::locale::utf::utf_traits::decode(from,from_end); + if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) { + from = prev_from; + break; + } + max --; + if(ch > 0xFFFF) { + if(state == 0) { + from = prev_from; + state = 1; + } + else { + state = 0; + } + } + } + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + return from - save_from; + #else + return save_max - max; + #endif + } + + + virtual std::codecvt_base::result + do_in( std::mbstate_t &std_state, + char const *from, + char const *from_end, + char const *&from_next, + uchar *to, + uchar *to_end, + uchar *&to_next) const + { + std::codecvt_base::result r=std::codecvt_base::ok; + + // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) + // according to standard. We use it to keep a flag 0/1 for surrogate pair writing + // + // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd + // and first pair is written, but no input consumed + boost::uint16_t &state = *reinterpret_cast(&std_state); + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering IN--------------" << std::endl; + std::cout << "State " << std::hex << state <::decode(from,from_end); + + if(ch==boost::locale::utf::illegal) { + from = from_saved; + r=std::codecvt_base::error; + break; + } + if(ch==boost::locale::utf::incomplete) { + from = from_saved; + r=std::codecvt_base::partial; + break; + } + // Normal codepoints go direcly to stream + if(ch <= 0xFFFF) { + *to++=ch; + } + else { + // for other codepoints we do following + // + // 1. We can't consume our input as we may find ourselfs + // in state where all input consumed but not all output written,i.e. only + // 1st pair is written + // 2. We only write first pair and mark this in the state, we also revert back + // the from pointer in order to make sure this codepoint would be read + // once again and then we would consume our input together with writing + // second surrogate pair + ch-=0x10000; + boost::uint16_t vh = ch >> 10; + boost::uint16_t vl = ch & 0x3FF; + boost::uint16_t w1 = vh + 0xD800; + boost::uint16_t w2 = vl + 0xDC00; + if(state == 0) { + from = from_saved; + *to++ = w1; + state = 1; + } + else { + *to++ = w2; + state = 0; + } + } + } + from_next=from; + to_next=to; + if(r == std::codecvt_base::ok && (from!=from_end || state!=0)) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state <=2 in order + // to be able to store first observerd surrogate pair + // + // State: state!=0 - a first surrogate pair was observerd (state = first pair), + // we expect the second one to come and then zero the state + /// + boost::uint16_t &state = *reinterpret_cast(&std_state); + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering OUT --------------" << std::endl; + std::cout << "State " << std::hex << state <::width(ch); + if(to_end - to < len) { + r=std::codecvt_base::partial; + break; + } + to = boost::locale::utf::utf_traits::encode(ch,to); + state = 0; + from++; + } + from_next=from; + to_next=to; + if(r==std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state < +class utf8_codecvt : public std::codecvt +{ +public: + utf8_codecvt(size_t refs = 0) : std::codecvt(refs) + { + } +protected: + + typedef CharType uchar; + + virtual std::codecvt_base::result do_unshift(std::mbstate_t &/*s*/,char *from,char * /*to*/,char *&next) const + { + next=from; + return std::codecvt_base::ok; + } + virtual int do_encoding() const throw() + { + return 0; + } + virtual int do_max_length() const throw() + { + return 4; + } + virtual bool do_always_noconv() const throw() + { + return false; + } + + virtual int + do_length( std::mbstate_t + #ifdef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + const + #endif + &/*state*/, + char const *from, + char const *from_end, + size_t max) const + { + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + char const *start_from = from; + #else + size_t save_max = max; + #endif + + while(max > 0 && from < from_end){ + char const *save_from = from; + boost::uint32_t ch=boost::locale::utf::utf_traits::decode(from,from_end); + if(ch==boost::locale::utf::incomplete || ch==boost::locale::utf::illegal) { + from = save_from; + break; + } + max--; + } + #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST + return from - start_from; + #else + return save_max - max; + #endif + } + + + virtual std::codecvt_base::result + do_in( std::mbstate_t &/*state*/, + char const *from, + char const *from_end, + char const *&from_next, + uchar *to, + uchar *to_end, + uchar *&to_next) const + { + std::codecvt_base::result r=std::codecvt_base::ok; + + // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) + // according to standard. We use it to keep a flag 0/1 for surrogate pair writing + // + // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observerd + // and first pair is written, but no input consumed + while(to < to_end && from < from_end) + { +#ifdef DEBUG_CODECVT + std::cout << "Entering IN--------------" << std::endl; + std::cout << "State " << std::hex << state <::decode(from,from_end); + + if(ch==boost::locale::utf::illegal) { + r=std::codecvt_base::error; + from = from_saved; + break; + } + if(ch==boost::locale::utf::incomplete) { + r=std::codecvt_base::partial; + from=from_saved; + break; + } + *to++=ch; + } + from_next=from; + to_next=to; + if(r == std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state <::width(ch); + if(to_end - to < len) { + r=std::codecvt_base::partial; + break; + } + to = boost::locale::utf::utf_traits::encode(ch,to); + from++; + } + from_next=from; + to_next=to; + if(r==std::codecvt_base::ok && from!=from_end) + r = std::codecvt_base::partial; +#ifdef DEBUG_CODECVT + std::cout << "Returning "; + switch(r) { + case std::codecvt_base::ok: + std::cout << "ok" << std::endl; + break; + case std::codecvt_base::partial: + std::cout << "partial" << std::endl; + break; + case std::codecvt_base::error: + std::cout << "error" << std::endl; + break; + default: + std::cout << "other" << std::endl; + break; + } + std::cout << "State " << std::hex << state < + +#ifdef BOOST_NOWIDE_USE_WINDOWS_H +#include +#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