Initial pass at adding support for char16_t and char32_t. Unstable work-in-progress.

This commit is contained in:
Beman
2015-05-25 10:59:28 -04:00
parent 13b1a4c311
commit 2af6caf4e9
7 changed files with 192 additions and 2 deletions

View File

@@ -38,12 +38,22 @@
#include <boost/system/api_config.hpp> // for BOOST_POSIX_API or BOOST_WINDOWS_API
#include <boost/detail/workaround.hpp>
// BOOST_FILESYSTEM_DEPRECATED needed for source compiles -----------------------------//
// BOOST_FILESYSTEM_DEPRECATED needed for source compiles
# ifdef BOOST_FILESYSTEM_SOURCE
# define BOOST_FILESYSTEM_DEPRECATED
# endif
// Support for C++11 char16_t and char32_t paths requires both character type (or
// equivalent typedef) support and header <codecvt> support.
# if BOOST_FILESYSTEM_VERSION > 3 \
&& !defined(BOOST_NO_CXX11_HDR_CODECVT) \
&& ((!defined(BOOST_NO_CXX11_CHAR16_T) && (!defined(BOOST_NO_CXX11_CHAR32_T)) \
|| (defined(_MSC_VER) && _MSC_VER >= 1600)))
# define BOOST_FILESYSTEM_CHAR16_CHAR32
#endif
// throw an exception ----------------------------------------------------------------//
//
// Exceptions were originally thrown via boost::throw_exception().

View File

@@ -75,6 +75,7 @@ namespace boost
<< BOOST_FILESYSTEM_SHOW_MACRO(BOOST_FILESYSTEM_NO_DEPRECATED) << '\n'
<< BOOST_FILESYSTEM_SHOW_MACRO(BOOST_FILESYSTEM_DECL) << '\n'
<< BOOST_FILESYSTEM_SHOW_MACRO(BOOST_SYMBOL_VISIBLE) << '\n'
<< BOOST_FILESYSTEM_SHOW_MACRO(BOOST_FILESYSTEM_CHAR16_CHAR32) << '\n'
<< BOOST_FILESYSTEM_SHOW_MACRO(BOOST_FILESYSTEM_OPERATIONS_TEST_TEMP) << '\n'
;
return os;

View File

@@ -124,6 +124,40 @@ namespace boost { namespace BOOST_FILESYSTEM_NAMESPACE {
convert(from, 0, to, cvt);
}
# ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
BOOST_FILESYSTEM_DECL
void convert(const char32_t* from,
const char32_t* from_end, // 0 for null terminated MBCS
std::wstring & to,
const codecvt_type&);
//BOOST_FILESYSTEM_DECL
// void convert(const char32_t* from,
// const char32_t* from_end, // 0 for null terminated MBCS
// std::string & to,
// const codecvt_type& cvt);
//inline
// void convert(const char32_t* from,
// std::wstring & to,
// const codecvt_type& cvt)
//{
// BOOST_ASSERT(from);
// convert(from, 0, to, cvt);
//}
//inline
// void convert(const wchar_t* from,
// std::string & to,
// const codecvt_type& cvt)
//{
// BOOST_ASSERT(from);
// convert(from, 0, to, cvt);
//}
# endif
// value types same -----------------------------------------------------------------//
// char

View File

@@ -25,6 +25,10 @@
#include <cstring> // for strlen
#include <cwchar> // for wcslen
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
# include <codecvt>
#endif
namespace pt = boost::filesystem::path_traits;
namespace fs = boost::filesystem;
namespace bs = boost::system;
@@ -93,6 +97,46 @@ namespace {
target.append(to, to_next);
}
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
//--------------------------------------------------------------------------------------//
// convert_aux const char32_t* to wstring //
//--------------------------------------------------------------------------------------//
static void convert_aux(
const char32_t* from,
const char32_t* from_end,
wchar_t* to, wchar_t* to_end,
std::wstring& target)
{
//std::cout << std::hex
// << " from=" << std::size_t(from)
// << " from_end=" << std::size_t(from_end)
// << " to=" << std::size_t(to)
// << " to_end=" << std::size_t(to_end)
// << std::endl;
typedef std::codecvt_utf16<char32_t> codecvt_type;
static codecvt_type cvt;
std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports
const char32_t* from_next;
wchar_t* to_next;
std::codecvt_base::result res;
if ((res = cvt.in(state, from, from_end, from_next,
to, to_end, to_next)) != std::codecvt_base::ok)
{
//std::cout << " result is " << static_cast<int>(res) << std::endl;
BOOST_FILESYSTEM_THROW(bs::system_error(res, fs::codecvt_error_category(),
"boost::filesystem::path codecvt to wstring"));
}
target.append(to, to_next);
}
#endif
//--------------------------------------------------------------------------------------//
// convert_aux const wchar_t* to string //
//--------------------------------------------------------------------------------------//
@@ -207,4 +251,47 @@ namespace boost { namespace BOOST_FILESYSTEM_NAMESPACE { namespace path_traits {
convert_aux(from, from_end, buf, buf+default_codecvt_buf_size, to, cvt);
}
}
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
# ifdef BOOST_WINDOWS_API
//--------------------------------------------------------------------------------------//
// convert const char32_t* to wstring //
//--------------------------------------------------------------------------------------//
BOOST_FILESYSTEM_DECL
void convert(const char32_t* from,
const char32_t* from_end, // 0 for null terminated MBCS
std::wstring& to,
const codecvt_type&)
{
BOOST_ASSERT(from);
if (!from_end) // null terminated
{
for (from_end = from; *from_end; ++from_end); // find end
}
if (from == from_end)
return;
std::size_t buf_size = (from_end - from) * 2*4; // perhaps too large, but that's OK
// dynamically allocate a buffer only if source is unusually large
if (buf_size > default_codecvt_buf_size)
{
boost::scoped_array< wchar_t > buf(new wchar_t[buf_size]);
convert_aux(from, from_end, buf.get(), buf.get()+buf_size, to);
}
else
{
wchar_t buf[default_codecvt_buf_size];
convert_aux(from, from_end, buf, buf+default_codecvt_buf_size, to);
}
}
# endif
#endif
}}} // namespace boost::filesystem::path_traits

