/*
 * Copyright 2015 - 2022 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */


#ifdef OX_USE_STDLIB
#include <cstdio>

#include "array.hpp"
#include "reader.hpp"

namespace ox {

[[nodiscard]]
constexpr int sdMap(ox::ios_base::seekdir in) noexcept {
	switch (in) {
		case ox::ios_base::beg:
			return SEEK_SET;
		case ox::ios_base::end:
			return SEEK_END;
		case ox::ios_base::cur:
			return SEEK_CUR;
	}
	return -1;
}

ox::Result<char> FileReader::peek() const noexcept {
	auto const c = fgetc(m_file);
	auto const ok = c != EOF;
	if (ok && ungetc(c, m_file)) [[unlikely]] {
		return OxError(1, "Unable to unget character");
	}
	return {static_cast<char>(c), OxError(!ok, "File peek failed")};
}

ox::Result<std::size_t> FileReader::read(char *v, std::size_t cnt) noexcept {
	return fread(v, 1, cnt, m_file);
}

ox::Error FileReader::seekg(std::size_t p) noexcept {
	return OxError(fseek(m_file, static_cast<int64_t>(p), SEEK_CUR) != 0);
}

ox::Error FileReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
	return OxError(fseek(m_file, p, sdMap(sd)) != 0);
}

ox::Result<std::size_t> FileReader::tellg() noexcept {
	const auto sz = ftell(m_file);
	return {static_cast<std::size_t>(sz), OxError(sz == -1)};
}

}

#endif
