harfang3d/harfang/foundation/rw_interface.h

135 lines
3.4 KiB
C
Raw Normal View History

2021-10-13 12:40:31 +00:00
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#pragma once
#include "foundation/assert.h"
#include "foundation/seek_mode.h"
#include <cassert>
#include <cstddef>
#include <string>
namespace hg {
#ifndef NDEBUG
#define ENABLE_BINARY_DEBUG_HANDLE
#endif
struct Handle { // 16 bytes
uint32_t v[4];
#ifdef ENABLE_BINARY_DEBUG_HANDLE
bool debug{false};
#endif
};
struct Reader {
size_t (*read)(Handle h, void *data, size_t size);
size_t (*size)(Handle h);
bool (*seek)(Handle h, ptrdiff_t offset, SeekMode mode);
size_t (*tell)(Handle h);
bool (*is_valid)(Handle h);
bool (*is_eof)(Handle h);
};
struct Writer {
size_t (*write)(Handle h, const void *data, size_t size);
bool (*is_valid)(Handle hnd);
};
//
#ifdef ENABLE_BINARY_DEBUG_HANDLE
template <typename T> bool Read(const Reader &i, const Handle &h, T &v) {
if (h.debug) {
uint16_t _check;
if (i.read(h, &_check, sizeof(uint16_t)) != sizeof(uint16_t))
return false;
assert(_check == sizeof(T));
}
return i.read(h, &v, sizeof(T)) == sizeof(T);
}
template <typename T> bool Write(const Writer &i, const Handle &h, const T &v) {
if (h.debug) {
uint16_t _check = sizeof(T);
if (i.write(h, &_check, sizeof(uint16_t)) != sizeof(uint16_t))
return false;
}
return i.write(h, &v, sizeof(T)) == sizeof(T);
}
#else
template <typename T> bool Read(const Reader &i, const Handle &h, T &v) { return i.read(h, &v, sizeof(T)) == sizeof(T); }
template <typename T> bool Write(const Writer &i, const Handle &h, const T &v) { return i.write(h, &v, sizeof(T)) == sizeof(T); }
#endif
//
bool Read(const Reader &i, const Handle &h, std::string &v);
bool Write(const Writer &i, const Handle &h, const std::string &v);
//
bool Seek(const Reader &i, const Handle &h, ptrdiff_t offset, SeekMode mode);
//
template <typename T> T Read(const Reader &i, const Handle &h) {
T v;
bool r = Read(i, h, v);
__ASSERT__(r == true);
return v;
}
template <typename T> bool Skip(const Reader &i, const Handle &h) { return Seek(i, h, sizeof(T), SM_Current); }
bool SkipString(const Reader &i, const Handle &h);
//
struct ReadProvider {
Handle (*open)(const char *path, bool silent);
void (*close)(Handle hnd);
bool (*is_file)(const char *path);
};
bool Exists(const Reader &ir, const ReadProvider &i, const char *path);
struct WriteProvider {
Handle (*open)(const char *path);
void (*close)(Handle hnd);
};
//
struct ScopedReadHandle {
#ifdef ENABLE_BINARY_DEBUG_HANDLE
ScopedReadHandle(ReadProvider i, const char *path, bool silent = false, bool debug = false) : i_(i), h_(i.open(path, silent)) { h_.debug = debug; }
#else
ScopedReadHandle(ReadProvider i, const char *path, bool silent = false) : i_(i), h_(i.open(path, silent)) {}
#endif
~ScopedReadHandle() { i_.close(h_); }
operator const Handle &() const { return h_; }
private:
Handle h_;
ReadProvider i_;
};
struct ScopedWriteHandle {
#ifdef ENABLE_BINARY_DEBUG_HANDLE
ScopedWriteHandle(WriteProvider i, const char *path, bool debug = false) : i_(i), h_(i.open(path)) { h_.debug = debug; }
#else
ScopedWriteHandle(WriteProvider i, const char *path) : i_(i), h_(i.open(path)) {}
#endif
~ScopedWriteHandle() { i_.close(h_); }
operator const Handle &() const { return h_; }
private:
Handle h_;
WriteProvider i_;
};
//
class Data;
Data LoadData(const Reader &i, const Handle &h);
std::string LoadString(const Reader &i, const Handle &h);
} // namespace hg