openbsd-ports/devel/boost/patches/patch-libs_filesystem_src_path_cpp
2013-03-26 20:19:04 +00:00

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