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_MESSAGES_H
10#define _LIBCPP___LOCALE_DIR_MESSAGES_H
11
12#include <__config>
13#include <__iterator/back_insert_iterator.h>
14#include <__locale_dir/locale.h>
15#include <__locale_dir/utf8_conversions.h>
16#include <string>
17
18#if _LIBCPP_HAS_LOCALIZATION
19
20# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21# pragma GCC system_header
22# endif
23
24# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
25// Most unix variants have catopen. These are the specific ones that don't.
26# if !defined(__BIONIC__) && !_LIBCPP_LIBC_NEWLIB && !defined(__EMSCRIPTEN__)
27# define _LIBCPP_HAS_CATOPEN 1
28# include <nl_types.h>
29# else
30# define _LIBCPP_HAS_CATOPEN 0
31# endif
32# else
33# define _LIBCPP_HAS_CATOPEN 0
34# endif
35
36_LIBCPP_BEGIN_NAMESPACE_STD
37_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
38
39class _LIBCPP_EXPORTED_FROM_ABI messages_base {
40public:
41 typedef intptr_t catalog;
42
43 _LIBCPP_HIDE_FROM_ABI messages_base() {}
44};
45
46template <class _CharT>
47class messages : public locale::facet, public messages_base {
48public:
49 typedef _CharT char_type;
50 typedef basic_string<_CharT> string_type;
51
52 _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {}
53
54 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string<char>& __nm, const locale& __loc) const {
55 return do_open(__nm, __loc);
56 }
57
58 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI string_type
59 get(catalog __c, int __set, int __msgid, const string_type& __dflt) const {
60 return do_get(__c, __set, __msgid, __dflt);
61 }
62
63 _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); }
64
65 static locale::id id;
66
67protected:
68 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {}
69
70 virtual catalog do_open(const basic_string<char>&, const locale&) const;
71 virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const;
72 virtual void do_close(catalog) const;
73};
74
75template <class _CharT>
76locale::id messages<_CharT>::id;
77
78template <class _CharT>
79typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const {
80# if _LIBCPP_HAS_CATOPEN
81 return (catalog)catopen(cat_name: __nm.c_str(), NL_CAT_LOCALE);
82# else // !_LIBCPP_HAS_CATOPEN
83 (void)__nm;
84 return -1;
85# endif // _LIBCPP_HAS_CATOPEN
86}
87
88template <class _CharT>
89typename messages<_CharT>::string_type
90messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const {
91# if _LIBCPP_HAS_CATOPEN
92 string __ndflt;
93 __narrow_to_utf8<sizeof(char_type) * __CHAR_BIT__>()(
94 std::back_inserter(x&: __ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size());
95 nl_catd __cat = (nl_catd)__c;
96 static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type");
97 char* __n = catgets(catalog: __cat, __set, number: __msgid, string: __ndflt.c_str());
98 string_type __w;
99 __widen_from_utf8<sizeof(char_type) * __CHAR_BIT__>()(std::back_inserter(__w), __n, __n + std::strlen(s: __n));
100 return __w;
101# else // !_LIBCPP_HAS_CATOPEN
102 (void)__c;
103 (void)__set;
104 (void)__msgid;
105 return __dflt;
106# endif // _LIBCPP_HAS_CATOPEN
107}
108
109template <class _CharT>
110void messages<_CharT>::do_close(catalog __c) const {
111# if _LIBCPP_HAS_CATOPEN
112 catclose(catalog: (nl_catd)__c);
113# else // !_LIBCPP_HAS_CATOPEN
114 (void)__c;
115# endif // _LIBCPP_HAS_CATOPEN
116}
117
118extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>;
119# if _LIBCPP_HAS_WIDE_CHARACTERS
120extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>;
121# endif
122
123template <class _CharT>
124class messages_byname : public messages<_CharT> {
125public:
126 typedef messages_base::catalog catalog;
127 typedef basic_string<_CharT> string_type;
128
129 _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {}
130
131 _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {}
132
133protected:
134 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {}
135};
136
137extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>;
138# if _LIBCPP_HAS_WIDE_CHARACTERS
139extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>;
140# endif
141
142_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
143_LIBCPP_END_NAMESPACE_STD
144
145#endif // _LIBCPP_HAS_LOCALIZATION
146
147#endif // _LIBCPP___LOCALE_DIR_MESSAGES_H
148