chromium/third_party/libc++/src/include/__filesystem/path.h

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___FILESYSTEM_PATH_H
#define _LIBCPP___FILESYSTEM_PATH_H

#include <__algorithm/replace.h>
#include <__algorithm/replace_copy.h>
#include <__config>
#include <__functional/unary_function.h>
#include <__fwd/functional.h>
#include <__iterator/back_insert_iterator.h>
#include <__iterator/iterator_traits.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_pointer.h>
#include <__type_traits/remove_const.h>
#include <__type_traits/remove_pointer.h>
#include <cstddef>
#include <string>
#include <string_view>

#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
#  include <iomanip> // for quoted
#  include <locale>
#endif

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#  pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM

_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH

template <class _Tp>
struct __can_convert_char {};
__can_convert_char<const _Tp>;
template <>
struct __can_convert_char<char> {};
template <>
struct __can_convert_char<wchar_t> {};
#  ifndef _LIBCPP_HAS_NO_CHAR8_T
template <>
struct __can_convert_char<char8_t> {};
#  endif
template <>
struct __can_convert_char<char16_t> {};
template <>
struct __can_convert_char<char32_t> {};

template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI bool __is_separator(_ECharT __e) {}

#  ifndef _LIBCPP_HAS_NO_CHAR8_T
__u8_string;
#  else
typedef string __u8_string;
#  endif

struct _NullSentinel {};

_Void;

template <class _Tp, class = void>
struct __is_pathable_string : public false_type {};

__is_pathable_string<basic_string<_ECharT, _Traits, _Alloc>, _Void<typename __can_convert_char<_ECharT>::__char_type>>;

__is_pathable_string<basic_string_view<_ECharT, _Traits>, _Void<typename __can_convert_char<_ECharT>::__char_type>>;

template <class _Source,
          class _DS            = __decay_t<_Source>,
          class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >,
          bool _IsCharPtr      = is_pointer<_DS>::value && __can_convert_char<_UnqualPtrType>::value>
struct __is_pathable_char_array : false_type {};

__is_pathable_char_array<_Source, _ECharT *, _UPtr, true>;

template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void>
struct __is_pathable_iter : false_type {};

__is_pathable_iter<_Iter, true, _Void<typename __can_convert_char<typename iterator_traits<_Iter>::value_type>::__char_type>>;

template <class _Tp,
          bool _IsStringT   = __is_pathable_string<_Tp>::value,
          bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
          bool _IsIterT     = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
struct __is_pathable : false_type {};

__is_pathable<_Tp, true, false, false>;

__is_pathable<_Tp, false, true, false>;

__is_pathable<_Tp, false, false, true>;

#  if defined(_LIBCPP_WIN32API)
typedef wstring __path_string;
typedef wchar_t __path_value;
#  else
__path_string;
__path_value;
#  endif

#  if defined(_LIBCPP_WIN32API)
_LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t);
_LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t);
#  endif

template <class _ECharT>
struct _PathCVT;

#  if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
template <class _ECharT>
struct _PathCVT {};
#  endif // !_LIBCPP_HAS_NO_LOCALIZATION

template <>
struct _PathCVT<__path_value> {};

#  if defined(_LIBCPP_WIN32API)
template <>
struct _PathCVT<char> {
  _LIBCPP_HIDE_FROM_ABI static void __append_string(__path_string& __dest, const basic_string<char>& __str) {
    size_t __size = __char_to_wide(__str, nullptr, 0);
    size_t __pos  = __dest.size();
    __dest.resize(__pos + __size);
    __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
  }

  template <class _Iter, __enable_if_t<__has_exactly_input_iterator_category<_Iter>::value, int> = 0>
  _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
    basic_string<char> __tmp(__b, __e);
    __append_string(__dest, __tmp);
  }

  template <class _Iter, __enable_if_t<__has_forward_iterator_category<_Iter>::value, int> = 0>
  _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
    basic_string<char> __tmp(__b, __e);
    __append_string(__dest, __tmp);
  }

  template <class _Iter>
  _LIBCPP_HIDE_FROM_ABI static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
    const char __sentinel = char{};
    basic_string<char> __tmp;
    for (; *__b != __sentinel; ++__b)
      __tmp.push_back(*__b);
    __append_string(__dest, __tmp);
  }

  template <class _Source>
  _LIBCPP_HIDE_FROM_ABI static void __append_source(__path_string& __dest, _Source const& __s) {
    using _Traits = __is_pathable<_Source>;
    __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
  }
};

template <class _ECharT>
struct _PathExport {
  typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
  typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;

  template <class _Str>
  _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
    string __utf8;
    _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
    _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
  }
};

template <>
struct _PathExport<char> {
  template <class _Str>
  _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
    size_t __size = __wide_to_char(__src, nullptr, 0);
    size_t __pos  = __dest.size();
    __dest.resize(__size);
    __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
  }
};

template <>
struct _PathExport<wchar_t> {
  template <class _Str>
  _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
    __dest.append(__src.begin(), __src.end());
  }
};

template <>
struct _PathExport<char16_t> {
  template <class _Str>
  _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
    __dest.append(__src.begin(), __src.end());
  }
};

#    ifndef _LIBCPP_HAS_NO_CHAR8_T
template <>
struct _PathExport<char8_t> {
  typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;

  template <class _Str>
  _LIBCPP_HIDE_FROM_ABI static void __append(_Str& __dest, const __path_string& __src) {
    _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
  }
};
#    endif /* !_LIBCPP_HAS_NO_CHAR8_T */
#  endif   /* _LIBCPP_WIN32API */

class _LIBCPP_EXPORTED_FROM_ABI path {};

inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept {}

_LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept;

_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP

_LIBCPP_END_NAMESPACE_FILESYSTEM

_LIBCPP_BEGIN_NAMESPACE_STD

template <>
struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<filesystem::path> : __unary_function<filesystem::path, size_t> {};

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 17

_LIBCPP_POP_MACROS

#endif // _LIBCPP___FILESYSTEM_PATH_H