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/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/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..9faca47 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
@@ -11,6 +11,7 @@
#include
#if BOOST_NOWIDE_USE_FSTREAM_REPLACEMENTS
+#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)
using std::basic_filebuf;
using std::filebuf;
#else // Windows
-
///
/// \brief This forward declaration defines the basic_filebuf type.
///
@@ -103,14 +98,7 @@ namespace nowide {
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/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/test/Jamfile.v2 b/test/Jamfile.v2
index 2597709..2fb6d99 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
diff --git a/test/test_stdio.cpp b/test/test_stdio.cpp
index 76dadca..5766458 100644
--- a/test/test_stdio.cpp
+++ b/test/test_stdio.cpp
@@ -8,26 +8,18 @@
//
#include
+
+#include
#include
#include
#include
#include "test.hpp"
-#ifdef _MSC_VER
-FILE* wfopen(const wchar_t* filename, const wchar_t* mode)
-{
- FILE* f;
- return (_wfopen_s(&f, filename, mode) == 0) ? f : NULL;
-}
-#else
-#define wfopen _wfopen
-#endif
-
bool file_exists(const std::string& filename)
{
#ifdef BOOST_WINDOWS
- FILE* f = wfopen(boost::nowide::widen(filename).c_str(), L"r");
+ FILE* f = boost::nowide::detail::wfopen(boost::nowide::widen(filename).c_str(), L"r");
#else
FILE* f = std::fopen(filename.c_str(), "r");
#endif
@@ -43,7 +35,7 @@ bool file_exists(const std::string& filename)
void create_test_file(const std::string& filename)
{
#ifdef BOOST_WINDOWS
- FILE* f = wfopen(boost::nowide::widen(filename).c_str(), L"w");
+ FILE* f = boost::nowide::detail::wfopen(boost::nowide::widen(filename).c_str(), L"w");
#else
FILE* f = std::fopen(filename.c_str(), "w");
#endif