brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · 42a56eb Raw
255 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H10#define _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H11 12#include <__config>13#include <__locale>14#include <__memory/allocator.h>15#include <string>16 17#if _LIBCPP_HAS_LOCALIZATION18 19#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)20#    pragma GCC system_header21#  endif22 23#  if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT)24 25_LIBCPP_PUSH_MACROS26#    include <__undef_macros>27 28_LIBCPP_BEGIN_NAMESPACE_STD29 30template <class _Codecvt,31          class _Elem      = wchar_t,32          class _WideAlloc = allocator<_Elem>,33          class _ByteAlloc = allocator<char> >34class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert {35public:36  typedef basic_string<char, char_traits<char>, _ByteAlloc> byte_string;37  typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string;38  typedef typename _Codecvt::state_type state_type;39  typedef typename wide_string::traits_type::int_type int_type;40 41private:42  byte_string __byte_err_string_;43  wide_string __wide_err_string_;44  _Codecvt* __cvtptr_;45  state_type __cvtstate_;46  size_t __cvtcount_;47 48public:49#    ifndef _LIBCPP_CXX03_LANG50  _LIBCPP_HIDE_FROM_ABI wstring_convert() : wstring_convert(new _Codecvt) {}51  _LIBCPP_HIDE_FROM_ABI explicit wstring_convert(_Codecvt* __pcvt);52#    else53  _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt);54#    endif55 56  _LIBCPP_HIDE_FROM_ABI wstring_convert(_Codecvt* __pcvt, state_type __state);57  _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI58  wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string());59#    ifndef _LIBCPP_CXX03_LANG60  _LIBCPP_HIDE_FROM_ABI wstring_convert(wstring_convert&& __wc);61#    endif62  _LIBCPP_HIDE_FROM_ABI ~wstring_convert();63 64  wstring_convert(const wstring_convert& __wc)            = delete;65  wstring_convert& operator=(const wstring_convert& __wc) = delete;66 67  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); }68  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) {69    return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));70  }71  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) {72    return from_bytes(__str.data(), __str.data() + __str.size());73  }74  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last);75 76  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) {77    return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1);78  }79  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) {80    return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));81  }82  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) {83    return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());84  }85  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last);86 87  _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; }88  _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; }89};90 91_LIBCPP_SUPPRESS_DEPRECATED_PUSH92template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>93inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt)94    : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) {}95_LIBCPP_SUPPRESS_DEPRECATED_POP96 97template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>98inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt, state_type __state)99    : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) {}100 101template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>102wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(103    const byte_string& __byte_err, const wide_string& __wide_err)104    : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) {105  __cvtptr_ = new _Codecvt;106}107 108#    ifndef _LIBCPP_CXX03_LANG109 110template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>111inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(wstring_convert&& __wc)112    : __byte_err_string_(std::move(__wc.__byte_err_string_)),113      __wide_err_string_(std::move(__wc.__wide_err_string_)),114      __cvtptr_(__wc.__cvtptr_),115      __cvtstate_(__wc.__cvtstate_),116      __cvtcount_(__wc.__cvtcount_) {117  __wc.__cvtptr_ = nullptr;118}119 120#    endif // _LIBCPP_CXX03_LANG121 122_LIBCPP_SUPPRESS_DEPRECATED_PUSH123template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>124wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() {125  delete __cvtptr_;126}127 128template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>129typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string130wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::from_bytes(const char* __frm, const char* __frm_end) {131  _LIBCPP_SUPPRESS_DEPRECATED_POP132  __cvtcount_ = 0;133  if (__cvtptr_ != nullptr) {134    wide_string __ws(2 * (__frm_end - __frm), _Elem());135    if (__frm != __frm_end)136      __ws.resize(__ws.capacity());137    codecvt_base::result __r = codecvt_base::ok;138    state_type __st          = __cvtstate_;139    if (__frm != __frm_end) {140      _Elem* __to     = std::addressof(__ws[0]);141      _Elem* __to_end = __to + __ws.size();142      const char* __frm_nxt;143      do {144        _Elem* __to_nxt;145        __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);146        __cvtcount_ += __frm_nxt - __frm;147        if (__frm_nxt == __frm) {148          __r = codecvt_base::error;149        } else if (__r == codecvt_base::noconv) {150          __ws.resize(__to - std::addressof(__ws[0]));151          // This only gets executed if _Elem is char152          __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);153          __frm = __frm_nxt;154          __r   = codecvt_base::ok;155        } else if (__r == codecvt_base::ok) {156          __ws.resize(__to_nxt - std::addressof(__ws[0]));157          __frm = __frm_nxt;158        } else if (__r == codecvt_base::partial) {159          ptrdiff_t __s = __to_nxt - std::addressof(__ws[0]);160          __ws.resize(2 * __s);161          __to     = std::addressof(__ws[0]) + __s;162          __to_end = std::addressof(__ws[0]) + __ws.size();163          __frm    = __frm_nxt;164        }165      } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);166    }167    if (__r == codecvt_base::ok)168      return __ws;169  }170 171  if (__wide_err_string_.empty())172    std::__throw_range_error("wstring_convert: from_bytes error");173 174  return __wide_err_string_;175}176 177template <class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc>178typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string179wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::to_bytes(const _Elem* __frm, const _Elem* __frm_end) {180  __cvtcount_ = 0;181  if (__cvtptr_ != nullptr) {182    byte_string __bs(2 * (__frm_end - __frm), char());183    if (__frm != __frm_end)184      __bs.resize(__bs.capacity());185    codecvt_base::result __r = codecvt_base::ok;186    state_type __st          = __cvtstate_;187    if (__frm != __frm_end) {188      char* __to     = std::addressof(__bs[0]);189      char* __to_end = __to + __bs.size();190      const _Elem* __frm_nxt;191      do {192        char* __to_nxt;193        __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);194        __cvtcount_ += __frm_nxt - __frm;195        if (__frm_nxt == __frm) {196          __r = codecvt_base::error;197        } else if (__r == codecvt_base::noconv) {198          __bs.resize(__to - std::addressof(__bs[0]));199          // This only gets executed if _Elem is char200          __bs.append((const char*)__frm, (const char*)__frm_end);201          __frm = __frm_nxt;202          __r   = codecvt_base::ok;203        } else if (__r == codecvt_base::ok) {204          __bs.resize(__to_nxt - std::addressof(__bs[0]));205          __frm = __frm_nxt;206        } else if (__r == codecvt_base::partial) {207          ptrdiff_t __s = __to_nxt - std::addressof(__bs[0]);208          __bs.resize(2 * __s);209          __to     = std::addressof(__bs[0]) + __s;210          __to_end = std::addressof(__bs[0]) + __bs.size();211          __frm    = __frm_nxt;212        }213      } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);214    }215    if (__r == codecvt_base::ok) {216      size_t __s = __bs.size();217      __bs.resize(__bs.capacity());218      char* __to     = std::addressof(__bs[0]) + __s;219      char* __to_end = __to + __bs.size();220      do {221        char* __to_nxt;222        __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);223        if (__r == codecvt_base::noconv) {224          __bs.resize(__to - std::addressof(__bs[0]));225          __r = codecvt_base::ok;226        } else if (__r == codecvt_base::ok) {227          __bs.resize(__to_nxt - std::addressof(__bs[0]));228        } else if (__r == codecvt_base::partial) {229          ptrdiff_t __sp = __to_nxt - std::addressof(__bs[0]);230          __bs.resize(2 * __sp);231          __to     = std::addressof(__bs[0]) + __sp;232          __to_end = std::addressof(__bs[0]) + __bs.size();233        }234      } while (__r == codecvt_base::partial);235      if (__r == codecvt_base::ok)236        return __bs;237    }238  }239 240  if (__byte_err_string_.empty())241    std::__throw_range_error("wstring_convert: to_bytes error");242 243  return __byte_err_string_;244}245 246_LIBCPP_END_NAMESPACE_STD247 248_LIBCPP_POP_MACROS249 250#  endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT)251 252#endif // _LIBCPP_HAS_LOCALIZATION253 254#endif // _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H255