228 lines
10 KiB
Plaintext
228 lines
10 KiB
Plaintext
$OpenBSD: patch-libs_filesystem_src_path_cpp,v 1.2 2013/03/26 20:19:04 brad Exp $
|
|
|
|
Fix "std::runtime_error: locale::facet::_S_create_c_locale name not valid"
|
|
error on OpenBSD when using non-C locales.
|
|
|
|
--- libs/filesystem/src/path.cpp.orig Mon Apr 16 09:36:28 2012
|
|
+++ libs/filesystem/src/path.cpp Tue Mar 26 15:47:25 2013
|
|
@@ -35,7 +35,8 @@
|
|
#ifdef BOOST_WINDOWS_API
|
|
# include "windows_file_codecvt.hpp"
|
|
# include <windows.h>
|
|
-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
|
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || \
|
|
+ defined(__OpenBSD__)
|
|
# include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
|
|
#endif
|
|
|
|
@@ -783,147 +784,104 @@ namespace filesystem
|
|
} // namespace filesystem
|
|
} // namespace boost
|
|
|
|
-//--------------------------------------------------------------------------------------//
|
|
-// //
|
|
-// detail helpers //
|
|
-// //
|
|
-//--------------------------------------------------------------------------------------//
|
|
-
|
|
namespace
|
|
{
|
|
|
|
//------------------------------------------------------------------------------------//
|
|
- // locale helpers //
|
|
+ // locale helpers //
|
|
//------------------------------------------------------------------------------------//
|
|
|
|
-#if defined(BOOST_WINDOWS_API) && defined(BOOST_FILESYSTEM_STATIC_LINK)
|
|
+ // Prior versions of these locale and codecvt implementations tried to take advantage
|
|
+ // of static initialization where possible, kept a local copy of the current codecvt
|
|
+ // facet (to avoid codecvt() having to call use_facet()), and was not multi-threading
|
|
+ // safe (again for efficiency).
|
|
+ //
|
|
+ // This was error prone, and required different implementation techniques depending
|
|
+ // on the compiler and also whether static or dynamic linking was used. Furthermore,
|
|
+ // users could not easily provide their multi-threading safe wrappers because the
|
|
+ // path interface requires the implementation itself to call codecvt() to obtain the
|
|
+ // default facet, and the initialization of the static within path_locale() could race.
|
|
+ //
|
|
+ // The code below is portable to all platforms, is much simpler, and hopefully will be
|
|
+ // much more robust. Timing tests (on Windows, using a Visual C++ release build)
|
|
+ // indicated the current code is roughly 9% slower than the previous code, and that
|
|
+ // seems a small price to pay for better code that is easier to use.
|
|
|
|
+ //boost::detail::lightweight_mutex locale_mutex;
|
|
+
|
|
inline std::locale default_locale()
|
|
{
|
|
+# if defined(BOOST_WINDOWS_API)
|
|
std::locale global_loc = std::locale();
|
|
- std::locale loc(global_loc, new windows_file_codecvt);
|
|
- return loc;
|
|
+ return std::locale(global_loc, new windows_file_codecvt);
|
|
+# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || \
|
|
+ defined(__OpenBSD__)
|
|
+ // "All BSD system functions expect their string parameters to be in UTF-8 encoding
|
|
+ // and nothing else." See
|
|
+ // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
|
|
+ //
|
|
+ // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
|
|
+ // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
|
|
+ // The right way to deal with it would be to always convert the filename to UTF-8
|
|
+ // before trying to open/create a file." See
|
|
+ // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
|
|
+ //
|
|
+ // "How a file name looks at the API level depends on the API. Current Carbon APIs
|
|
+ // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
|
|
+ // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
|
|
+ // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
|
|
+ // cases." See
|
|
+ // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
|
|
+ //
|
|
+ // Many thanks to Peter Dimov for digging out the above references!
|
|
+
|
|
+ std::locale global_loc = std::locale();
|
|
+ return std::locale(global_loc, new boost::filesystem::detail::utf8_codecvt_facet);
|
|
+# else // Other POSIX
|
|
+ // ISO C calls std::locale("") "the locale-specific native environment", and this
|
|
+ // locale is the default for many POSIX-based operating systems such as Linux.
|
|
+ return std::locale("");
|
|
+# endif
|
|
}
|
|
|
|
inline std::locale& path_locale()
|
|
+ // std::locale("") construction, needed on non-Apple POSIX systems, can throw
|
|
+ // (if environmental variables LC_MESSAGES or LANG are wrong, for example), so
|
|
+ // path_locale() provides lazy initialization via a local static to ensure that any
|
|
+ // exceptions occur after main() starts and so can be caught. Furthermore,
|
|
+ // path_locale() is only called if path::codecvt() or path::imbue() are themselves
|
|
+ // actually called, ensuring that an exception will only be thrown if std::locale("")
|
|
+ // is really needed.
|
|
{
|
|
static std::locale loc(default_locale());
|
|
return loc;
|
|
}
|
|
-
|
|
- inline const path::codecvt_type*& codecvt_facet_ptr()
|
|
- {
|
|
- static const std::codecvt<wchar_t, char, std::mbstate_t>*
|
|
- facet(
|
|
- &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
|
|
- (path_locale()));
|
|
- return facet;
|
|
- }
|
|
-
|
|
-#elif defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_STATIC_LINK)
|
|
-
|
|
- std::locale path_locale(std::locale(), new windows_file_codecvt);
|
|
-
|
|
- const std::codecvt<wchar_t, char, std::mbstate_t>*
|
|
- codecvt_facet_ptr(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
|
|
- (path_locale));
|
|
-
|
|
-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
|
-
|
|
- // "All BSD system functions expect their string parameters to be in UTF-8 encoding
|
|
- // and nothing else." See
|
|
- // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html
|
|
- //
|
|
- // "The kernel will reject any filename that is not a valid UTF-8 string, and it will
|
|
- // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS.
|
|
- // The right way to deal with it would be to always convert the filename to UTF-8
|
|
- // before trying to open/create a file." See
|
|
- // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html
|
|
- //
|
|
- // "How a file name looks at the API level depends on the API. Current Carbon APIs
|
|
- // handle file names as an array of UTF-16 characters; POSIX ones handle them as an
|
|
- // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk
|
|
- // depends on the disk format; HFS+ uses UTF-16, but that's not important in most
|
|
- // cases." See
|
|
- // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html
|
|
- //
|
|
- // Many thanks to Peter Dimov for digging out the above references!
|
|
-
|
|
- std::locale path_locale(std::locale(),
|
|
- new boost::filesystem::detail::utf8_codecvt_facet);
|
|
-
|
|
- const std::codecvt<wchar_t, char, std::mbstate_t>*
|
|
- codecvt_facet_ptr(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
|
|
- (path_locale));
|
|
-
|
|
-#else // Other POSIX
|
|
-
|
|
- // ISO C calls std::locale("") "the locale-specific native environment", and this
|
|
- // locale is the default for many POSIX-based operating systems such as Linux.
|
|
-
|
|
- // std::locale("") construction can throw (if environmental variables LC_MESSAGES or
|
|
- // or LANG are wrong, for example), so lazy initialization is used to ensure
|
|
- // that exceptions occur after main() starts and so can be caught.
|
|
-
|
|
- std::locale path_locale; // initialized by path::codecvt() below
|
|
- const std::codecvt<wchar_t, char, std::mbstate_t>* codecvt_facet_ptr; // ditto
|
|
-
|
|
-# endif
|
|
-
|
|
} // unnamed namespace
|
|
|
|
//--------------------------------------------------------------------------------------//
|
|
-// path::imbue implementation //
|
|
+// path::codecvt() and path::imbue() implementation //
|
|
//--------------------------------------------------------------------------------------//
|
|
|
|
namespace boost
|
|
{
|
|
namespace filesystem
|
|
{
|
|
+ // See comments above
|
|
|
|
-#if defined(BOOST_WINDOWS_API) && defined(BOOST_FILESYSTEM_STATIC_LINK)
|
|
-
|
|
const path::codecvt_type& path::codecvt()
|
|
{
|
|
- BOOST_ASSERT_MSG(codecvt_facet_ptr(), "codecvt_facet_ptr() facet hasn't been properly initialized");
|
|
- return *codecvt_facet_ptr();
|
|
+ BOOST_ASSERT_MSG(&path_locale(), "boost::filesystem::path locale initialization error");
|
|
+// boost::detail::lightweight_mutex::scoped_lock lock(locale_mutex);
|
|
+ return std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale());
|
|
}
|
|
|
|
- std::locale path::imbue(const std::locale & loc)
|
|
+ std::locale path::imbue(const std::locale& loc)
|
|
{
|
|
+// boost::detail::lightweight_mutex::scoped_lock lock(locale_mutex);
|
|
std::locale temp(path_locale());
|
|
path_locale() = loc;
|
|
- codecvt_facet_ptr() =
|
|
- &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale());
|
|
return temp;
|
|
}
|
|
-
|
|
-#else
|
|
-
|
|
- const path::codecvt_type& path::codecvt()
|
|
- {
|
|
-# if defined(BOOST_POSIX_API) && \
|
|
- !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
|
|
- // A local static initialized by calling path::imbue ensures that std::locale(""),
|
|
- // which may throw, is called only if path_locale and condecvt_facet will actually
|
|
- // be used. Thus misconfigured environmental variables will only cause an
|
|
- // exception if a valid std::locale("") is actually needed.
|
|
- static std::locale posix_lazy_initialization(path::imbue(std::locale("")));
|
|
-# endif
|
|
- return *codecvt_facet_ptr;
|
|
- }
|
|
-
|
|
- std::locale path::imbue(const std::locale& loc)
|
|
- {
|
|
- std::locale temp(path_locale);
|
|
- path_locale = loc;
|
|
- codecvt_facet_ptr =
|
|
- &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(path_locale);
|
|
- return temp;
|
|
- }
|
|
-
|
|
-
|
|
-#endif
|
|
|
|
} // namespace filesystem
|
|
} // namespace boost
|