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