xref: /freebsd/contrib/llvm-project/libcxx/include/__locale_dir/messages.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
37 class _LIBCPP_EXPORTED_FROM_ABI messages_base {
38 public:
39   typedef intptr_t catalog;
40 
messages_base()41   _LIBCPP_HIDE_FROM_ABI messages_base() {}
42 };
43 
44 template <class _CharT>
45 class messages : public locale::facet, public messages_base {
46 public:
47   typedef _CharT char_type;
48   typedef basic_string<_CharT> string_type;
49 
facet(__refs)50   _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {}
51 
open(const basic_string<char> & __nm,const locale & __loc)52   _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string<char>& __nm, const locale& __loc) const {
53     return do_open(__nm, __loc);
54   }
55 
get(catalog __c,int __set,int __msgid,const string_type & __dflt)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 
close(catalog __c)60   _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); }
61 
62   static locale::id id;
63 
64 protected:
~messages()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 
72 template <class _CharT>
73 locale::id messages<_CharT>::id;
74 
75 template <class _CharT>
do_open(const basic_string<char> & __nm,const locale &)76 typename 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 
85 template <class _CharT>
86 typename messages<_CharT>::string_type
do_get(catalog __c,int __set,int __msgid,const string_type & __dflt)87 messages<_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 
106 template <class _CharT>
do_close(catalog __c)107 void 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 
115 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>;
116 #  if _LIBCPP_HAS_WIDE_CHARACTERS
117 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>;
118 #  endif
119 
120 template <class _CharT>
121 class messages_byname : public messages<_CharT> {
122 public:
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 
130 protected:
~messages_byname()131   _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {}
132 };
133 
134 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>;
135 #  if _LIBCPP_HAS_WIDE_CHARACTERS
136 extern 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
144