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