From 6230db51b1b6cc71e66e37df79b4603e556e73b5 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Wed, 18 Dec 2013 16:54:36 +0000 Subject: [PATCH] Fix for std::locale's which produce collate keys with embedded null's, see https://svn.boost.org/trac/boost/ticket/9451 --- include/boost/regex/v4/cpp_regex_traits.hpp | 29 ++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/include/boost/regex/v4/cpp_regex_traits.hpp b/include/boost/regex/v4/cpp_regex_traits.hpp index 53f56da8..b81d8c84 100644 --- a/include/boost/regex/v4/cpp_regex_traits.hpp +++ b/include/boost/regex/v4/cpp_regex_traits.hpp @@ -21,6 +21,7 @@ #include #include +#include #ifndef BOOST_NO_STD_LOCALE @@ -582,7 +583,7 @@ typename cpp_regex_traits_implementation::string_type // however at least one std lib will always throw // std::bad_alloc for certain arguments... // - string_type result; + string_type result, result2; #ifndef BOOST_NO_EXCEPTIONS try{ #endif @@ -601,14 +602,36 @@ typename cpp_regex_traits_implementation::string_type while(result.size() && (charT(0) == *result.rbegin())) result.erase(result.size() - 1); #endif - BOOST_ASSERT(std::find(result.begin(), result.end(), charT(0)) == result.end()); + // + // We may have NULL's used as separators between sections of the collate string, + // an example would be Boost.Locale. We have no way to detect this case via + // #defines since this can be used with any compiler/platform combination. + // Unfortunately our state machine (which was devised when all implementations + // used underlying C language API's) can't cope with that case. One workaround + // is to replace each character with 2, fortunately this code isn't used that + // much as this is now slower than before :-( + // + typedef typename make_unsigned::type uchar_type; + result2.reserve(result.size() * 2 + 2); + for(unsigned i = 0; i < result.size(); ++i) + { + if(static_cast(result[i]) == (std::numeric_limits::max)()) + { + result2.append(1, charT((std::numeric_limits::max)())).append(1, charT('b')); + } + else + { + result2.append(1, static_cast(1 + static_cast(result[i]))).append(1, charT('b') - 1); + } + } + BOOST_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end()); #ifndef BOOST_NO_EXCEPTIONS } catch(...) { } #endif - return result; + return result2; }