View File

@@ -22,14 +22,39 @@
#include <boost/detail/lightweight_test.hpp>
#include <boost/detail/lightweight_main.hpp>
#include <boost/utility/string_ref.hpp>
using std::cout;
using std::endl;
namespace fs = boost::filesystem;
using boost::basic_string_ref;
using boost::string_ref;
using boost::wstring_ref;
void f1(const string_ref&)
{
cout << "narrow" << endl;
}
void f1(const wstring_ref&)
{
cout << "wide" << endl;
}
template <class T>
void foo(const T& from)
{
f1(basic_string_ref<typename T::value_type>(from));
}
//------------------------------------ cpp_main --------------------------------------//
int cpp_main(int argc, char* argv[])
{
foo(std::string("string"));
//foo<char>(std::string("string"));
//foo<char, std::char_traits<char>>("string");
cout << "Hello, filesystem world" << endl;
cout << fs::config() << endl;

View File

@@ -65,12 +65,12 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\include\boost\filesystem\config.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\config_info.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\convenience.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\detail\is_iterator.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\detail\source_value_type.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\detail\utf8_codecvt_facet.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\detail\version.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\detail\version_imp.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\exception.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\fstream.hpp" />
<ClInclude Include="..\..\..\include\boost\filesystem\operations.hpp" />

View File

@@ -63,6 +63,12 @@ using std::endl;
using std::string;
using std::wstring;
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
using std::u16string;
using std::u32string;
#endif
#define CHECK(x) check(x, __FILE__, __LINE__)
#define PATH_IS(a, b) check_path(a, b, __FILE__, __LINE__)
#define NATIVE_IS(p, s, ws) check_native(p, s, ws, __FILE__, __LINE__)
@@ -160,6 +166,14 @@ namespace
boost::container::vector<wchar_t> wbv; // see main() for initialization to w, f, u, z
#endif
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
const char16_t u16a[] = {'u', '1', '6', 's', 't', 'r', 'i', 'n', 'g', '\0'};
const char32_t u32a[] = {'u', '3', '2', 's', 't', 'r', 'i', 'n', 'g', '\0'};
u16string u16s(u16a);
u32string u32s(u32a);
#endif
class Base {};
class Derived : public Base {};
void fun(const boost::shared_ptr< Base >&) {}
@@ -301,6 +315,25 @@ namespace
BOOST_TEST_EQ(x19.native().size(), 7U);
#endif
#ifdef BOOST_FILESYSTEM_CHAR16_CHAR32
{
path x1(u32a);
PATH_IS(x1, L"u32string");
BOOST_TEST_EQ(x1.native().size(), 9U);
path x2(u32s);
PATH_IS(x2, L"u32string");
BOOST_TEST_EQ(x2.native().size(), 9U);
path x3(&u32a[0], &u32a[8]);
PATH_IS(x3, L"u32string");
BOOST_TEST_EQ(x3.native().size(), 9U);
}
#endif
// easy-to-make coding errors
// path e1(x0, path::codecvt()); // fails to compile, and that is OK