// SPDX-License-Identifier: 0BSD


#pragma once


#include <cstdio>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utility>

#ifndef O_PATH
#define O_PATH O_RDONLY
#endif


namespace vore {
	namespace {
		class fd {
		public:
			constexpr fd() noexcept = default;
			fd(const char * path, int flags, mode_t mode = 0, int from = AT_FDCWD) noexcept {
				while((this->desc = openat(from, path, flags, mode)) == -1 && errno == EINTR)
					;
				this->opened = this->desc != -1;
			}
			fd(int desc) noexcept : desc(desc), opened(desc != -1) {}

			fd(const fd &) = delete;
			constexpr fd(fd && oth) noexcept { *this = std::move(oth); }

			constexpr fd & operator=(fd && oth) noexcept {
				this->swap(oth);
				return *this;
			}

			~fd() {
				if(this->opened)
					close(this->desc);
			}

			constexpr operator int() const noexcept { return this->desc; }

			int take() noexcept {
				this->opened = false;
				return this->desc;
			}

			constexpr void swap(fd & oth) noexcept {
				std::swap(this->desc, oth.desc);
				std::swap(this->opened, oth.opened);
			}

		private:
			int desc = -1;

		public:
			bool opened = false;
		};
	}
}
