This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFC 2/2] libstdc++: Add codecvt<char32_t, char, mbstate_t>.
- From: Rüdiger Sonderfeld <ruediger at c-plusplus dot de>
- To: libstdc++ at gcc dot gnu dot org
- Date: Fri, 25 Apr 2014 23:45:26 +0200
- Subject: [RFC 2/2] libstdc++: Add codecvt<char32_t, char, mbstate_t>.
- Authentication-results: sourceware.org; auth=none
- References: <cover dot 1398460425 dot git dot ruediger at c-plusplus dot de>
UTF-32/UTF-8 codec converter (codecvt) specialization.
C++11: [locale.codecvt]
* libstdc++-v3/config/abi/pre/gnu.ver: Add vtable/typeinfo for
__codecvt_abstract_base<char32_t, char, mbstate_t>.
* libstdc++-v3/include/bits/codecvt.h (codecvt<char32_t, char,
mbstate_t>): New specialization.
* libstdc++-v3/src/c++11/codecvt.cc (codecvt<char32_t, char,
mbstate_t>): Same.
(utf32_to_utf8, utf8_to_utf32, utf8_to_utf32_length): New local
functions.
(use_facet<codecvt<char32_t, char, mbstate_t> >)
(has_facet<codecvt<char32_t, char, mbstate_t> >): New specialization.
* libstdc++-v3/include/bits/locale_facets.h (_GLIBCXX_NUM_FACETS):
Updated for char32_t facets
* libstdc++-v3/src/c++11/Makefile.am: Add locale_init.cc,
localename.cc, and c32locale-inst.cc.
* libstdc++-v3/src/c++11/Makefile.in: Updated.
* libstdc++-v3/src/c++11/c32locale-inst.cc: New file.
* libstdc++-v3/src/c++11/locale_init.cc: Moved file and added
codecvt<char32_t, char, mbstate_t> facet.
* libstdc++-v3/src/c++11/localename.cc: Moved file and added
codecvt<char32_t, char, mbstate_t> facet.
* libstdc++-v3/src/c++98/Makefile.am: Removed localename.cc and
locale_init.cc.
* libstdc++-v3/src/c++98/Makefile.in: Updated.
* libstdc++-v3/testsuite/22_locale/codecvt/char32_t/1.cc: New test.
---
libstdc++-v3/config/abi/pre/gnu.ver | 5 +
libstdc++-v3/include/bits/codecvt.h | 76 ++++
libstdc++-v3/include/bits/locale_facets.h | 6 +-
libstdc++-v3/src/c++11/Makefile.am | 5 +-
libstdc++-v3/src/c++11/Makefile.in | 14 +-
libstdc++-v3/src/c++11/c32locale-inst.cc | 57 +++
libstdc++-v3/src/c++11/codecvt.cc | 259 +++++++++++
libstdc++-v3/src/c++11/locale_init.cc | 487 +++++++++++++++++++++
libstdc++-v3/src/c++11/localename.cc | 357 +++++++++++++++
libstdc++-v3/src/c++98/Makefile.am | 2 -
libstdc++-v3/src/c++98/Makefile.in | 9 +-
libstdc++-v3/src/c++98/locale_init.cc | 472 --------------------
libstdc++-v3/src/c++98/localename.cc | 352 ---------------
.../testsuite/22_locale/codecvt/char32_t/1.cc | 101 +++++
14 files changed, 1362 insertions(+), 840 deletions(-)
create mode 100644 libstdc++-v3/src/c++11/c32locale-inst.cc
create mode 100644 libstdc++-v3/src/c++11/locale_init.cc
create mode 100644 libstdc++-v3/src/c++11/localename.cc
delete mode 100644 libstdc++-v3/src/c++98/locale_init.cc
delete mode 100644 libstdc++-v3/src/c++98/localename.cc
create mode 100644 libstdc++-v3/testsuite/22_locale/codecvt/char32_t/1.cc
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index f0ce4f0..e1e75e0 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1365,6 +1365,11 @@ GLIBCXX_3.4.20 {
# std::regex_error::regex_error(std::regex_constants::error_type)
_ZNSt11regex_errorC[01]ENSt15regex_constants10error_typeE;
+ # typeinfo, vtable for __codecvt_abstract_base<char32_t, char, mbstate_t>
+ _ZTVSt23__codecvt_abstract_baseIDic11__mbstate_tE;
+ _ZTISt23__codecvt_abstract_baseIDic11__mbstate_tE;
+ _ZTSSt23__codecvt_abstract_baseIDic11__mbstate_tE;
+
} GLIBCXX_3.4.19;
# Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h
index 18038e1..80ef606 100644
--- a/libstdc++-v3/include/bits/codecvt.h
+++ b/libstdc++-v3/include/bits/codecvt.h
@@ -453,6 +453,71 @@ namespace std _GLIBCXX_VISIBILITY(default)
};
#endif //_GLIBCXX_USE_WCHAR_T
+#if __cplusplus >= 201103L && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+ /**
+ * @brief class codecvt<char32_t, char, mbstate_t> specialization.
+ *
+ * Converts between UTF-32 and UTF-8.
+ */
+ template<>
+ class codecvt<char32_t, char, mbstate_t>
+ : public __codecvt_abstract_base<char32_t, char, mbstate_t>
+ {
+ public:
+ // Types:
+ typedef char32_t intern_type;
+ typedef char extern_type;
+ typedef mbstate_t state_type;
+
+ protected:
+ __c_locale _M_c_locale_codecvt;
+
+ public:
+ static locale::id id;
+
+ explicit
+ codecvt(size_t __refs = 0);
+
+ explicit
+ codecvt(__c_locale __cloc, size_t __refs = 0);
+
+ protected:
+ virtual
+ ~codecvt();
+
+ virtual result
+ do_out(state_type& __state, const intern_type* __from,
+ const intern_type* __from_end, const intern_type*& __from_next,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_unshift(state_type& __state,
+ extern_type* __to, extern_type* __to_end,
+ extern_type*& __to_next) const;
+
+ virtual result
+ do_in(state_type& __state,
+ const extern_type* __from, const extern_type* __from_end,
+ const extern_type*& __from_next,
+ intern_type* __to, intern_type* __to_end,
+ intern_type*& __to_next) const;
+
+ virtual
+ int do_encoding() const _GLIBCXX_NOEXCEPT;
+
+ virtual
+ bool do_always_noconv() const _GLIBCXX_NOEXCEPT;
+
+ virtual
+ int do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const;
+
+ virtual int
+ do_max_length() const _GLIBCXX_NOEXCEPT;
+ };
+#endif // __cplusplus >= 201103L && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+
/// class codecvt_byname [22.2.1.6].
template<typename _InternT, typename _ExternT, typename _StateT>
class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT>
@@ -499,8 +564,19 @@ namespace std _GLIBCXX_VISIBILITY(default)
bool
has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
#endif
+
+#if __cplusplus >= 201103L && defined(_GLIBCXX_USE_C99_STDINT_TR1)
+ extern template
+ const codecvt<char32_t, char, mbstate_t>&
+ use_facet<codecvt<char32_t, char, mbstate_t> >(const locale&);
+
+ extern template
+ bool
+ has_facet<codecvt<char32_t, char, mbstate_t> >(const locale&);
#endif
+#endif // _GLIBCXX_EXTERN_TEMPLATE
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 453bbed..17eef49 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -51,8 +51,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- // NB: Don't instantiate required wchar_t facets if no wchar_t support.
-#ifdef _GLIBCXX_USE_WCHAR_T
+ // NB: Don't instantiate required wchar_t/char*_t facets if no wchar_t/char*_t support.
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+# define _GLIBCXX_NUM_FACETS 42 // TODO
+#elif defined(_GLIBCXX_USE_WCHAR_T)
# define _GLIBCXX_NUM_FACETS 28
#else
# define _GLIBCXX_NUM_FACETS 14
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am
index 921a3a7..c555c9e 100644
--- a/libstdc++-v3/src/c++11/Makefile.am
+++ b/libstdc++-v3/src/c++11/Makefile.am
@@ -38,6 +38,8 @@ sources = \
hash_c++0x.cc \
hashtable_c++0x.cc \
limits.cc \
+ locale_init.cc \
+ localename.cc \
mutex.cc \
placeholders.cc \
random.cc \
@@ -52,7 +54,8 @@ if ENABLE_EXTERN_TEMPLATE
inst_sources = \
fstream-inst.cc \
string-inst.cc \
- wstring-inst.cc
+ wstring-inst.cc \
+ c32locale-inst.cc
else
# XTEMPLATE_FLAGS =
inst_sources =
diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in
index d5143c4..f3839c5 100644
--- a/libstdc++-v3/src/c++11/Makefile.in
+++ b/libstdc++-v3/src/c++11/Makefile.in
@@ -69,11 +69,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
libc__11convenience_la_LIBADD =
am__objects_1 = chrono.lo condition_variable.lo codecvt.lo debug.lo \
functexcept.lo functional.lo future.lo hash_c++0x.lo \
- hashtable_c++0x.lo limits.lo mutex.lo placeholders.lo \
- random.lo regex.lo shared_ptr.lo snprintf_lite.lo \
- system_error.lo thread.lo
+ hashtable_c++0x.lo limits.lo locale_init.lo localename.lo \
+ mutex.lo placeholders.lo random.lo regex.lo shared_ptr.lo \
+ snprintf_lite.lo system_error.lo thread.lo
@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = fstream-inst.lo \
-@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo wstring-inst.lo
+@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo wstring-inst.lo \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ c32locale-inst.lo
am_libc__11convenience_la_OBJECTS = $(am__objects_1) $(am__objects_2)
libc__11convenience_la_OBJECTS = $(am_libc__11convenience_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@@ -321,6 +322,8 @@ sources = \
hash_c++0x.cc \
hashtable_c++0x.cc \
limits.cc \
+ locale_init.cc \
+ localename.cc \
mutex.cc \
placeholders.cc \
random.cc \
@@ -337,7 +340,8 @@ sources = \
@ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \
@ENABLE_EXTERN_TEMPLATE_TRUE@ fstream-inst.cc \
@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.cc \
-@ENABLE_EXTERN_TEMPLATE_TRUE@ wstring-inst.cc
+@ENABLE_EXTERN_TEMPLATE_TRUE@ wstring-inst.cc \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ c32locale-inst.cc
libc__11convenience_la_SOURCES = $(sources) $(inst_sources)
diff --git a/libstdc++-v3/src/c++11/c32locale-inst.cc b/libstdc++-v3/src/c++11/c32locale-inst.cc
new file mode 100644
index 0000000..442f862
--- /dev/null
+++ b/libstdc++-v3/src/c++11/c32locale-inst.cc
@@ -0,0 +1,57 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+#include <locale>
+#include <bits/c++config.h>
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+
+#define C char32_t
+
+//#include "../c++98/locale-inst.cc"
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // codecvt
+ inline template class __codecvt_abstract_base<C, char, mbstate_t>;
+ template class codecvt_byname<C, char, mbstate_t>;
+
+ template
+ const codecvt<C, char, mbstate_t>&
+ use_facet<codecvt<C, char, mbstate_t> >(const locale&);
+
+ template
+ bool
+ has_facet<codecvt<C, char, mbstate_t> >(const locale&);
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
diff --git a/libstdc++-v3/src/c++11/codecvt.cc b/libstdc++-v3/src/c++11/codecvt.cc
index 7c94c38..1f3a718 100644
--- a/libstdc++-v3/src/c++11/codecvt.cc
+++ b/libstdc++-v3/src/c++11/codecvt.cc
@@ -35,6 +35,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
locale::id codecvt<wchar_t, char, mbstate_t>::id;
#endif
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ locale::id codecvt<char32_t, char, mbstate_t>::id;
+#endif
+
codecvt<char, char, mbstate_t>::
codecvt(size_t __refs)
: __codecvt_abstract_base<char, char, mbstate_t>(__refs),
@@ -147,5 +151,260 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ return false; }
#endif // _GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+
+ // UTF-8 implementation.
+ namespace
+ {
+ codecvt_base::result
+ utf32_to_utf8(const char32_t* from, const char32_t* from_end,
+ const char32_t*& from_next,
+ char* to, char* to_end, char*& to_next,
+ unsigned long maxcode = 0x10FFFF)
+ {
+ for (from_next = from, to_next = to;
+ from_next != from_end and to_next != to_end;
+ ++from_next)
+ {
+ if (*from_next > maxcode)
+ return codecvt_base::error;
+ else if (*from_next <= 0x7F)
+ *to_next++ = uint8_t(*from_next);
+ else if (0x80 <= *from_next and *from_next <= 0x7FF)
+ {
+ if (to_end - to_next < 2)
+ return codecvt_base::partial;
+ // 00000yyy yyxxxxxx
+ *to_next++ = (*from_next >> 6) | 0xC0; // 110yyyyy
+ *to_next++ = (*from_next & 0x3F) | 0x80; // 10xxxxxx
+ }
+ else if ( (0x800 <= *from_next and *from_next < 0xD800) or
+ (0xDFFF < *from_next and *from_next <= 0xFFFF))
+ // exclude surrogate pairs (0xD800 to 0xDFFF)
+ {
+ if (to_end - to_next < 3)
+ return codecvt_base::partial;
+ // zzzzyyyy yyxxxxxx
+ *to_next++ = (*from_next >> 12) | 0xE0; // 1110zzzz
+ *to_next++ = ((*from_next >> 6) & 0x3F) | 0x80; // 10yyyyyy
+ *to_next++ = (*from_next & 0x3F) | 0x80; // 10xxxxxx
+ }
+ else if (0x10000 <= *from_next and *from_next <= 0x10FFFF)
+ {
+ if (to_end - to_next < 4)
+ return codecvt_base::partial;
+ // 000uuuzzzzzzyyyy yyxxxxxx
+ *to_next++ = (*from_next >> 18) | 0xF0; // 11110uuu
+ *to_next++ = ((*from_next >> 12) & 0x3F) | 0x80; // 10zzzzzz
+ *to_next++ = ((*from_next >> 6) & 0x3F) | 0x80; // 10yyyyyy
+ *to_next++ = (*from_next & 0x3F) | 0x80; // 10xxxxxx
+ }
+ else
+ return codecvt_base::error;
+ }
+ if (to_next == to_end && from != from_end)
+ return codecvt_base::partial;
+ else
+ return codecvt_base::ok;
+ }
+
+ codecvt_base::result
+ utf8_to_utf32(const char* from, const char* from_end,
+ const char*& from_next,
+ char32_t* to, char32_t* to_end, char32_t*& to_next,
+ unsigned long maxcode = 0x10FFFF)
+ {
+ // TODO reset from_next on error?
+ for(from_next = from, to_next = to; to_next != to_end; ++from_next)
+ {
+ const size_t len = from_end - from_next;
+ if (len >= 4 and (*from_next & 0xF0) == 0xF0)
+ {
+ const uint32_t first = *from_next++ & 0x07;
+
+ if ((*from_next & 0x80) != 0x80)
+ return codecvt_base::error;
+ const uint32_t second = *from_next++ & 0x3F;
+
+ if ((*from_next & 0x80 ) != 0x80)
+ return codecvt_base::error;
+ const uint32_t third = *from_next++ & 0x3F;
+
+ if ((*from_next & 0x80) != 0x80)
+ return codecvt_base::error;
+
+ *to_next = ((first << 18) | (second << 12) | (third << 6)
+ | (*from_next & 0x3F));
+ if (*to_next > maxcode)
+ return codecvt_base::error;
+ ++to_next;
+ }
+ else if (len >= 3 and (*from_next & 0xE0) == 0xE0)
+ {
+ const uint32_t first = *from_next++ & 0x0F;
+
+ if ((*from_next & 0x80) != 0x80)
+ return codecvt_base::error;
+ const uint32_t second = *from_next++ & 0x3F;
+
+ if ((*from_next & 0x80) != 0x80)
+ return codecvt_base::error;
+
+ *to_next = (first << 12) | (second << 6) | (*from_next & 0x3F);
+ if (*to_next > maxcode)
+ return codecvt_base::error;
+ ++to_next;
+ }
+ else if (len >= 2 and (*from_next & 0xC0) == 0xC0)
+ {
+ const uint32_t first = *from_next++ & 0x1F;
+
+ if ((*from_next & 0x80) != 0x80)
+ return codecvt_base::error;
+
+ *to_next = (first << 6) | (*from_next & 0x3F);
+ if (*to_next > maxcode)
+ return codecvt_base::error;
+ ++to_next;
+ }
+ else if (len >= 1 and (*from_next & 0x7F) == *from_next)
+ {
+ *to_next = uint8_t(*from_next);
+ if (*to_next > maxcode)
+ return codecvt_base::error;
+ ++to_next;
+ }
+ else if (len == 0)
+ break;
+ else
+ return codecvt_base::partial;
+ }
+ if (to_next == to_end && from != from_end)
+ return codecvt_base::partial;
+ else
+ return codecvt_base::ok;
+ }
+
+ int
+ utf8_to_utf32_length(const char* from, const char* from_end,
+ size_t max,
+ unsigned long maxcode = 0x10FFFF)
+ {
+ const char* from_next = from;
+ for(size_t count = 0; count < max; ++count, ++from_next)
+ {
+ const size_t len = from_end - from_next;
+ if (len >= 4 and (*from_next & 0xF0) == 0xF0)
+ {
+ const uint32_t first = *from_next++ & 0x07;
+ if ((*from_next & 0x80) != 0x80)
+ return (from_next - from) - 1;
+ const uint32_t second = *from_next++ & 0x3F;
+ if ((*from_next & 0x80 ) != 0x80)
+ return (from_next - from) - 2;
+ const uint32_t third = *from_next++ & 0x3F;
+ if ((*from_next & 0x80) != 0x80)
+ return (from_next - from) - 3;
+ const char32_t cp = (first << 18) | (second << 12) | (third << 6)
+ | (*from_next & 0x3F);
+ if (cp > maxcode)
+ return (from_next - from) - 3;
+ }
+ else if (len >= 3 and (*from_next & 0xE0) == 0xE0)
+ {
+ const uint32_t first = *from_next++ & 0x0F;
+ if ((*from_next & 0x80) != 0x80)
+ return (from_next - from) - 1;
+ const uint32_t second = *from_next++ & 0x3F;
+ if ((*from_next & 0x80 ) != 0x80)
+ return (from_next - from) - 2;
+ const char32_t cp = (first << 12) | (second << 6)
+ | (*from_next & 0x3F);
+ if (cp > maxcode)
+ return (from_next - from) - 2;
+ }
+ else if (len >= 2 and (*from_next & 0xC0) == 0xC0)
+ {
+ const uint32_t first = *from_next++ & 0x1F;
+ if ((*from_next & 0x80) != 0x80)
+ return (from_next - from) - 1;
+ const char32_t cp = (first << 6) | (*from_next & 0x3F);
+ if (cp > maxcode)
+ return (from_next - from) - 1;
+ }
+ else if (len >= 1 and (*from_next & 0x7F) == *from_next)
+ {
+ if (uint8_t(*from_next) > maxcode)
+ break;
+ }
+ else
+ break;
+ }
+ return from_next - from;
+ }
+ } // anonymous namespace
+
+ // codecvt<char32_t, char, mbstate_t> required specialization
+ codecvt<char32_t, char, mbstate_t>::
+ codecvt(size_t __refs)
+ : __codecvt_abstract_base<char32_t, char, mbstate_t>(__refs),
+ _M_c_locale_codecvt(_S_get_c_locale())
+ { }
+
+ codecvt<char32_t, char, mbstate_t>::
+ codecvt(__c_locale __cloc, size_t __refs)
+ : __codecvt_abstract_base<char32_t, char, mbstate_t>(__refs),
+ _M_c_locale_codecvt(_S_clone_c_locale(__cloc))
+ { }
+
+ codecvt<char32_t, char, mbstate_t>::
+ ~codecvt()
+ { _S_destroy_c_locale(_M_c_locale_codecvt); }
+
+ codecvt_base::result
+ codecvt<char32_t, char, mbstate_t>::
+ do_out(mbstate_t&, const char32_t* from, const char32_t* from_end,
+ const char32_t*& from_next, char* to, char* to_end,
+ char*& to_next) const
+ { return utf32_to_utf8(from, from_end, from_next, to, to_end, to_next); }
+
+ codecvt_base::result
+ codecvt<char32_t, char, mbstate_t>::
+ do_unshift(state_type&, extern_type* __to,
+ extern_type*, extern_type*& __to_next) const
+ {
+ __to_next = __to;
+ return noconv;
+ }
+
+ codecvt_base::result
+ codecvt<char32_t, char, mbstate_t>::
+ do_in(mbstate_t&, const char* from, const char* from_end,
+ const char*& from_next, char32_t* to, char32_t* to_end,
+ char32_t*& to_next) const
+ { return utf8_to_utf32(from, from_end, from_next, to, to_end, to_next); }
+
+ int
+ codecvt<char32_t, char, mbstate_t>::
+ do_encoding() const _GLIBCXX_NOEXCEPT
+ { return 0; }
+
+ bool
+ codecvt<char32_t, char, mbstate_t>::
+ do_always_noconv() const _GLIBCXX_NOEXCEPT
+ { return false; }
+
+ int
+ codecvt<char32_t, char, mbstate_t>::
+ do_length(state_type&, const extern_type* __from,
+ const extern_type* __end, size_t __max) const
+ { return utf8_to_utf32_length(__from, __end, __max); }
+
+ int
+ codecvt<char32_t, char, mbstate_t>::
+ do_max_length() const _GLIBCXX_NOEXCEPT
+ { return 4; }
+#endif // _GLIBCXX_USE_C99_STDINT_TR1
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/src/c++11/locale_init.cc b/libstdc++-v3/src/c++11/locale_init.cc
new file mode 100644
index 0000000..80405fe
--- /dev/null
+++ b/libstdc++-v3/src/c++11/locale_init.cc
@@ -0,0 +1,487 @@
+// Copyright (C) 1997-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <clocale>
+#include <cstring>
+#include <cstdlib> // For getenv, free.
+#include <cctype>
+#include <cwctype> // For towupper, etc.
+#include <locale>
+#include <ext/concurrence.h>
+
+namespace
+{
+ __gnu_cxx::__mutex&
+ get_locale_mutex()
+ {
+ static __gnu_cxx::__mutex locale_mutex;
+ return locale_mutex;
+ }
+
+ using namespace std;
+
+ typedef char fake_locale_Impl[sizeof(locale::_Impl)]
+ __attribute__ ((aligned(__alignof__(locale::_Impl))));
+ fake_locale_Impl c_locale_impl;
+
+ typedef char fake_locale[sizeof(locale)]
+ __attribute__ ((aligned(__alignof__(locale))));
+ fake_locale c_locale;
+
+ typedef char fake_name_vec[sizeof(char*)]
+ __attribute__ ((aligned(__alignof__(char*))));
+ fake_name_vec name_vec[6 + _GLIBCXX_NUM_CATEGORIES];
+
+ typedef char fake_names[sizeof(char[2])]
+ __attribute__ ((aligned(__alignof__(char[2]))));
+ fake_names name_c[6 + _GLIBCXX_NUM_CATEGORIES];
+
+ typedef char fake_facet_vec[sizeof(locale::facet*)]
+ __attribute__ ((aligned(__alignof__(locale::facet*))));
+ fake_facet_vec facet_vec[_GLIBCXX_NUM_FACETS];
+
+ typedef char fake_cache_vec[sizeof(locale::facet*)]
+ __attribute__ ((aligned(__alignof__(locale::facet*))));
+ fake_cache_vec cache_vec[_GLIBCXX_NUM_FACETS];
+
+ typedef char fake_ctype_c[sizeof(std::ctype<char>)]
+ __attribute__ ((aligned(__alignof__(std::ctype<char>))));
+ fake_ctype_c ctype_c;
+
+ typedef char fake_collate_c[sizeof(std::collate<char>)]
+ __attribute__ ((aligned(__alignof__(std::collate<char>))));
+ fake_collate_c collate_c;
+
+ typedef char fake_numpunct_c[sizeof(numpunct<char>)]
+ __attribute__ ((aligned(__alignof__(numpunct<char>))));
+ fake_numpunct_c numpunct_c;
+
+ typedef char fake_num_get_c[sizeof(num_get<char>)]
+ __attribute__ ((aligned(__alignof__(num_get<char>))));
+ fake_num_get_c num_get_c;
+
+ typedef char fake_num_put_c[sizeof(num_put<char>)]
+ __attribute__ ((aligned(__alignof__(num_put<char>))));
+ fake_num_put_c num_put_c;
+
+ typedef char fake_codecvt_c[sizeof(codecvt<char, char, mbstate_t>)]
+ __attribute__ ((aligned(__alignof__(codecvt<char, char, mbstate_t>))));
+ fake_codecvt_c codecvt_c;
+
+ typedef char fake_moneypunct_c[sizeof(moneypunct<char, true>)]
+ __attribute__ ((aligned(__alignof__(moneypunct<char, true>))));
+ fake_moneypunct_c moneypunct_ct;
+ fake_moneypunct_c moneypunct_cf;
+
+ typedef char fake_money_get_c[sizeof(money_get<char>)]
+ __attribute__ ((aligned(__alignof__(money_get<char>))));
+ fake_money_get_c money_get_c;
+
+ typedef char fake_money_put_c[sizeof(money_put<char>)]
+ __attribute__ ((aligned(__alignof__(money_put<char>))));
+ fake_money_put_c money_put_c;
+
+ typedef char fake_timepunct_c[sizeof(__timepunct<char>)]
+ __attribute__ ((aligned(__alignof__(__timepunct<char>))));
+ fake_timepunct_c timepunct_c;
+
+ typedef char fake_time_get_c[sizeof(time_get<char>)]
+ __attribute__ ((aligned(__alignof__(time_get<char>))));
+ fake_time_get_c time_get_c;
+
+ typedef char fake_time_put_c[sizeof(time_put<char>)]
+ __attribute__ ((aligned(__alignof__(time_put<char>))));
+ fake_time_put_c time_put_c;
+
+ typedef char fake_messages_c[sizeof(messages<char>)]
+ __attribute__ ((aligned(__alignof__(messages<char>))));
+ fake_messages_c messages_c;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ typedef char fake_wtype_w[sizeof(std::ctype<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::ctype<wchar_t>))));
+ fake_wtype_w ctype_w;
+
+ typedef char fake_wollate_w[sizeof(std::collate<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::collate<wchar_t>))));
+ fake_wollate_w collate_w;
+
+ typedef char fake_numpunct_w[sizeof(numpunct<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(numpunct<wchar_t>))));
+ fake_numpunct_w numpunct_w;
+
+ typedef char fake_num_get_w[sizeof(num_get<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(num_get<wchar_t>))));
+ fake_num_get_w num_get_w;
+
+ typedef char fake_num_put_w[sizeof(num_put<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(num_put<wchar_t>))));
+ fake_num_put_w num_put_w;
+
+ typedef char fake_wodecvt_w[sizeof(codecvt<wchar_t, char, mbstate_t>)]
+ __attribute__ ((aligned(__alignof__(codecvt<wchar_t, char, mbstate_t>))));
+ fake_wodecvt_w codecvt_w;
+
+ typedef char fake_moneypunct_w[sizeof(moneypunct<wchar_t, true>)]
+ __attribute__ ((aligned(__alignof__(moneypunct<wchar_t, true>))));
+ fake_moneypunct_w moneypunct_wt;
+ fake_moneypunct_w moneypunct_wf;
+
+ typedef char fake_money_get_w[sizeof(money_get<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(money_get<wchar_t>))));
+ fake_money_get_w money_get_w;
+
+ typedef char fake_money_put_w[sizeof(money_put<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(money_put<wchar_t>))));
+ fake_money_put_w money_put_w;
+
+ typedef char fake_timepunct_w[sizeof(__timepunct<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(__timepunct<wchar_t>))));
+ fake_timepunct_w timepunct_w;
+
+ typedef char fake_time_get_w[sizeof(time_get<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(time_get<wchar_t>))));
+ fake_time_get_w time_get_w;
+
+ typedef char fake_time_put_w[sizeof(time_put<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(time_put<wchar_t>))));
+ fake_time_put_w time_put_w;
+
+ typedef char fake_messages_w[sizeof(messages<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(messages<wchar_t>))));
+ fake_messages_w messages_w;
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ typedef char fake_codecvt_c32[sizeof(codecvt<char32_t, char, mbstate_t>)]
+ __attribute__ ((aligned(__alignof__(codecvt<char32_t, char, mbstate_t>))));
+ fake_codecvt_c32 codecvt_c32;
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
+
+ // Storage for "C" locale caches.
+ typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)]
+ __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
+ fake_num_cache_c numpunct_cache_c;
+
+ typedef char fake_money_cache_c[sizeof(std::__moneypunct_cache<char, true>)]
+ __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<char, true>))));
+ fake_money_cache_c moneypunct_cache_ct;
+ fake_money_cache_c moneypunct_cache_cf;
+
+ typedef char fake_time_cache_c[sizeof(std::__timepunct_cache<char>)]
+ __attribute__ ((aligned(__alignof__(std::__timepunct_cache<char>))));
+ fake_time_cache_c timepunct_cache_c;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ typedef char fake_num_cache_w[sizeof(std::__numpunct_cache<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>))));
+ fake_num_cache_w numpunct_cache_w;
+
+ typedef char fake_money_cache_w[sizeof(std::__moneypunct_cache<wchar_t,true>)]
+ __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<wchar_t,true>))));
+ fake_money_cache_w moneypunct_cache_wt;
+ fake_money_cache_w moneypunct_cache_wf;
+
+ typedef char fake_time_cache_w[sizeof(std::__timepunct_cache<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::__timepunct_cache<wchar_t>))));
+ fake_time_cache_w timepunct_cache_w;
+#endif
+} // anonymous namespace
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ locale::locale() throw() : _M_impl(0)
+ {
+ _S_initialize();
+
+ // Checked locking to optimize the common case where _S_global
+ // still points to _S_classic (locale::_S_initialize_once()):
+ // - If they are the same, just increment the reference count and
+ // we are done. This effectively constructs a C locale object
+ // identical to the static c_locale.
+ // - Otherwise, _S_global can and may be destroyed due to
+ // locale::global() call on another thread, in which case we
+ // fall back to lock protected access to both _S_global and
+ // its reference count.
+ _M_impl = _S_global;
+ if (_M_impl == _S_classic)
+ _M_impl->_M_add_reference();
+ else
+ {
+ __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
+ _S_global->_M_add_reference();
+ _M_impl = _S_global;
+ }
+ }
+
+ locale
+ locale::global(const locale& __other)
+ {
+ _S_initialize();
+ _Impl* __old;
+ {
+ __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
+ __old = _S_global;
+ __other._M_impl->_M_add_reference();
+ _S_global = __other._M_impl;
+ const string __other_name = __other.name();
+ if (__other_name != "*")
+ setlocale(LC_ALL, __other_name.c_str());
+ }
+
+ // Reference count sanity check: one reference removed for the
+ // subsition of __other locale, one added by return-by-value. Net
+ // difference: zero. When the returned locale object's destrutor
+ // is called, then the reference count is decremented and possibly
+ // destroyed.
+ return locale(__old);
+ }
+
+ const locale&
+ locale::classic()
+ {
+ _S_initialize();
+ return *(new (&c_locale) locale(_S_classic));
+ }
+
+ void
+ locale::_S_initialize_once() throw()
+ {
+ // 2 references.
+ // One reference for _S_classic, one for _S_global
+ _S_classic = new (&c_locale_impl) _Impl(2);
+ _S_global = _S_classic;
+ }
+
+ void
+ locale::_S_initialize()
+ {
+#ifdef __GTHREADS
+ if (__gthread_active_p())
+ __gthread_once(&_S_once, _S_initialize_once);
+#endif
+ if (!_S_classic)
+ _S_initialize_once();
+ }
+
+ // Definitions for static const data members of locale::_Impl
+ const locale::id* const
+ locale::_Impl::_S_id_ctype[] =
+ {
+ &std::ctype<char>::id,
+ &codecvt<char, char, mbstate_t>::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &std::ctype<wchar_t>::id,
+ &codecvt<wchar_t, char, mbstate_t>::id,
+#endif
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ //&std::ctype<char32_t>::id, TODO
+ &codecvt<char32_t, char, mbstate_t>::id,
+#endif
+ 0
+ };
+
+ const locale::id* const
+ locale::_Impl::_S_id_numeric[] =
+ {
+ &num_get<char>::id,
+ &num_put<char>::id,
+ &numpunct<char>::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &num_get<wchar_t>::id,
+ &num_put<wchar_t>::id,
+ &numpunct<wchar_t>::id,
+#endif
+ 0
+ };
+
+ const locale::id* const
+ locale::_Impl::_S_id_collate[] =
+ {
+ &std::collate<char>::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &std::collate<wchar_t>::id,
+#endif
+ 0
+ };
+
+ const locale::id* const
+ locale::_Impl::_S_id_time[] =
+ {
+ &__timepunct<char>::id,
+ &time_get<char>::id,
+ &time_put<char>::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &__timepunct<wchar_t>::id,
+ &time_get<wchar_t>::id,
+ &time_put<wchar_t>::id,
+#endif
+ 0
+ };
+
+ const locale::id* const
+ locale::_Impl::_S_id_monetary[] =
+ {
+ &money_get<char>::id,
+ &money_put<char>::id,
+ &moneypunct<char, false>::id,
+ &moneypunct<char, true >::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &money_get<wchar_t>::id,
+ &money_put<wchar_t>::id,
+ &moneypunct<wchar_t, false>::id,
+ &moneypunct<wchar_t, true >::id,
+#endif
+ 0
+ };
+
+ const locale::id* const
+ locale::_Impl::_S_id_messages[] =
+ {
+ &std::messages<char>::id,
+#ifdef _GLIBCXX_USE_WCHAR_T
+ &std::messages<wchar_t>::id,
+#endif
+ 0
+ };
+
+ const locale::id* const* const
+ locale::_Impl::_S_facet_categories[] =
+ {
+ // Order must match the decl order in class locale.
+ locale::_Impl::_S_id_ctype,
+ locale::_Impl::_S_id_numeric,
+ locale::_Impl::_S_id_collate,
+ locale::_Impl::_S_id_time,
+ locale::_Impl::_S_id_monetary,
+ locale::_Impl::_S_id_messages,
+ 0
+ };
+
+ // Construct "C" _Impl.
+ locale::_Impl::
+ _Impl(size_t __refs) throw()
+ : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS),
+ _M_caches(0), _M_names(0)
+ {
+ _M_facets = new (&facet_vec) const facet*[_M_facets_size];
+ _M_caches = new (&cache_vec) const facet*[_M_facets_size];
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ _M_facets[__i] = _M_caches[__i] = 0;
+
+ // Name the categories.
+ _M_names = new (&name_vec) char*[_S_categories_size];
+ _M_names[0] = new (&name_c[0]) char[2];
+ std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2);
+ for (size_t __j = 1; __j < _S_categories_size; ++__j)
+ _M_names[__j] = 0;
+
+ // This is needed as presently the C++ version of "C" locales
+ // != data in the underlying locale model for __timepunct,
+ // numpunct, and moneypunct. Also, the "C" locales must be
+ // constructed in a way such that they are pre-allocated.
+ // NB: Set locale::facets(ref) count to one so that each individual
+ // facet is not destroyed when the locale (and thus locale::_Impl) is
+ // destroyed.
+ _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
+ _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
+
+ typedef __numpunct_cache<char> num_cache_c;
+ num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
+ _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
+
+ _M_init_facet(new (&num_get_c) num_get<char>(1));
+ _M_init_facet(new (&num_put_c) num_put<char>(1));
+ _M_init_facet(new (&collate_c) std::collate<char>(1));
+
+ typedef __moneypunct_cache<char, false> money_cache_cf;
+ typedef __moneypunct_cache<char, true> money_cache_ct;
+ money_cache_cf* __mpcf = new (&moneypunct_cache_cf) money_cache_cf(2);
+ _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1));
+ money_cache_ct* __mpct = new (&moneypunct_cache_ct) money_cache_ct(2);
+ _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1));
+
+ _M_init_facet(new (&money_get_c) money_get<char>(1));
+ _M_init_facet(new (&money_put_c) money_put<char>(1));
+
+ typedef __timepunct_cache<char> time_cache_c;
+ time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2);
+ _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1));
+
+ _M_init_facet(new (&time_get_c) time_get<char>(1));
+ _M_init_facet(new (&time_put_c) time_put<char>(1));
+ _M_init_facet(new (&messages_c) std::messages<char>(1));
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
+ _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
+
+ typedef __numpunct_cache<wchar_t> num_cache_w;
+ num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
+ _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
+
+ _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
+ _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
+ _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
+
+ typedef __moneypunct_cache<wchar_t, false> money_cache_wf;
+ typedef __moneypunct_cache<wchar_t, true> money_cache_wt;
+ money_cache_wf* __mpwf = new (&moneypunct_cache_wf) money_cache_wf(2);
+ _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1));
+ money_cache_wt* __mpwt = new (&moneypunct_cache_wt) money_cache_wt(2);
+ _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1));
+
+ _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
+ _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
+
+ typedef __timepunct_cache<wchar_t> time_cache_w;
+ time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2);
+ _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1));
+
+ _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
+ _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
+ _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ _M_init_facet(new (&codecvt_c32) codecvt<char32_t, char, mbstate_t>(1));
+ // TODO...
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
+
+ // This locale is safe to pre-cache, after all the facets have
+ // been created and installed.
+ _M_caches[numpunct<char>::id._M_id()] = __npc;
+ _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf;
+ _M_caches[moneypunct<char, true>::id._M_id()] = __mpct;
+ _M_caches[__timepunct<char>::id._M_id()] = __tpc;
+#ifdef _GLIBCXX_USE_WCHAR_T
+ _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
+ _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf;
+ _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt;
+ _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw;
+#endif
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/src/c++11/localename.cc b/libstdc++-v3/src/c++11/localename.cc
new file mode 100644
index 0000000..5f407a4
--- /dev/null
+++ b/libstdc++-v3/src/c++11/localename.cc
@@ -0,0 +1,357 @@
+// Copyright (C) 1997-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <clocale>
+#include <cstring>
+#include <cstdlib>
+#include <locale>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ using namespace __gnu_cxx;
+
+ locale::locale(const char* __s) : _M_impl(0)
+ {
+ if (__s)
+ {
+ _S_initialize();
+ if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0)
+ (_M_impl = _S_classic)->_M_add_reference();
+ else if (std::strcmp(__s, "") != 0)
+ _M_impl = new _Impl(__s, 1);
+ else
+ {
+ // Get it from the environment.
+ char* __env = std::getenv("LC_ALL");
+ // If LC_ALL is set we are done.
+ if (__env && std::strcmp(__env, "") != 0)
+ {
+ if (std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ (_M_impl = _S_classic)->_M_add_reference();
+ else
+ _M_impl = new _Impl(__env, 1);
+ }
+ else
+ {
+ // LANG may set a default different from "C".
+ string __lang;
+ __env = std::getenv("LANG");
+ if (!__env || std::strcmp(__env, "") == 0
+ || std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ __lang = "C";
+ else
+ __lang = __env;
+
+ // Scan the categories looking for the first one
+ // different from LANG.
+ size_t __i = 0;
+ if (__lang == "C")
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ if (__env && std::strcmp(__env, "") != 0
+ && std::strcmp(__env, "C") != 0
+ && std::strcmp(__env, "POSIX") != 0)
+ break;
+ }
+ else
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ if (__env && std::strcmp(__env, "") != 0
+ && __lang != __env)
+ break;
+ }
+
+ // If one is found, build the complete string of
+ // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
+ if (__i < _S_categories_size)
+ {
+ string __str;
+ __str.reserve(128);
+ for (size_t __j = 0; __j < __i; ++__j)
+ {
+ __str += _S_categories[__j];
+ __str += '=';
+ __str += __lang;
+ __str += ';';
+ }
+ __str += _S_categories[__i];
+ __str += '=';
+ __str += __env;
+ __str += ';';
+ ++__i;
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ __str += _S_categories[__i];
+ if (!__env || std::strcmp(__env, "") == 0)
+ {
+ __str += '=';
+ __str += __lang;
+ __str += ';';
+ }
+ else if (std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ __str += "=C;";
+ else
+ {
+ __str += '=';
+ __str += __env;
+ __str += ';';
+ }
+ }
+ __str.erase(__str.end() - 1);
+ _M_impl = new _Impl(__str.c_str(), 1);
+ }
+ // ... otherwise either an additional instance of
+ // the "C" locale or LANG.
+ else if (__lang == "C")
+ (_M_impl = _S_classic)->_M_add_reference();
+ else
+ _M_impl = new _Impl(__lang.c_str(), 1);
+ }
+ }
+ }
+ else
+ __throw_runtime_error(__N("locale::locale null not valid"));
+ }
+
+ locale::locale(const locale& __base, const char* __s, category __cat)
+ : _M_impl(0)
+ {
+ // NB: There are complicated, yet more efficient ways to do
+ // this. Building up locales on a per-category way is tedious, so
+ // let's do it this way until people complain.
+ locale __add(__s);
+ _M_coalesce(__base, __add, __cat);
+ }
+
+ locale::locale(const locale& __base, const locale& __add, category __cat)
+ : _M_impl(0)
+ { _M_coalesce(__base, __add, __cat); }
+
+ void
+ locale::_M_coalesce(const locale& __base, const locale& __add,
+ category __cat)
+ {
+ __cat = _S_normalize_category(__cat);
+ _M_impl = new _Impl(*__base._M_impl, 1);
+
+ __try
+ { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
+ __catch(...)
+ {
+ _M_impl->_M_remove_reference();
+ __throw_exception_again;
+ }
+ }
+
+ // Construct named _Impl.
+ locale::_Impl::
+ _Impl(const char* __s, size_t __refs)
+ : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS),
+ _M_caches(0), _M_names(0)
+ {
+ // Initialize the underlying locale model, which also checks to
+ // see if the given name is valid.
+ __c_locale __cloc;
+ locale::facet::_S_create_c_locale(__cloc, __s);
+ __c_locale __clocm = __cloc;
+
+ __try
+ {
+ _M_facets = new const facet*[_M_facets_size];
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ _M_facets[__i] = 0;
+ _M_caches = new const facet*[_M_facets_size];
+ for (size_t __j = 0; __j < _M_facets_size; ++__j)
+ _M_caches[__j] = 0;
+ _M_names = new char*[_S_categories_size];
+ for (size_t __k = 0; __k < _S_categories_size; ++__k)
+ _M_names[__k] = 0;
+
+ // Name the categories.
+ const char* __smon = __s;
+ const size_t __len = std::strlen(__s);
+ if (!std::memchr(__s, ';', __len))
+ {
+ _M_names[0] = new char[__len + 1];
+ std::memcpy(_M_names[0], __s, __len + 1);
+ }
+ else
+ {
+ const char* __end = __s;
+ bool __found_ctype = false;
+ bool __found_monetary = false;
+ size_t __ci = 0, __mi = 0;
+ for (size_t __i = 0; __i < _S_categories_size; ++__i)
+ {
+ const char* __beg = std::strchr(__end + 1, '=') + 1;
+ __end = std::strchr(__beg, ';');
+ if (!__end)
+ __end = __s + __len;
+ _M_names[__i] = new char[__end - __beg + 1];
+ std::memcpy(_M_names[__i], __beg, __end - __beg);
+ _M_names[__i][__end - __beg] = '\0';
+ if (!__found_ctype
+ && *(__beg - 2) == 'E' && *(__beg - 3) == 'P')
+ {
+ __found_ctype = true;
+ __ci = __i;
+ }
+ else if (!__found_monetary && *(__beg - 2) == 'Y')
+ {
+ __found_monetary = true;
+ __mi = __i;
+ }
+ }
+
+ if (std::strcmp(_M_names[__ci], _M_names[__mi]))
+ {
+ __smon = _M_names[__mi];
+ __clocm = locale::facet::_S_lc_ctype_c_locale(__cloc,
+ __smon);
+ }
+ }
+
+ // Construct all standard facets and add them to _M_facets.
+ _M_init_facet(new std::ctype<char>(__cloc, 0, false));
+ _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
+ _M_init_facet(new numpunct<char>(__cloc));
+ _M_init_facet(new num_get<char>);
+ _M_init_facet(new num_put<char>);
+ _M_init_facet(new std::collate<char>(__cloc));
+ _M_init_facet(new moneypunct<char, false>(__cloc, 0));
+ _M_init_facet(new moneypunct<char, true>(__cloc, 0));
+ _M_init_facet(new money_get<char>);
+ _M_init_facet(new money_put<char>);
+ _M_init_facet(new __timepunct<char>(__cloc, __s));
+ _M_init_facet(new time_get<char>);
+ _M_init_facet(new time_put<char>);
+ _M_init_facet(new std::messages<char>(__cloc, __s));
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ _M_init_facet(new std::ctype<wchar_t>(__cloc));
+ _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc));
+ _M_init_facet(new numpunct<wchar_t>(__cloc));
+ _M_init_facet(new num_get<wchar_t>);
+ _M_init_facet(new num_put<wchar_t>);
+ _M_init_facet(new std::collate<wchar_t>(__cloc));
+ _M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon));
+ _M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon));
+ _M_init_facet(new money_get<wchar_t>);
+ _M_init_facet(new money_put<wchar_t>);
+ _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
+ _M_init_facet(new time_get<wchar_t>);
+ _M_init_facet(new time_put<wchar_t>);
+ _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ _M_init_facet(new codecvt<char32_t, char, mbstate_t>(__cloc));
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
+
+ locale::facet::_S_destroy_c_locale(__cloc);
+ if (__clocm != __cloc)
+ locale::facet::_S_destroy_c_locale(__clocm);
+ }
+ __catch(...)
+ {
+ locale::facet::_S_destroy_c_locale(__cloc);
+ if (__clocm != __cloc)
+ locale::facet::_S_destroy_c_locale(__clocm);
+ this->~_Impl();
+ __throw_exception_again;
+ }
+ }
+
+ void
+ locale::_Impl::
+ _M_replace_categories(const _Impl* __imp, category __cat)
+ {
+ category __mask = 1;
+ if (!_M_names[0] || !__imp->_M_names[0])
+ {
+ if (_M_names[0])
+ {
+ delete [] _M_names[0];
+ _M_names[0] = 0; // Unnamed.
+ }
+
+ for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
+ {
+ if (__mask & __cat)
+ // Need to replace entry in _M_facets with other locale's info.
+ _M_replace_category(__imp, _S_facet_categories[__ix]);
+ }
+ }
+ else
+ {
+ if (!_M_names[1])
+ {
+ // A full set of _M_names must be prepared, all identical
+ // to _M_names[0] to begin with. Then, below, a few will
+ // be replaced by the corresponding __imp->_M_names. I.e.,
+ // not a "simple" locale anymore (see locale::operator==).
+ const size_t __len = std::strlen(_M_names[0]) + 1;
+ for (size_t __i = 1; __i < _S_categories_size; ++__i)
+ {
+ _M_names[__i] = new char[__len];
+ std::memcpy(_M_names[__i], _M_names[0], __len);
+ }
+ }
+
+ for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
+ {
+ if (__mask & __cat)
+ {
+ // Need to replace entry in _M_facets with other locale's info.
+ _M_replace_category(__imp, _S_facet_categories[__ix]);
+
+ // FIXME: Hack for libstdc++/29217: the numerical encodings
+ // of the time and collate categories are swapped vs the
+ // order of the names in locale::_S_categories. We'd like to
+ // adjust the former (the latter is dictated by compatibility
+ // with glibc) but we can't for binary compatibility.
+ size_t __ix_name = __ix;
+ if (__ix == 2 || __ix == 3)
+ __ix_name = 5 - __ix;
+
+ char* __src = __imp->_M_names[__ix_name] ?
+ __imp->_M_names[__ix_name] : __imp->_M_names[0];
+ const size_t __len = std::strlen(__src) + 1;
+ char* __new = new char[__len];
+ std::memcpy(__new, __src, __len);
+ delete [] _M_names[__ix_name];
+ _M_names[__ix_name] = __new;
+ }
+ }
+ }
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am
index a714fe9..c0286b5 100644
--- a/libstdc++-v3/src/c++98/Makefile.am
+++ b/libstdc++-v3/src/c++98/Makefile.am
@@ -123,9 +123,7 @@ sources = \
list_associated.cc \
list_associated-2.cc \
locale.cc \
- locale_init.cc \
locale_facets.cc \
- localename.cc \
math_stubs_float.cc \
math_stubs_long_double.cc \
stdexcept.cc \
diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in
index 691614f..5a5b8f1 100644
--- a/libstdc++-v3/src/c++98/Makefile.in
+++ b/libstdc++-v3/src/c++98/Makefile.in
@@ -85,10 +85,9 @@ am__objects_5 = bitmap_allocator.lo pool_allocator.lo mt_allocator.lo \
hashtable_tr1.lo ios.lo ios_failure.lo ios_init.lo \
ios_locale.lo list.lo list-aux.lo list-aux-2.lo \
list_associated.lo list_associated-2.lo locale.lo \
- locale_init.lo locale_facets.lo localename.lo \
- math_stubs_float.lo math_stubs_long_double.lo stdexcept.lo \
- strstream.lo tree.lo istream.lo streambuf.lo valarray.lo \
- $(am__objects_1) $(am__objects_4)
+ locale_facets.lo math_stubs_float.lo math_stubs_long_double.lo \
+ stdexcept.lo strstream.lo tree.lo istream.lo streambuf.lo \
+ valarray.lo $(am__objects_1) $(am__objects_4)
am_libc__98convenience_la_OBJECTS = $(am__objects_5)
libc__98convenience_la_OBJECTS = $(am_libc__98convenience_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@@ -387,9 +386,7 @@ sources = \
list_associated.cc \
list_associated-2.cc \
locale.cc \
- locale_init.cc \
locale_facets.cc \
- localename.cc \
math_stubs_float.cc \
math_stubs_long_double.cc \
stdexcept.cc \
diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
deleted file mode 100644
index 2c6dfc5..0000000
--- a/libstdc++-v3/src/c++98/locale_init.cc
+++ /dev/null
@@ -1,472 +0,0 @@
-// Copyright (C) 1997-2014 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-// <http://www.gnu.org/licenses/>.
-
-#include <clocale>
-#include <cstring>
-#include <cstdlib> // For getenv, free.
-#include <cctype>
-#include <cwctype> // For towupper, etc.
-#include <locale>
-#include <ext/concurrence.h>
-
-namespace
-{
- __gnu_cxx::__mutex&
- get_locale_mutex()
- {
- static __gnu_cxx::__mutex locale_mutex;
- return locale_mutex;
- }
-
- using namespace std;
-
- typedef char fake_locale_Impl[sizeof(locale::_Impl)]
- __attribute__ ((aligned(__alignof__(locale::_Impl))));
- fake_locale_Impl c_locale_impl;
-
- typedef char fake_locale[sizeof(locale)]
- __attribute__ ((aligned(__alignof__(locale))));
- fake_locale c_locale;
-
- typedef char fake_name_vec[sizeof(char*)]
- __attribute__ ((aligned(__alignof__(char*))));
- fake_name_vec name_vec[6 + _GLIBCXX_NUM_CATEGORIES];
-
- typedef char fake_names[sizeof(char[2])]
- __attribute__ ((aligned(__alignof__(char[2]))));
- fake_names name_c[6 + _GLIBCXX_NUM_CATEGORIES];
-
- typedef char fake_facet_vec[sizeof(locale::facet*)]
- __attribute__ ((aligned(__alignof__(locale::facet*))));
- fake_facet_vec facet_vec[_GLIBCXX_NUM_FACETS];
-
- typedef char fake_cache_vec[sizeof(locale::facet*)]
- __attribute__ ((aligned(__alignof__(locale::facet*))));
- fake_cache_vec cache_vec[_GLIBCXX_NUM_FACETS];
-
- typedef char fake_ctype_c[sizeof(std::ctype<char>)]
- __attribute__ ((aligned(__alignof__(std::ctype<char>))));
- fake_ctype_c ctype_c;
-
- typedef char fake_collate_c[sizeof(std::collate<char>)]
- __attribute__ ((aligned(__alignof__(std::collate<char>))));
- fake_collate_c collate_c;
-
- typedef char fake_numpunct_c[sizeof(numpunct<char>)]
- __attribute__ ((aligned(__alignof__(numpunct<char>))));
- fake_numpunct_c numpunct_c;
-
- typedef char fake_num_get_c[sizeof(num_get<char>)]
- __attribute__ ((aligned(__alignof__(num_get<char>))));
- fake_num_get_c num_get_c;
-
- typedef char fake_num_put_c[sizeof(num_put<char>)]
- __attribute__ ((aligned(__alignof__(num_put<char>))));
- fake_num_put_c num_put_c;
-
- typedef char fake_codecvt_c[sizeof(codecvt<char, char, mbstate_t>)]
- __attribute__ ((aligned(__alignof__(codecvt<char, char, mbstate_t>))));
- fake_codecvt_c codecvt_c;
-
- typedef char fake_moneypunct_c[sizeof(moneypunct<char, true>)]
- __attribute__ ((aligned(__alignof__(moneypunct<char, true>))));
- fake_moneypunct_c moneypunct_ct;
- fake_moneypunct_c moneypunct_cf;
-
- typedef char fake_money_get_c[sizeof(money_get<char>)]
- __attribute__ ((aligned(__alignof__(money_get<char>))));
- fake_money_get_c money_get_c;
-
- typedef char fake_money_put_c[sizeof(money_put<char>)]
- __attribute__ ((aligned(__alignof__(money_put<char>))));
- fake_money_put_c money_put_c;
-
- typedef char fake_timepunct_c[sizeof(__timepunct<char>)]
- __attribute__ ((aligned(__alignof__(__timepunct<char>))));
- fake_timepunct_c timepunct_c;
-
- typedef char fake_time_get_c[sizeof(time_get<char>)]
- __attribute__ ((aligned(__alignof__(time_get<char>))));
- fake_time_get_c time_get_c;
-
- typedef char fake_time_put_c[sizeof(time_put<char>)]
- __attribute__ ((aligned(__alignof__(time_put<char>))));
- fake_time_put_c time_put_c;
-
- typedef char fake_messages_c[sizeof(messages<char>)]
- __attribute__ ((aligned(__alignof__(messages<char>))));
- fake_messages_c messages_c;
-
-#ifdef _GLIBCXX_USE_WCHAR_T
- typedef char fake_wtype_w[sizeof(std::ctype<wchar_t>)]
- __attribute__ ((aligned(__alignof__(std::ctype<wchar_t>))));
- fake_wtype_w ctype_w;
-
- typedef char fake_wollate_w[sizeof(std::collate<wchar_t>)]
- __attribute__ ((aligned(__alignof__(std::collate<wchar_t>))));
- fake_wollate_w collate_w;
-
- typedef char fake_numpunct_w[sizeof(numpunct<wchar_t>)]
- __attribute__ ((aligned(__alignof__(numpunct<wchar_t>))));
- fake_numpunct_w numpunct_w;
-
- typedef char fake_num_get_w[sizeof(num_get<wchar_t>)]
- __attribute__ ((aligned(__alignof__(num_get<wchar_t>))));
- fake_num_get_w num_get_w;
-
- typedef char fake_num_put_w[sizeof(num_put<wchar_t>)]
- __attribute__ ((aligned(__alignof__(num_put<wchar_t>))));
- fake_num_put_w num_put_w;
-
- typedef char fake_wodecvt_w[sizeof(codecvt<wchar_t, char, mbstate_t>)]
- __attribute__ ((aligned(__alignof__(codecvt<wchar_t, char, mbstate_t>))));
- fake_wodecvt_w codecvt_w;
-
- typedef char fake_moneypunct_w[sizeof(moneypunct<wchar_t, true>)]
- __attribute__ ((aligned(__alignof__(moneypunct<wchar_t, true>))));
- fake_moneypunct_w moneypunct_wt;
- fake_moneypunct_w moneypunct_wf;
-
- typedef char fake_money_get_w[sizeof(money_get<wchar_t>)]
- __attribute__ ((aligned(__alignof__(money_get<wchar_t>))));
- fake_money_get_w money_get_w;
-
- typedef char fake_money_put_w[sizeof(money_put<wchar_t>)]
- __attribute__ ((aligned(__alignof__(money_put<wchar_t>))));
- fake_money_put_w money_put_w;
-
- typedef char fake_timepunct_w[sizeof(__timepunct<wchar_t>)]
- __attribute__ ((aligned(__alignof__(__timepunct<wchar_t>))));
- fake_timepunct_w timepunct_w;
-
- typedef char fake_time_get_w[sizeof(time_get<wchar_t>)]
- __attribute__ ((aligned(__alignof__(time_get<wchar_t>))));
- fake_time_get_w time_get_w;
-
- typedef char fake_time_put_w[sizeof(time_put<wchar_t>)]
- __attribute__ ((aligned(__alignof__(time_put<wchar_t>))));
- fake_time_put_w time_put_w;
-
- typedef char fake_messages_w[sizeof(messages<wchar_t>)]
- __attribute__ ((aligned(__alignof__(messages<wchar_t>))));
- fake_messages_w messages_w;
-#endif
-
- // Storage for "C" locale caches.
- typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)]
- __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
- fake_num_cache_c numpunct_cache_c;
-
- typedef char fake_money_cache_c[sizeof(std::__moneypunct_cache<char, true>)]
- __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<char, true>))));
- fake_money_cache_c moneypunct_cache_ct;
- fake_money_cache_c moneypunct_cache_cf;
-
- typedef char fake_time_cache_c[sizeof(std::__timepunct_cache<char>)]
- __attribute__ ((aligned(__alignof__(std::__timepunct_cache<char>))));
- fake_time_cache_c timepunct_cache_c;
-
-#ifdef _GLIBCXX_USE_WCHAR_T
- typedef char fake_num_cache_w[sizeof(std::__numpunct_cache<wchar_t>)]
- __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>))));
- fake_num_cache_w numpunct_cache_w;
-
- typedef char fake_money_cache_w[sizeof(std::__moneypunct_cache<wchar_t,true>)]
- __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<wchar_t,true>))));
- fake_money_cache_w moneypunct_cache_wt;
- fake_money_cache_w moneypunct_cache_wf;
-
- typedef char fake_time_cache_w[sizeof(std::__timepunct_cache<wchar_t>)]
- __attribute__ ((aligned(__alignof__(std::__timepunct_cache<wchar_t>))));
- fake_time_cache_w timepunct_cache_w;
-#endif
-} // anonymous namespace
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- locale::locale() throw() : _M_impl(0)
- {
- _S_initialize();
-
- // Checked locking to optimize the common case where _S_global
- // still points to _S_classic (locale::_S_initialize_once()):
- // - If they are the same, just increment the reference count and
- // we are done. This effectively constructs a C locale object
- // identical to the static c_locale.
- // - Otherwise, _S_global can and may be destroyed due to
- // locale::global() call on another thread, in which case we
- // fall back to lock protected access to both _S_global and
- // its reference count.
- _M_impl = _S_global;
- if (_M_impl == _S_classic)
- _M_impl->_M_add_reference();
- else
- {
- __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
- _S_global->_M_add_reference();
- _M_impl = _S_global;
- }
- }
-
- locale
- locale::global(const locale& __other)
- {
- _S_initialize();
- _Impl* __old;
- {
- __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
- __old = _S_global;
- __other._M_impl->_M_add_reference();
- _S_global = __other._M_impl;
- const string __other_name = __other.name();
- if (__other_name != "*")
- setlocale(LC_ALL, __other_name.c_str());
- }
-
- // Reference count sanity check: one reference removed for the
- // subsition of __other locale, one added by return-by-value. Net
- // difference: zero. When the returned locale object's destrutor
- // is called, then the reference count is decremented and possibly
- // destroyed.
- return locale(__old);
- }
-
- const locale&
- locale::classic()
- {
- _S_initialize();
- return *(new (&c_locale) locale(_S_classic));
- }
-
- void
- locale::_S_initialize_once() throw()
- {
- // 2 references.
- // One reference for _S_classic, one for _S_global
- _S_classic = new (&c_locale_impl) _Impl(2);
- _S_global = _S_classic;
- }
-
- void
- locale::_S_initialize()
- {
-#ifdef __GTHREADS
- if (__gthread_active_p())
- __gthread_once(&_S_once, _S_initialize_once);
-#endif
- if (!_S_classic)
- _S_initialize_once();
- }
-
- // Definitions for static const data members of locale::_Impl
- const locale::id* const
- locale::_Impl::_S_id_ctype[] =
- {
- &std::ctype<char>::id,
- &codecvt<char, char, mbstate_t>::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &std::ctype<wchar_t>::id,
- &codecvt<wchar_t, char, mbstate_t>::id,
-#endif
- 0
- };
-
- const locale::id* const
- locale::_Impl::_S_id_numeric[] =
- {
- &num_get<char>::id,
- &num_put<char>::id,
- &numpunct<char>::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &num_get<wchar_t>::id,
- &num_put<wchar_t>::id,
- &numpunct<wchar_t>::id,
-#endif
- 0
- };
-
- const locale::id* const
- locale::_Impl::_S_id_collate[] =
- {
- &std::collate<char>::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &std::collate<wchar_t>::id,
-#endif
- 0
- };
-
- const locale::id* const
- locale::_Impl::_S_id_time[] =
- {
- &__timepunct<char>::id,
- &time_get<char>::id,
- &time_put<char>::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &__timepunct<wchar_t>::id,
- &time_get<wchar_t>::id,
- &time_put<wchar_t>::id,
-#endif
- 0
- };
-
- const locale::id* const
- locale::_Impl::_S_id_monetary[] =
- {
- &money_get<char>::id,
- &money_put<char>::id,
- &moneypunct<char, false>::id,
- &moneypunct<char, true >::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &money_get<wchar_t>::id,
- &money_put<wchar_t>::id,
- &moneypunct<wchar_t, false>::id,
- &moneypunct<wchar_t, true >::id,
-#endif
- 0
- };
-
- const locale::id* const
- locale::_Impl::_S_id_messages[] =
- {
- &std::messages<char>::id,
-#ifdef _GLIBCXX_USE_WCHAR_T
- &std::messages<wchar_t>::id,
-#endif
- 0
- };
-
- const locale::id* const* const
- locale::_Impl::_S_facet_categories[] =
- {
- // Order must match the decl order in class locale.
- locale::_Impl::_S_id_ctype,
- locale::_Impl::_S_id_numeric,
- locale::_Impl::_S_id_collate,
- locale::_Impl::_S_id_time,
- locale::_Impl::_S_id_monetary,
- locale::_Impl::_S_id_messages,
- 0
- };
-
- // Construct "C" _Impl.
- locale::_Impl::
- _Impl(size_t __refs) throw()
- : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS),
- _M_caches(0), _M_names(0)
- {
- _M_facets = new (&facet_vec) const facet*[_M_facets_size];
- _M_caches = new (&cache_vec) const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- _M_facets[__i] = _M_caches[__i] = 0;
-
- // Name the categories.
- _M_names = new (&name_vec) char*[_S_categories_size];
- _M_names[0] = new (&name_c[0]) char[2];
- std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2);
- for (size_t __j = 1; __j < _S_categories_size; ++__j)
- _M_names[__j] = 0;
-
- // This is needed as presently the C++ version of "C" locales
- // != data in the underlying locale model for __timepunct,
- // numpunct, and moneypunct. Also, the "C" locales must be
- // constructed in a way such that they are pre-allocated.
- // NB: Set locale::facets(ref) count to one so that each individual
- // facet is not destroyed when the locale (and thus locale::_Impl) is
- // destroyed.
- _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
- _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
-
- typedef __numpunct_cache<char> num_cache_c;
- num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
- _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
-
- _M_init_facet(new (&num_get_c) num_get<char>(1));
- _M_init_facet(new (&num_put_c) num_put<char>(1));
- _M_init_facet(new (&collate_c) std::collate<char>(1));
-
- typedef __moneypunct_cache<char, false> money_cache_cf;
- typedef __moneypunct_cache<char, true> money_cache_ct;
- money_cache_cf* __mpcf = new (&moneypunct_cache_cf) money_cache_cf(2);
- _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1));
- money_cache_ct* __mpct = new (&moneypunct_cache_ct) money_cache_ct(2);
- _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1));
-
- _M_init_facet(new (&money_get_c) money_get<char>(1));
- _M_init_facet(new (&money_put_c) money_put<char>(1));
-
- typedef __timepunct_cache<char> time_cache_c;
- time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2);
- _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1));
-
- _M_init_facet(new (&time_get_c) time_get<char>(1));
- _M_init_facet(new (&time_put_c) time_put<char>(1));
- _M_init_facet(new (&messages_c) std::messages<char>(1));
-
-#ifdef _GLIBCXX_USE_WCHAR_T
- _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
- _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
-
- typedef __numpunct_cache<wchar_t> num_cache_w;
- num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
- _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
-
- _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
- _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
- _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
-
- typedef __moneypunct_cache<wchar_t, false> money_cache_wf;
- typedef __moneypunct_cache<wchar_t, true> money_cache_wt;
- money_cache_wf* __mpwf = new (&moneypunct_cache_wf) money_cache_wf(2);
- _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1));
- money_cache_wt* __mpwt = new (&moneypunct_cache_wt) money_cache_wt(2);
- _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1));
-
- _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
- _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
-
- typedef __timepunct_cache<wchar_t> time_cache_w;
- time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2);
- _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1));
-
- _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
- _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
- _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
-#endif
-
- // This locale is safe to pre-cache, after all the facets have
- // been created and installed.
- _M_caches[numpunct<char>::id._M_id()] = __npc;
- _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf;
- _M_caches[moneypunct<char, true>::id._M_id()] = __mpct;
- _M_caches[__timepunct<char>::id._M_id()] = __tpc;
-#ifdef _GLIBCXX_USE_WCHAR_T
- _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
- _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf;
- _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt;
- _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw;
-#endif
- }
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
diff --git a/libstdc++-v3/src/c++98/localename.cc b/libstdc++-v3/src/c++98/localename.cc
deleted file mode 100644
index e93c846..0000000
--- a/libstdc++-v3/src/c++98/localename.cc
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (C) 1997-2014 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-// <http://www.gnu.org/licenses/>.
-
-#include <clocale>
-#include <cstring>
-#include <cstdlib>
-#include <locale>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
- using namespace __gnu_cxx;
-
- locale::locale(const char* __s) : _M_impl(0)
- {
- if (__s)
- {
- _S_initialize();
- if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0)
- (_M_impl = _S_classic)->_M_add_reference();
- else if (std::strcmp(__s, "") != 0)
- _M_impl = new _Impl(__s, 1);
- else
- {
- // Get it from the environment.
- char* __env = std::getenv("LC_ALL");
- // If LC_ALL is set we are done.
- if (__env && std::strcmp(__env, "") != 0)
- {
- if (std::strcmp(__env, "C") == 0
- || std::strcmp(__env, "POSIX") == 0)
- (_M_impl = _S_classic)->_M_add_reference();
- else
- _M_impl = new _Impl(__env, 1);
- }
- else
- {
- // LANG may set a default different from "C".
- string __lang;
- __env = std::getenv("LANG");
- if (!__env || std::strcmp(__env, "") == 0
- || std::strcmp(__env, "C") == 0
- || std::strcmp(__env, "POSIX") == 0)
- __lang = "C";
- else
- __lang = __env;
-
- // Scan the categories looking for the first one
- // different from LANG.
- size_t __i = 0;
- if (__lang == "C")
- for (; __i < _S_categories_size; ++__i)
- {
- __env = std::getenv(_S_categories[__i]);
- if (__env && std::strcmp(__env, "") != 0
- && std::strcmp(__env, "C") != 0
- && std::strcmp(__env, "POSIX") != 0)
- break;
- }
- else
- for (; __i < _S_categories_size; ++__i)
- {
- __env = std::getenv(_S_categories[__i]);
- if (__env && std::strcmp(__env, "") != 0
- && __lang != __env)
- break;
- }
-
- // If one is found, build the complete string of
- // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
- if (__i < _S_categories_size)
- {
- string __str;
- __str.reserve(128);
- for (size_t __j = 0; __j < __i; ++__j)
- {
- __str += _S_categories[__j];
- __str += '=';
- __str += __lang;
- __str += ';';
- }
- __str += _S_categories[__i];
- __str += '=';
- __str += __env;
- __str += ';';
- ++__i;
- for (; __i < _S_categories_size; ++__i)
- {
- __env = std::getenv(_S_categories[__i]);
- __str += _S_categories[__i];
- if (!__env || std::strcmp(__env, "") == 0)
- {
- __str += '=';
- __str += __lang;
- __str += ';';
- }
- else if (std::strcmp(__env, "C") == 0
- || std::strcmp(__env, "POSIX") == 0)
- __str += "=C;";
- else
- {
- __str += '=';
- __str += __env;
- __str += ';';
- }
- }
- __str.erase(__str.end() - 1);
- _M_impl = new _Impl(__str.c_str(), 1);
- }
- // ... otherwise either an additional instance of
- // the "C" locale or LANG.
- else if (__lang == "C")
- (_M_impl = _S_classic)->_M_add_reference();
- else
- _M_impl = new _Impl(__lang.c_str(), 1);
- }
- }
- }
- else
- __throw_runtime_error(__N("locale::locale null not valid"));
- }
-
- locale::locale(const locale& __base, const char* __s, category __cat)
- : _M_impl(0)
- {
- // NB: There are complicated, yet more efficient ways to do
- // this. Building up locales on a per-category way is tedious, so
- // let's do it this way until people complain.
- locale __add(__s);
- _M_coalesce(__base, __add, __cat);
- }
-
- locale::locale(const locale& __base, const locale& __add, category __cat)
- : _M_impl(0)
- { _M_coalesce(__base, __add, __cat); }
-
- void
- locale::_M_coalesce(const locale& __base, const locale& __add,
- category __cat)
- {
- __cat = _S_normalize_category(__cat);
- _M_impl = new _Impl(*__base._M_impl, 1);
-
- __try
- { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
- __catch(...)
- {
- _M_impl->_M_remove_reference();
- __throw_exception_again;
- }
- }
-
- // Construct named _Impl.
- locale::_Impl::
- _Impl(const char* __s, size_t __refs)
- : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS),
- _M_caches(0), _M_names(0)
- {
- // Initialize the underlying locale model, which also checks to
- // see if the given name is valid.
- __c_locale __cloc;
- locale::facet::_S_create_c_locale(__cloc, __s);
- __c_locale __clocm = __cloc;
-
- __try
- {
- _M_facets = new const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- _M_facets[__i] = 0;
- _M_caches = new const facet*[_M_facets_size];
- for (size_t __j = 0; __j < _M_facets_size; ++__j)
- _M_caches[__j] = 0;
- _M_names = new char*[_S_categories_size];
- for (size_t __k = 0; __k < _S_categories_size; ++__k)
- _M_names[__k] = 0;
-
- // Name the categories.
- const char* __smon = __s;
- const size_t __len = std::strlen(__s);
- if (!std::memchr(__s, ';', __len))
- {
- _M_names[0] = new char[__len + 1];
- std::memcpy(_M_names[0], __s, __len + 1);
- }
- else
- {
- const char* __end = __s;
- bool __found_ctype = false;
- bool __found_monetary = false;
- size_t __ci = 0, __mi = 0;
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- {
- const char* __beg = std::strchr(__end + 1, '=') + 1;
- __end = std::strchr(__beg, ';');
- if (!__end)
- __end = __s + __len;
- _M_names[__i] = new char[__end - __beg + 1];
- std::memcpy(_M_names[__i], __beg, __end - __beg);
- _M_names[__i][__end - __beg] = '\0';
- if (!__found_ctype
- && *(__beg - 2) == 'E' && *(__beg - 3) == 'P')
- {
- __found_ctype = true;
- __ci = __i;
- }
- else if (!__found_monetary && *(__beg - 2) == 'Y')
- {
- __found_monetary = true;
- __mi = __i;
- }
- }
-
- if (std::strcmp(_M_names[__ci], _M_names[__mi]))
- {
- __smon = _M_names[__mi];
- __clocm = locale::facet::_S_lc_ctype_c_locale(__cloc,
- __smon);
- }
- }
-
- // Construct all standard facets and add them to _M_facets.
- _M_init_facet(new std::ctype<char>(__cloc, 0, false));
- _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
- _M_init_facet(new numpunct<char>(__cloc));
- _M_init_facet(new num_get<char>);
- _M_init_facet(new num_put<char>);
- _M_init_facet(new std::collate<char>(__cloc));
- _M_init_facet(new moneypunct<char, false>(__cloc, 0));
- _M_init_facet(new moneypunct<char, true>(__cloc, 0));
- _M_init_facet(new money_get<char>);
- _M_init_facet(new money_put<char>);
- _M_init_facet(new __timepunct<char>(__cloc, __s));
- _M_init_facet(new time_get<char>);
- _M_init_facet(new time_put<char>);
- _M_init_facet(new std::messages<char>(__cloc, __s));
-
-#ifdef _GLIBCXX_USE_WCHAR_T
- _M_init_facet(new std::ctype<wchar_t>(__cloc));
- _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc));
- _M_init_facet(new numpunct<wchar_t>(__cloc));
- _M_init_facet(new num_get<wchar_t>);
- _M_init_facet(new num_put<wchar_t>);
- _M_init_facet(new std::collate<wchar_t>(__cloc));
- _M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon));
- _M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon));
- _M_init_facet(new money_get<wchar_t>);
- _M_init_facet(new money_put<wchar_t>);
- _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
- _M_init_facet(new time_get<wchar_t>);
- _M_init_facet(new time_put<wchar_t>);
- _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
-#endif
- locale::facet::_S_destroy_c_locale(__cloc);
- if (__clocm != __cloc)
- locale::facet::_S_destroy_c_locale(__clocm);
- }
- __catch(...)
- {
- locale::facet::_S_destroy_c_locale(__cloc);
- if (__clocm != __cloc)
- locale::facet::_S_destroy_c_locale(__clocm);
- this->~_Impl();
- __throw_exception_again;
- }
- }
-
- void
- locale::_Impl::
- _M_replace_categories(const _Impl* __imp, category __cat)
- {
- category __mask = 1;
- if (!_M_names[0] || !__imp->_M_names[0])
- {
- if (_M_names[0])
- {
- delete [] _M_names[0];
- _M_names[0] = 0; // Unnamed.
- }
-
- for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
- {
- if (__mask & __cat)
- // Need to replace entry in _M_facets with other locale's info.
- _M_replace_category(__imp, _S_facet_categories[__ix]);
- }
- }
- else
- {
- if (!_M_names[1])
- {
- // A full set of _M_names must be prepared, all identical
- // to _M_names[0] to begin with. Then, below, a few will
- // be replaced by the corresponding __imp->_M_names. I.e.,
- // not a "simple" locale anymore (see locale::operator==).
- const size_t __len = std::strlen(_M_names[0]) + 1;
- for (size_t __i = 1; __i < _S_categories_size; ++__i)
- {
- _M_names[__i] = new char[__len];
- std::memcpy(_M_names[__i], _M_names[0], __len);
- }
- }
-
- for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
- {
- if (__mask & __cat)
- {
- // Need to replace entry in _M_facets with other locale's info.
- _M_replace_category(__imp, _S_facet_categories[__ix]);
-
- // FIXME: Hack for libstdc++/29217: the numerical encodings
- // of the time and collate categories are swapped vs the
- // order of the names in locale::_S_categories. We'd like to
- // adjust the former (the latter is dictated by compatibility
- // with glibc) but we can't for binary compatibility.
- size_t __ix_name = __ix;
- if (__ix == 2 || __ix == 3)
- __ix_name = 5 - __ix;
-
- char* __src = __imp->_M_names[__ix_name] ?
- __imp->_M_names[__ix_name] : __imp->_M_names[0];
- const size_t __len = std::strlen(__src) + 1;
- char* __new = new char[__len];
- std::memcpy(__new, __src, __len);
- delete [] _M_names[__ix_name];
- _M_names[__ix_name] = __new;
- }
- }
- }
- }
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/char32_t/1.cc b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t/1.cc
new file mode 100644
index 0000000..c31a845
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/codecvt/char32_t/1.cc
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++11" }
+
+// 2014-04-24 RÃÂdiger Sonderfeld
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 3, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// [locale.codecvt], C++11 22.4.1.4. specialization.
+
+#include <locale>
+#include <cstring>
+#include <testsuite_hooks.h>
+
+// from 22_locale/codecvt/in/wchar_t/1.cc
+void
+zero_state(std::mbstate_t& state)
+{ std::memset(&state, 0, sizeof(std::mbstate_t)); }
+
+void
+test01()
+{
+ using namespace std;
+ typedef codecvt<char32_t, char, mbstate_t> codecvt_c32;
+ locale loc_c = locale::classic();
+ VERIFY(has_facet<codecvt_c32>(loc_c));
+ const codecvt_c32* const cvt = &use_facet<codecvt_c32>(loc_c);
+
+ VERIFY(not cvt->always_noconv());
+ VERIFY(cvt->max_length() == 4);
+ VERIFY(cvt->encoding() == 0);
+
+ const char u8dat[] = u8"HÃÂllÃÂ ÃÂÂÂ ÃÂÂ ÃÂÂ f(ÃÂ) exp(-2ÃÂÃÂ) dÃÂ ÃÂÂÂ ÃÂÂÂ ÃÂÂÂ ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ ÃÂÂ";
+ const char* const u8dat_end = u8dat + sizeof(u8dat);
+
+ const char32_t u32dat[] = U"H\U000000E4ll\U000000F6 \U0001F63F \U000056FD "
+ U"\U0000222B f(\U000003BA) exp(-2\U000003C0\U000003C9) d\U000003BA "
+ U"\U0001F6BF \U0001F6BF \U0001F648 \U00000413\U00000435\U0000043E"
+ U"\U00000433\U00000440\U00000430\U00000444\U00000438\U0000044F \U0000FB05";
+ const char32_t* const u32dat_end = u32dat + sizeof(u32dat)/sizeof(*u32dat);
+
+ {
+ const size_t len = u32dat_end - u32dat + 1;
+ char32_t* const buffer = new char32_t[len];
+ char32_t* const buffer_end = buffer + len;
+
+ const char* from_next;
+ char32_t* to_next;
+
+ codecvt_c32::state_type state01;
+ zero_state(state01);
+ codecvt_base::result res = cvt->in(state01, u8dat, u8dat_end, from_next,
+ buffer, buffer_end, to_next);
+
+ VERIFY(res == codecvt_base::ok);
+ VERIFY(from_next == u8dat_end);
+ VERIFY(memcmp((void*)buffer, (void*)u32dat, sizeof(u32dat)) == 0);
+
+ delete[]buffer;
+ }
+
+ {
+ const size_t len = u8dat_end - u8dat + 1;
+ char* const buffer = new char[len];
+ char* const buffer_end = buffer + len;
+
+ const char32_t* from_next;
+ char* to_next;
+
+ codecvt_c32::state_type state01;
+ zero_state(state01);
+ codecvt_base::result res = cvt->out(state01, u32dat, u32dat_end, from_next,
+ buffer, buffer_end, to_next);
+
+ VERIFY(res == codecvt_base::ok);
+ VERIFY(from_next == u32dat_end);
+ VERIFY(memcmp((void*)buffer, (void*)u8dat, sizeof(u8dat)) == 0);
+
+ delete[]buffer;
+ }
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
--
1.9.2