diff --git a/.travis.yml b/.travis.yml
index 5fd85ab..0128bbc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -262,8 +262,14 @@ script:
else
false
fi
+ # DYLD_LIBRARY_PATH causes problems on system() spawned processes
+ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ LINK=static
+ else
+ LINK=static,shared
+ fi
- which $TRAVIS_COMPILER
- $TRAVIS_COMPILER --version
- |
echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam
- - ./b2 -j3 libs/nowide/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined define=UBSAN=1 debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} ${VISIBILITY:+visibility=$VISIBILITY}
+ - ./b2 -j3 libs/nowide/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release link=$LINK ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined define=UBSAN=1 debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} ${VISIBILITY:+visibility=$VISIBILITY}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42e31cd..2529b14 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,7 +44,7 @@ endif()
# Using glob here is ok as it is only for headers
file(GLOB_RECURSE headers include/*.hpp)
-add_library(boost_nowide src/iostream.cpp ${headers})
+add_library(boost_nowide src/cstdio.cpp src/cstdlib.cpp src/iostream.cpp ${headers})
add_library(Boost::nowide ALIAS boost_nowide)
set_target_properties(boost_nowide PROPERTIES
CXX_VISIBILITY_PRESET hidden
diff --git a/appveyor.yml b/appveyor.yml
index 48760af..50cbe79 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -13,7 +13,7 @@ branches:
- /feature\/.*/
matrix:
- fast_finish: true
+ fast_finish: false
environment:
matrix:
@@ -81,7 +81,7 @@ test_script:
- PATH=%ADDPATH%%PATH%
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- - b2 -j3 libs/nowide/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
+ - b2 -j3 libs/nowide/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release link=shared,static
- ps: |
If ("$env:BOOST_CMAKE" -eq "1") {
./b2 --clean
diff --git a/build/Jamfile.v2 b/build/Jamfile.v2
index 95d5632..639492d 100644
--- a/build/Jamfile.v2
+++ b/build/Jamfile.v2
@@ -14,7 +14,7 @@ project boost/nowide
shared:BOOST_NOWIDE_DYN_LINK=1
;
-SOURCES = iostream ;
+SOURCES = cstdio cstdlib iostream ;
lib boost_nowide
: $(SOURCES).cpp
diff --git a/include/boost/nowide/config.hpp b/include/boost/nowide/config.hpp
index ab14944..15f24b5 100644
--- a/include/boost/nowide/config.hpp
+++ b/include/boost/nowide/config.hpp
@@ -46,22 +46,31 @@
#include
#endif // auto-linking disabled
-/// @def BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
-/// @brief Define to 1 to use internal classes from fstream.hpp
+/// @def BOOST_NOWIDE_USE_WCHAR_OVERLOADS
+/// @brief Whether to use the wchar_t* overloads in fstream/filebuf
+/// Enabled on Windows and Cygwin as the latter may use wchar_t in filesystem::path
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#define BOOST_NOWIDE_USE_WCHAR_OVERLOADS 1
+#else
+#define BOOST_NOWIDE_USE_WCHAR_OVERLOADS 0
+#endif
+
+/// @def BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+/// @brief Define to 1 to use internal class from filebuf.hpp
///
-/// - On Non-Windows platforms: Define to 1 to use the same classes from header
-/// that are used on Windows.
+/// - On Non-Windows platforms: Define to 1 to use the same class from header
+/// that is used on Windows.
/// - On Windows: No effect, always overwritten to 1
///
/// Affects boost::nowide::basic_filebuf,
/// boost::nowide::basic_ofstream, boost::nowide::basic_ifstream, boost::nowide::basic_fstream
-#if defined(BOOST_WINDOWS)
-#ifdef BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
-#undef BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
+#if defined(BOOST_WINDOWS) || BOOST_NOWIDE_USE_WCHAR_OVERLOADS
+#ifdef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+#undef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
#endif
-#define BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS 1
-#elif !defined(BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS)
-#define BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS 0
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 1
+#elif !defined(BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT)
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 0
#endif
#if BOOST_VERSION < 106500 && defined(BOOST_GCC) && __GNUC__ >= 7
diff --git a/include/boost/nowide/cstdio.hpp b/include/boost/nowide/cstdio.hpp
index 7a313ad..bf48045 100644
--- a/include/boost/nowide/cstdio.hpp
+++ b/include/boost/nowide/cstdio.hpp
@@ -1,5 +1,6 @@
//
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -8,18 +9,9 @@
#ifndef BOOST_NOWIDE_CSTDIO_HPP_INCLUDED
#define BOOST_NOWIDE_CSTDIO_HPP_INCLUDED
-#include
-
-#ifdef BOOST_WINDOWS
-#include
-#endif
+#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)
@@ -32,43 +24,24 @@ namespace nowide {
///
/// \brief Same as freopen but file_name and mode are UTF-8 strings
///
- inline FILE* freopen(const char* file_name, const char* mode, FILE* stream)
- {
- const wstackstring wname(file_name);
- const wshort_stackstring wmode(mode);
- return _wfreopen(wname.get(), wmode.get(), stream);
- }
+ BOOST_NOWIDE_DECL FILE* freopen(const char* file_name, const char* mode, FILE* stream);
///
/// \brief Same as fopen but file_name and mode are UTF-8 strings
///
- inline FILE* fopen(const char* file_name, const char* mode)
- {
- const wstackstring wname(file_name);
- const wshort_stackstring wmode(mode);
- return _wfopen(wname.get(), wmode.get());
- }
+ BOOST_NOWIDE_DECL FILE* fopen(const char* file_name, const char* mode);
///
/// \brief Same as rename but old_name and new_name are UTF-8 strings
///
- inline int rename(const char* old_name, const char* new_name)
- {
- const wstackstring wold(old_name), wnew(new_name);
- return _wrename(wold.get(), wnew.get());
- }
+ BOOST_NOWIDE_DECL int rename(const char* old_name, const char* new_name);
///
/// \brief Same as rename but name is UTF-8 string
///
- inline int remove(const char* name)
- {
- const wstackstring wname(name);
- return _wremove(wname.get());
- }
+ BOOST_NOWIDE_DECL int remove(const char* name);
#endif
+ namespace detail {
+ BOOST_NOWIDE_DECL FILE* wfopen(const wchar_t* filename, const wchar_t* mode);
+ }
} // namespace nowide
} // namespace boost
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
#endif
diff --git a/include/boost/nowide/cstdlib.hpp b/include/boost/nowide/cstdlib.hpp
index 3385fbb..657222e 100644
--- a/include/boost/nowide/cstdlib.hpp
+++ b/include/boost/nowide/cstdlib.hpp
@@ -8,12 +8,8 @@
#ifndef BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED
#define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED
-#include
-#ifdef BOOST_WINDOWS
-#include
-#include
-#include
-#else
+#include
+#if !BOOST_WINDOWS
#include
#endif
@@ -21,9 +17,6 @@ namespace boost {
namespace nowide {
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
using std::getenv;
- using ::setenv;
- using ::unsetenv;
- using ::putenv;
using std::system;
#else
///
@@ -31,91 +24,43 @@ namespace nowide {
///
/// This function is not thread safe or reenterable as defined by the standard library
///
- inline char* getenv(const char* key)
- {
- static stackstring value;
-
- const wshort_stackstring name(key);
-
- static const size_t buf_size = 64;
- wchar_t buf[buf_size];
- std::vector tmp;
- wchar_t* ptr = buf;
- size_t n = GetEnvironmentVariableW(name.get(), 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.get(), &tmp[0], static_cast(tmp.size() - 1));
- // The size may have changed
- if(n >= tmp.size() - 1)
- return 0;
- ptr = &tmp[0];
- }
- value.convert(ptr);
- return value.get();
- }
- ///
- /// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value,
- ///
- /// if overwrite is not 0, that the old value is always overwritten, otherwise,
- /// if the variable exists it remains unchanged
- ///
- inline int setenv(const char* key, const char* value, int overwrite)
- {
- const wshort_stackstring name(key);
- if(!overwrite)
- {
- wchar_t unused[2];
- if(GetEnvironmentVariableW(name.get(), unused, 2) != 0 || GetLastError() != 203) // ERROR_ENVVAR_NOT_FOUND
- return 0;
- }
- const wstackstring wval(value);
- if(SetEnvironmentVariableW(name.get(), wval.get()))
- return 0;
- return -1;
- }
- ///
- /// \brief Remove environment variable \a key
- ///
- inline int unsetenv(const char* key)
- {
- const wshort_stackstring name(key);
- if(SetEnvironmentVariableW(name.get(), 0))
- return 0;
- return -1;
- }
- ///
- /// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE
- ///
- inline int putenv(char* string)
- {
- const char* key = string;
- const char* key_end = string;
- while(*key_end != '=' && *key_end != '\0')
- key_end++;
- if(*key_end == '\0')
- return -1;
- const wshort_stackstring wkey(key, key_end);
- const wstackstring wvalue(key_end + 1);
-
- if(SetEnvironmentVariableW(wkey.get(), wvalue.get()))
- return 0;
- return -1;
- }
+ BOOST_NOWIDE_DECL char* getenv(const char* key);
///
/// Same as std::system but cmd is UTF-8.
///
- inline int system(const char* cmd)
- {
- if(!cmd)
- return _wsystem(0);
- const wstackstring wcmd(cmd);
- return _wsystem(wcmd.get());
- }
+ BOOST_NOWIDE_DECL int system(const char* cmd);
+
#endif
+ ///
+ /// \brief Set environment variable \a key to \a value
+ ///
+ /// if overwrite is not 0, that the old value is always overwritten, otherwise,
+ /// if the variable exists it remains unchanged
+ ///
+ /// \a key and \a value are UTF-8 on Windows
+ /// \return zero on success, else nonzero
+ ///
+ BOOST_NOWIDE_DECL int setenv(const char* key, const char* value, int overwrite);
+
+ ///
+ /// \brief Remove environment variable \a key
+ ///
+ /// \a key is UTF-8 on Windows
+ /// \return zero on success, else nonzero
+ ///
+ BOOST_NOWIDE_DECL int unsetenv(const char* key);
+
+ ///
+ /// \brief Adds or changes an environment variable, \a string must be in format KEY=VALUE
+ ///
+ /// \a string MAY become part of the environment, hence changes to the value MAY change
+ /// the environment. For portability it is hence recommended NOT to change it.
+ /// \a string is UTF-8 on Windows
+ /// \return zero on success, else nonzero
+ ///
+ BOOST_NOWIDE_DECL int putenv(char* string);
+
} // namespace nowide
} // namespace boost
diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp
index 4fbe428..aa4c1be 100644
--- a/include/boost/nowide/filebuf.hpp
+++ b/include/boost/nowide/filebuf.hpp
@@ -1,6 +1,6 @@
//
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
-// Copyright (c) 2019 Alexander Grund
+// Copyright (c) 2019-2020 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -10,7 +10,8 @@
#define BOOST_NOWIDE_FILEBUF_HPP_INCLUDED
#include
-#if BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
+#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+#include
#include
#include
#include
@@ -23,18 +24,12 @@
#include
#endif
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable : 4996 4244 4800)
-#endif
-
namespace boost {
namespace nowide {
-#if !BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS && !defined(BOOST_NOWIDE_DOXYGEN)
+#if !BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT && !defined(BOOST_NOWIDE_DOXYGEN)
using std::basic_filebuf;
using std::filebuf;
#else // Windows
-
///
/// \brief This forward declaration defines the basic_filebuf type.
///
@@ -97,20 +92,13 @@ namespace nowide {
if(is_open())
return NULL;
validate_cvt(this->getloc());
- const bool ate = bool(mode & std::ios_base::ate);
+ const bool ate = (mode & std::ios_base::ate) != 0;
if(ate)
- mode = mode ^ std::ios_base::ate;
+ mode &= ~std::ios_base::ate;
const wchar_t* smode = get_mode(mode);
if(!smode)
return 0;
-#ifdef BOOST_WINDOWS
- file_ = ::_wfopen(s, smode);
-#else
- const stackstring name(s);
- const short_stackstring smode2(smode);
- file_ = std::fopen(name.get(), smode2.get());
-#endif
-
+ file_ = detail::wfopen(s, smode);
if(!file_)
return 0;
if(ate && std::fseek(file_, 0, SEEK_END) != 0)
@@ -177,7 +165,7 @@ namespace nowide {
if(owns_buffer_)
delete[] buffer_;
buffer_ = s;
- buffer_size_ = (n >= 0) ? n : 0;
+ buffer_size_ = (n >= 0) ? static_cast(n) : 0;
return this;
}
@@ -197,7 +185,7 @@ namespace nowide {
setp(buffer_, buffer_ + buffer_size_);
if(c != EOF)
{
- *buffer_ = c;
+ *buffer_ = Traits::to_char_type(c);
pbump(1);
}
} else if(c != EOF)
@@ -206,7 +194,7 @@ namespace nowide {
{
make_buffer();
setp(buffer_, buffer_ + buffer_size_);
- *buffer_ = c;
+ *buffer_ = Traits::to_char_type(c);
pbump(1);
} else if(std::fputc(c, file_) == EOF)
{
@@ -247,7 +235,7 @@ namespace nowide {
const int c = std::fgetc(file_);
if(c == EOF)
return EOF;
- last_char_ = c;
+ last_char_ = Traits::to_char_type(c);
setg(&last_char_, &last_char_, &last_char_ + 1);
} else
{
@@ -305,7 +293,8 @@ namespace nowide {
case std::ios_base::end: whence = SEEK_END; break;
default: assert(false); return EOF;
}
- if(std::fseek(file_, off, whence) != 0)
+ assert(off <= std::numeric_limits::max());
+ if(std::fseek(file_, static_cast(off), whence) != 0)
return EOF;
return std::ftell(file_);
}
@@ -330,7 +319,7 @@ namespace nowide {
const std::streamsize off = gptr() - egptr();
setg(0, 0, 0);
assert(off <= std::numeric_limits::max());
- if(off && std::fseek(file_, off, SEEK_CUR) != 0)
+ if(off && std::fseek(file_, static_cast(off), SEEK_CUR) != 0)
return false;
}
return true;
@@ -427,8 +416,4 @@ namespace nowide {
} // namespace nowide
} // namespace boost
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
#endif
diff --git a/include/boost/nowide/fstream.hpp b/include/boost/nowide/fstream.hpp
index 0d22fa8..754c528 100644
--- a/include/boost/nowide/fstream.hpp
+++ b/include/boost/nowide/fstream.hpp
@@ -77,7 +77,7 @@ namespace nowide {
{
open(file_name, mode);
}
-#ifdef BOOST_WINDOWS
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
explicit basic_ifstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::in)
{
open(file_name, mode);
@@ -118,7 +118,7 @@ namespace nowide {
{
open(file_name, mode);
}
-#ifdef BOOST_WINDOWS
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
explicit basic_ofstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::out)
{
open(file_name, mode);
@@ -162,7 +162,7 @@ namespace nowide {
{
open(file_name, mode);
}
-#ifdef BOOST_WINDOWS
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
explicit basic_fstream(const wchar_t* file_name,
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
{
@@ -187,9 +187,6 @@ namespace nowide {
using fstream_impl::close;
using fstream_impl::rdbuf;
};
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
///
/// Same as std::filebuf but accepts UTF-8 strings under Windows
@@ -225,6 +222,7 @@ namespace nowide {
public T_StreamType::template stream_base::type
{
typedef basic_filebuf internal_buffer_type;
+ typedef buf_holder base_buf_holder;
typedef typename T_StreamType::template stream_base::type stream_base;
public:
@@ -232,7 +230,9 @@ namespace nowide {
using stream_base::clear;
protected:
- fstream_impl() : stream_base(rdbuf())
+ using base_buf_holder::buf_;
+
+ fstream_impl() : stream_base(&buf_)
{}
void open(const std::string& file_name, std::ios_base::openmode mode = T_StreamType::mode())
@@ -243,7 +243,7 @@ namespace nowide {
typename detail::enable_if_path::type open(const Path& file_name,
std::ios_base::openmode mode = T_StreamType::mode())
{
- return open(file_name.c_str(), mode);
+ open(file_name.c_str(), mode);
}
void open(const char* file_name, std::ios_base::openmode mode = T_StreamType::mode())
{
@@ -252,7 +252,7 @@ namespace nowide {
else
clear();
}
-#ifdef BOOST_WINDOWS
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
void open(const wchar_t* file_name, std::ios_base::openmode mode = T_StreamType::mode())
{
if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
@@ -277,10 +277,12 @@ namespace nowide {
internal_buffer_type* rdbuf() const
{
- return const_cast(&this->buf_);
+ return const_cast(&buf_);
}
};
-
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
/// Trait to heuristically check for a *::filesystem::path
/// Done by checking for make_preferred and filename member functions with correct signature
template
diff --git a/include/boost/nowide/stackstring.hpp b/include/boost/nowide/stackstring.hpp
index 555f733..39de405 100644
--- a/include/boost/nowide/stackstring.hpp
+++ b/include/boost/nowide/stackstring.hpp
@@ -34,50 +34,6 @@ namespace nowide {
typedef CharOut output_char;
typedef CharIn input_char;
- basic_stackstring(const basic_stackstring& other) : data_(NULL)
- {
- *this = other;
- }
-
- friend void swap(basic_stackstring& lhs, basic_stackstring& rhs)
- {
- if(lhs.uses_stack_memory())
- {
- if(rhs.uses_stack_memory())
- {
- for(size_t i = 0; i < buffer_size; i++)
- std::swap(lhs.buffer_[i], rhs.buffer_[i]);
- } else
- {
- lhs.data_ = rhs.data_;
- rhs.data_ = rhs.buffer_;
- for(size_t i = 0; i < buffer_size; i++)
- rhs.buffer_[i] = lhs.buffer_[i];
- }
- } else if(rhs.uses_stack_memory())
- {
- rhs.data_ = lhs.data_;
- lhs.data_ = lhs.buffer_;
- for(size_t i = 0; i < buffer_size; i++)
- lhs.buffer_[i] = rhs.buffer_[i];
- } else
- std::swap(lhs.data_, rhs.data_);
- }
- basic_stackstring& operator=(const basic_stackstring& other)
- {
- if(this != &other)
- {
- clear();
- const size_t len = other.length();
- if(other.uses_stack_memory())
- data_ = buffer_;
- else
- data_ = new output_char[len + 1];
- std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1));
- }
- return *this;
- }
-
basic_stackstring() : data_(NULL)
{
buffer_[0] = 0;
@@ -90,6 +46,36 @@ namespace nowide {
{
convert(begin, end);
}
+
+ basic_stackstring(const basic_stackstring& other) : data_(NULL)
+ {
+ *this = other;
+ }
+ basic_stackstring& operator=(const basic_stackstring& other)
+ {
+ if(this != &other)
+ {
+ clear();
+ const size_t len = other.length();
+ if(other.uses_stack_memory())
+ data_ = buffer_;
+ else if(other.data_)
+ data_ = new output_char[len + 1];
+ else
+ {
+ data_ = NULL;
+ return *this;
+ }
+ std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1));
+ }
+ return *this;
+ }
+
+ ~basic_stackstring()
+ {
+ clear();
+ }
+
output_char* convert(const input_char* input)
{
if(input)
@@ -132,9 +118,30 @@ namespace nowide {
delete[] data_;
data_ = NULL;
}
- ~basic_stackstring()
+
+ friend void swap(basic_stackstring& lhs, basic_stackstring& rhs)
{
- clear();
+ if(lhs.uses_stack_memory())
+ {
+ if(rhs.uses_stack_memory())
+ {
+ for(size_t i = 0; i < buffer_size; i++)
+ std::swap(lhs.buffer_[i], rhs.buffer_[i]);
+ } else
+ {
+ lhs.data_ = rhs.data_;
+ rhs.data_ = rhs.buffer_;
+ for(size_t i = 0; i < buffer_size; i++)
+ rhs.buffer_[i] = lhs.buffer_[i];
+ }
+ } else if(rhs.uses_stack_memory())
+ {
+ rhs.data_ = lhs.data_;
+ lhs.data_ = lhs.buffer_;
+ for(size_t i = 0; i < buffer_size; i++)
+ lhs.buffer_[i] = rhs.buffer_[i];
+ } else
+ std::swap(lhs.data_, rhs.data_);
}
private:
diff --git a/src/cstdio.cpp b/src/cstdio.cpp
new file mode 100644
index 0000000..0b0e75c
--- /dev/null
+++ b/src/cstdio.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
+//
+// 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
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__)
+// Need the _w* functions which are extensions on MinGW/Cygwin
+#undef __STRICT_ANSI__
+#endif
+
+#include
+#include
+
+namespace boost {
+namespace nowide {
+ namespace detail {
+ FILE* wfopen(const wchar_t* filename, const wchar_t* mode)
+ {
+#ifdef BOOST_WINDOWS
+ return ::_wfopen(filename, mode);
+#else
+ const stackstring name(filename);
+ const short_stackstring smode2(mode);
+ return std::fopen(name.get(), smode2.get());
+#endif
+ }
+ } // namespace detail
+
+#ifdef BOOST_WINDOWS
+ ///
+ /// \brief Same as freopen but file_name and mode are UTF-8 strings
+ ///
+ FILE* freopen(const char* file_name, const char* mode, FILE* stream)
+ {
+ const wstackstring wname(file_name);
+ const wshort_stackstring wmode(mode);
+ return _wfreopen(wname.get(), wmode.get(), stream);
+ }
+ ///
+ /// \brief Same as fopen but file_name and mode are UTF-8 strings
+ ///
+ FILE* fopen(const char* file_name, const char* mode)
+ {
+ const wstackstring wname(file_name);
+ const wshort_stackstring wmode(mode);
+ return _wfopen(wname.get(), wmode.get());
+ }
+ ///
+ /// \brief Same as rename but old_name and new_name are UTF-8 strings
+ ///
+ int rename(const char* old_name, const char* new_name)
+ {
+ const wstackstring wold(old_name), wnew(new_name);
+ return _wrename(wold.get(), wnew.get());
+ }
+ ///
+ /// \brief Same as rename but name is UTF-8 string
+ ///
+ int remove(const char* name)
+ {
+ const wstackstring wname(name);
+ return _wremove(wname.get());
+ }
+#endif
+} // namespace nowide
+} // namespace boost
diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp
new file mode 100644
index 0000000..8fbda07
--- /dev/null
+++ b/src/cstdlib.cpp
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
+//
+// 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
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__)
+// Need the _w* functions which are extensions on MinGW/Cygwin
+#undef __STRICT_ANSI__
+#endif
+
+#include
+
+#if !BOOST_WINDOWS
+namespace boost {
+namespace nowide {
+ int setenv(const char* key, const char* value, int overwrite)
+ {
+ return ::setenv(key, value, overwrite);
+ }
+
+ int unsetenv(const char* key)
+ {
+ return ::unsetenv(key);
+ }
+
+ int putenv(char* string)
+ {
+ return ::putenv(string);
+ }
+} // namespace nowide
+} // namespace boost
+#else
+#include
+#include
+#include
+
+namespace boost {
+namespace nowide {
+ char* getenv(const char* key)
+ {
+ static stackstring value;
+
+ const wshort_stackstring name(key);
+
+ static const size_t buf_size = 64;
+ wchar_t buf[buf_size];
+ std::vector tmp;
+ wchar_t* ptr = buf;
+ size_t n = GetEnvironmentVariableW(name.get(), 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.get(), &tmp[0], static_cast(tmp.size() - 1));
+ // The size may have changed
+ if(n >= tmp.size() - 1)
+ return 0;
+ ptr = &tmp[0];
+ }
+ value.convert(ptr);
+ return value.get();
+ }
+
+ int setenv(const char* key, const char* value, int overwrite)
+ {
+ const wshort_stackstring name(key);
+ if(!overwrite)
+ {
+ wchar_t unused[2];
+ if(GetEnvironmentVariableW(name.get(), unused, 2) != 0 || GetLastError() != 203) // ERROR_ENVVAR_NOT_FOUND
+ return 0;
+ }
+ const wstackstring wval(value);
+ if(SetEnvironmentVariableW(name.get(), wval.get()))
+ return 0;
+ return -1;
+ }
+
+ int unsetenv(const char* key)
+ {
+ const wshort_stackstring name(key);
+ if(SetEnvironmentVariableW(name.get(), 0))
+ return 0;
+ return -1;
+ }
+
+ int putenv(char* string)
+ {
+ const char* key = string;
+ const char* key_end = string;
+ while(*key_end != '=' && *key_end != '\0')
+ key_end++;
+ if(*key_end == '\0')
+ return -1;
+ const wshort_stackstring wkey(key, key_end);
+ const wstackstring wvalue(key_end + 1);
+
+ if(SetEnvironmentVariableW(wkey.get(), wvalue.get()))
+ return 0;
+ return -1;
+ }
+
+ int system(const char* cmd)
+ {
+ if(!cmd)
+ return _wsystem(0);
+ const wstackstring wcmd(cmd);
+ return _wsystem(wcmd.get());
+ }
+} // namespace nowide
+} // namespace boost
+#endif
diff --git a/standalone/config.hpp b/standalone/config.hpp
index ec438ae..43bdc6a 100644
--- a/standalone/config.hpp
+++ b/standalone/config.hpp
@@ -31,12 +31,12 @@
#endif
#if defined(NOWIDE_WINDOWS)
-#ifdef BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
-#undef BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
+#ifdef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+#undef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
#endif
-#define BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS 1
-#elif !defined(BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS)
-#define BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS 0
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 1
+#elif !defined(BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT)
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 0
#endif
#endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 9d5d4e1..3ec5973 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -27,7 +27,7 @@ boost_nowide_add_test(test_system_n SRC test_system.cpp DEFINITIONS BOOST_NOWIDE
if(WIN32)
boost_nowide_add_test(test_system_w SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=0)
else()
- boost_nowide_add_test(test_internal_fstream SRC test_fstream.cpp DEFINITIONS BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS=1)
+ boost_nowide_add_test(test_internal_fstream SRC test_fstream.cpp DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1)
endif()
if(NOT BOOST_NOWIDE_STANDALONE)
@@ -40,4 +40,4 @@ endif()
if(NOT BOOST_SUPERPROJECT_SOURCE_DIR)
find_package(Boost 1.56 REQUIRED COMPONENTS chrono)
endif()
-boost_nowide_add_test(benchmark_fstream COMPILE_ONLY DEFINITIONS BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS=1 LIBRARIES Boost::chrono)
+boost_nowide_add_test(benchmark_fstream COMPILE_ONLY DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 LIBRARIES Boost::chrono)
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index e14a636..4478814 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -10,6 +10,7 @@
import testing ;
project : requirements
+ /boost/nowide//boost_nowide
pedantic
on
gcc:-Wno-long-long
@@ -26,12 +27,11 @@ run test_env.cpp ;
run test_env.cpp : : : BOOST_NOWIDE_TEST_INCLUDE_WINDOWS=1 : test_env_win ;
run test_fs.cpp : : : /boost/filesystem//boost_filesystem/off : ;
run test_fstream.cpp ;
-run test_fstream.cpp : : : BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS=1 windows:no : test_internal_fstream;
-run test_iostream.cpp : : : /boost/nowide//boost_nowide static : test_iostream_static ;
-run test_iostream.cpp : : : /boost/nowide//boost_nowide shared : test_iostream_shared ;
+run test_fstream.cpp : : : BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 windows:no : test_internal_fstream ;
+run test_iostream.cpp ;
run test_stackstring.cpp ;
run test_stdio.cpp ;
run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=1 windows:shell32 : test_system_n ;
-run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 windows:shell32 no windows:yes: test_system_w ;
+run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 windows:shell32 no windows:yes : test_system_w ;
-compile benchmark_fstream.cpp : BOOST_NOWIDE_USE_WIN_FSTREAM=1 /boost/chrono//boost_chrono/;
+compile benchmark_fstream.cpp : BOOST_NOWIDE_USE_WIN_FSTREAM=1 /boost/chrono//boost_chrono/ ;
diff --git a/test/benchmark_fstream.cpp b/test/benchmark_fstream.cpp
index 56279c0..2f22a57 100644
--- a/test/benchmark_fstream.cpp
+++ b/test/benchmark_fstream.cpp
@@ -19,11 +19,17 @@
#include
#include
#include