1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___LOCALE_DIR_LOCALE_H
10#define _LIBCPP___LOCALE_DIR_LOCALE_H
11
12#include <__config>
13
14#if _LIBCPP_HAS_LOCALIZATION
15
16# include <__configuration/availability.h>
17# include <__cstddef/size_t.h>
18# include <__fwd/ios.h>
19# include <__locale_dir/locale_base_api.h>
20# include <__memory/addressof.h>
21# include <__memory/shared_count.h>
22# include <__utility/no_destroy.h>
23# include <__utility/private_constructor_tag.h>
24# include <__utility/swap.h>
25# include <cstdint>
26# include <stdexcept>
27# include <string>
28# include <text_encoding>
29
30// Some platforms require more includes than others. Keep the includes on all platforms for now.
31# include <clocale>
32# include <cstddef>
33# include <cstdlib>
34# include <cstring>
35
36# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
37# pragma GCC system_header
38# endif
39
40_LIBCPP_BEGIN_NAMESPACE_STD
41_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
42
43class _LIBCPP_EXPORTED_FROM_ABI locale;
44
45template <class _CharT>
46class collate;
47
48template <class _Facet>
49_LIBCPP_HIDE_FROM_ABI bool has_facet(const locale&) _NOEXCEPT;
50
51template <class _Facet>
52_LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&);
53
54class _LIBCPP_EXPORTED_FROM_ABI locale {
55public:
56 // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor,
57 // so it is trivially relocatable.
58 using __trivially_relocatable _LIBCPP_NODEBUG = locale;
59
60 // types:
61 class _LIBCPP_EXPORTED_FROM_ABI facet;
62 class _LIBCPP_EXPORTED_FROM_ABI id;
63
64 typedef int category;
65
66 static const category // values assigned here are for exposition only
67 none = 0,
68 collate = _LIBCPP_COLLATE_MASK, ctype = _LIBCPP_CTYPE_MASK, monetary = _LIBCPP_MONETARY_MASK,
69 numeric = _LIBCPP_NUMERIC_MASK, time = _LIBCPP_TIME_MASK, messages = _LIBCPP_MESSAGES_MASK,
70 all = collate | ctype | monetary | numeric | time | messages;
71
72 // construct/copy/destroy:
73 locale() _NOEXCEPT;
74 locale(const locale&) _NOEXCEPT;
75 explicit locale(const char*);
76 explicit locale(const string&);
77 locale(const locale&, const char*, category);
78 locale(const locale&, const string&, category);
79 template <class _Facet>
80 _LIBCPP_HIDE_FROM_ABI locale(const locale&, _Facet*);
81 locale(const locale&, const locale&, category);
82
83 ~locale();
84
85 const locale& operator=(const locale&) _NOEXCEPT;
86
87 template <class _Facet>
88 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI locale combine(const locale& __other) const {
89 if (!std::has_facet<_Facet>(__other))
90 __throw_runtime_error("locale::combine: locale missing facet");
91
92 return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other))));
93 }
94
95 // locale operations:
96 [[__nodiscard__]] string name() const;
97 bool operator==(const locale&) const;
98# if _LIBCPP_STD_VER <= 17
99 _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); }
100# endif
101 template <class _CharT, class _Traits, class _Allocator>
102 [[__nodiscard__]]
103 _LIBCPP_HIDE_FROM_ABI bool operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
104 const basic_string<_CharT, _Traits, _Allocator>& __y) const {
105 return std::use_facet<std::collate<_CharT> >(*this).compare(
106 __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0;
107 }
108# if _LIBCPP_STD_VER >= 26
109 [[nodiscard]] _LIBCPP_AVAILABILITY_TEXT_ENCODING_ENVIRONMENT
110 _LIBCPP_HIDE_FROM_ABI std::text_encoding encoding() const {
111 std::string __name = name();
112 return std::__get_locale_encoding(name: __name.c_str());
113 }
114# endif
115
116 // global locale objects:
117 static locale global(const locale&);
118 [[__nodiscard__]] static const locale& classic();
119
120private:
121 class __imp;
122 __imp* __locale_;
123
124 template <class>
125 friend struct __no_destroy;
126
127 friend ios_base;
128
129 _LIBCPP_HIDE_FROM_ABI explicit locale(__private_constructor_tag, __imp* __loc) : __locale_(__loc) {}
130
131 void __install_ctor(const locale&, facet*, long);
132 static locale& __global();
133 bool has_facet(id&) const;
134 const facet* use_facet(id&) const;
135
136 template <class _Facet>
137 friend bool has_facet(const locale&) _NOEXCEPT;
138 template <class _Facet>
139 friend const _Facet& use_facet(const locale&);
140
141 _LIBCPP_HIDE_FROM_ABI friend void swap(locale&, locale&) _NOEXCEPT;
142};
143
144_LIBCPP_HIDE_FROM_ABI inline void swap(locale& __lhs, locale& __rhs) _NOEXCEPT {
145 std::swap(x&: __lhs.__locale_, y&: __rhs.__locale_);
146}
147
148class _LIBCPP_EXPORTED_FROM_ABI locale::facet : public __shared_count {
149protected:
150 _LIBCPP_HIDE_FROM_ABI explicit facet(size_t __refs = 0) : __shared_count(static_cast<long>(__refs) - 1) {}
151
152 ~facet() override;
153
154 // facet(const facet&) = delete; // effectively done in __shared_count
155 // void operator=(const facet&) = delete;
156
157private:
158 void __on_zero_shared() _NOEXCEPT override;
159};
160
161class _LIBCPP_EXPORTED_FROM_ABI locale::id {
162# ifdef _LIBCPP_ABI_COMPACT_LOCALE_ID
163 using __id_type _LIBCPP_NODEBUG = int32_t;
164# else
165 using __id_type _LIBCPP_NODEBUG = uintptr_t;
166# endif
167
168 __id_type __id_ = 0;
169
170# ifndef _LIBCPP_ABI_COMPACT_LOCALE_ID
171 [[__maybe_unused__]] int32_t __dummy_ = 0;
172# endif
173
174public:
175 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR id() = default;
176 void operator=(const id&) = delete;
177 id(const id&) = delete;
178
179public: // only needed for tests
180 long __get();
181
182 friend class locale;
183 friend class locale::__imp;
184};
185
186template <class _Facet>
187inline _LIBCPP_HIDE_FROM_ABI locale::locale(const locale& __other, _Facet* __f) {
188 __install_ctor(__other, __f, __f ? __f->id.__get() : 0);
189}
190
191template <class _Facet>
192[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale& __l) _NOEXCEPT {
193 return __l.has_facet(_Facet::id);
194}
195
196template <class _Facet>
197[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale& __l) {
198 return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
199}
200
201_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
202_LIBCPP_END_NAMESPACE_STD
203
204#endif // _LIBCPP_HAS_LOCALIZATION
205
206#endif // _LIBCPP___LOCALE_DIR_LOCALE_H
207