chromium/third_party/libc++/src/src/filesystem/directory_iterator.cpp

//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include <__assert>
#include <__config>
#include <errno.h>
#include <filesystem>
#include <stack>
#include <utility>

#include "error.h"
#include "file_descriptor.h"

#if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#  include <windows.h>
#else
#  include <dirent.h> // for DIR & friends
#endif

_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM

ErrorHandler;

#if defined(_LIBCPP_WIN32API)
class __dir_stream {
public:
  __dir_stream()                               = delete;
  __dir_stream& operator=(const __dir_stream&) = delete;

  __dir_stream(__dir_stream&& __ds) noexcept
      : __stream_(__ds.__stream_), __root_(std::move(__ds.__root_)), __entry_(std::move(__ds.__entry_)) {
    __ds.__stream_ = INVALID_HANDLE_VALUE;
  }

  __dir_stream(const path& root, directory_options opts, error_code& ec)
      : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
    if (root.native().empty()) {
      ec = make_error_code(errc::no_such_file_or_directory);
      return;
    }
    __stream_ = ::FindFirstFileW((root / "*").c_str(), &__data_);
    if (__stream_ == INVALID_HANDLE_VALUE) {
      ec                                  = detail::make_windows_error(GetLastError());
      const bool ignore_permission_denied = bool(opts & directory_options::skip_permission_denied);
      if (ignore_permission_denied && ec.value() == static_cast<int>(errc::permission_denied))
        ec.clear();
      return;
    }
    if (!assign())
      advance(ec);
  }

  ~__dir_stream() noexcept {
    if (__stream_ == INVALID_HANDLE_VALUE)
      return;
    close();
  }

  bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }

  bool advance(error_code& ec) {
    while (::FindNextFileW(__stream_, &__data_)) {
      if (assign())
        return true;
    }
    close();
    return false;
  }

  bool assign() {
    if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L".."))
      return false;
    // FIXME: Cache more of this
    // directory_entry::__cached_data cdata;
    // cdata.__type_ = get_file_type(__data_);
    // cdata.__size_ = get_file_size(__data_);
    // cdata.__write_time_ = get_write_time(__data_);
    __entry_.__assign_iter_entry(
        __root_ / __data_.cFileName, directory_entry::__create_iter_result(detail::get_file_type(__data_)));
    return true;
  }

private:
  error_code close() noexcept {
    error_code ec;
    if (!::FindClose(__stream_))
      ec = detail::make_windows_error(GetLastError());
    __stream_ = INVALID_HANDLE_VALUE;
    return ec;
  }

  HANDLE __stream_{INVALID_HANDLE_VALUE};
  WIN32_FIND_DATAW __data_;

public:
  path __root_;
  directory_entry __entry_;
};
#else
class __dir_stream {};
#endif

// directory_iterator

directory_iterator::directory_iterator(const path& p, error_code* ec, directory_options opts) {}

directory_iterator& directory_iterator::__increment(error_code* ec) {}

directory_entry const& directory_iterator::__dereference() const {}

// recursive_directory_iterator

struct recursive_directory_iterator::__shared_imp {};

recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options opt, error_code* ec)
    :{}

void recursive_directory_iterator::__pop(error_code* ec) {}

directory_options recursive_directory_iterator::options() const {}

int recursive_directory_iterator::depth() const {}

const directory_entry& recursive_directory_iterator::__dereference() const {}

recursive_directory_iterator& recursive_directory_iterator::__increment(error_code* ec) {}

void recursive_directory_iterator::__advance(error_code* ec) {}

bool recursive_directory_iterator::__try_recursion(error_code* ec) {}

_LIBCPP_END_NAMESPACE_FILESYSTEM