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