osuplusplus/include/config.hpp

197 lines
5.6 KiB
C++

#pragma once
#ifndef PP_DEBUG
#include <cinttypes>
#include <vector>
#include <SFML/Graphics/Color.hpp>
#endif
#include <util_stream_ops.hpp>
#include <string_util.hpp>
#include <va_args_util.hpp>
#define CONFIG(name, ...) \
struct name {\
__VA_ARGS__\
};
#define SECTION(name, type_name, ...) \
struct type_name {\
__VA_ARGS__\
} name;
#define SECTION_LIST(name, type) std::vector<type> name;
#define VAR_UINT(section, name) uint name;
#define VAR_UINT_P(section, name, prefix) VAR_UINT(section, name)
#define VAR_UINT_D(section, name, default) uint name = default;
#define VAR_INT(section, name) int name;
#define VAR_INT_P(section, name, prefix) VAR_INT(section, name)
#define VAR_INT_D(section, name, default) int name = default;
#define VAR_STRING(section, name) std::string name;
#define VAR_STRING_P(section, name, prefix) VAR_STRING(section, name)
#define VAR_STRING_D(section, name, default) std::string name = default;
#define VAR_BOOL(section, name) bool name;
#define VAR_BOOL_P(section, name, prefix) VAR_BOOL(section, name)
#define VAR_BOOL_D(section, name, default) bool name = default;
#define VAR_FLOAT(section, name) double name;
#define VAR_FLOAT_P(section, name, prefix) VAR_FLOAT(section, name)
#define VAR_FLOAT_D(section, name, default) double name = default;
#define VAR_COLOUR(section, name) sf::Color name;
#define VAR_COLOUR_P(section, name, prefix) VAR_COLOUR(section, name)
#define VAR_COLOUR_D(section, name, default) sf::Color name = default;
#define VAR_LIST(section, name, type) std::vector<type> name;
#define VAR_LIST_SEP(section, name, type, sep) std::vector<type> name;
#define VAR_LIST_SEP_P(section, name, type, sep, prefix) std::vector<type> name;
#define VAR_LIST_NUMBERED(section, name, type) std::vector<type> name;
#define ENUM(name, ...) \
enum class name {\
__VA_ARGS__\
};\
ENUM_STREAM_OPS(name, __VA_ARGS__)
#define VAR_ENUM(section, name, enum_type) enum_type name;
#define VAR_ENUM_P(section, name, prefix) VAR_ENUM(section, name)
#define VAR_ENUM_D(section, name, enum_type, default) enum_type name = enum_type::default;
#define ENUM_TO_STRING_CASE(name, e) case name::e: os << #e; break;
#define ENUM_FROM_STRING(name, e) if (input == #e) { en = name::e; hasBeenSet = true; }
#define ENUM_STREAM_OPS(name, ...) \
inline std::ostream &operator<<(std::ostream &os, const name &en) {\
switch (en) {\
FOR_EACH(ENUM_TO_STRING_CASE, name, __VA_ARGS__)\
}\
return os;\
}\
\
inline std::istream &operator>>(std::istream &is, name &en) {\
std::string input;\
is >> input;\
if (isInt(input)) {\
try {\
int inputNum = std::stoul(input);\
if (inputNum >= ARG_COUNT(__VA_ARGS__)) {\
/* TODO this and the comment below give me -Wmaybe-uninitialized
* which I would say is the expected outcome in this case
* but what do I know; find a way to silence the warning
* while still retaining this behaviour */\
is.setstate(std::ios_base::failbit);\
} else {\
en = static_cast<name>(inputNum);\
}\
} catch (std::invalid_argument const&) {\
/* the comment below */\
is.setstate(std::ios_base::failbit);\
}\
} else {\
toUpper(input);\
bool hasBeenSet = false;\
FOR_EACH(ENUM_FROM_STRING, name, __VA_ARGS__)\
if (!hasBeenSet) {\
is.setstate(std::ios_base::failbit);\
}\
}\
return is;\
}
#define STRUCT(name, ...) \
struct name {\
__VA_ARGS__\
};
#define VAR_STRUCT(section, name, struct_type) struct_type name;
#define VAR_STRUCT_P(section, name, prefix) VAR_STRUCT(section, name)
#define VAR_STRUCT_D(section, name, struct_type, default) struct_type name = default;
#define STRUCT_FIELD_TO_STRING(name, field) os << " " << #field << ": " << str.field << "\n";
#define STRUCT_FROM_STRING(name, field) \
std::getline(is, input, ',');\
ss = std::stringstream(input);\
ss >> str.field;
#define STRUCT_INPUT_STREAM_OP(name, ...) \
inline std::istream &operator>>(std::istream &is, name &str) {\
std::string input;\
std::stringstream ss;\
FOR_EACH(STRUCT_FROM_STRING, name, __VA_ARGS__)\
return is;\
}
#define STRUCT_OUTPUT_STREAM_OP(name, ...) \
inline std::ostream &operator<<(std::ostream &os, const name &str) {\
os << #name << " {\n";\
FOR_EACH(STRUCT_FIELD_TO_STRING, name, __VA_ARGS__)\
os << "}";\
return os;\
}
#define STRUCT_STREAM_OPS(name, ...) \
STRUCT_INPUT_STREAM_OP(name, __VA_ARGS__) \
STRUCT_OUTPUT_STREAM_OP(name, __VA_ARGS__)
#include <config_def.hpp>
#undef CONFIG
#undef SECTION
#undef SECTION_LIST
#undef VAR_UINT
#undef VAR_UINT_P
#undef VAR_UINT_D
#undef VAR_INT
#undef VAR_INT_P
#undef VAR_INT_D
#undef VAR_STRING
#undef VAR_STRING_P
#undef VAR_STRING_D
#undef VAR_BOOL
#undef VAR_BOOL_P
#undef VAR_BOOL_D
#undef VAR_FLOAT
#undef VAR_FLOAT_P
#undef VAR_FLOAT_D
#undef VAR_COLOUR
#undef VAR_COLOUR_P
#undef VAR_COLOUR_D
#undef ENUM
#undef VAR_ENUM
#undef VAR_ENUM_P
#undef VAR_ENUM_D
#undef ENUM_TO_STRING_CASE
#undef ENUM_FROM_STRING
#undef ENUM_STREAM_OPS
#undef STRUCT
#undef VAR_STRUCT
#undef VAR_STRUCT_P
#undef VAR_STRUCT_D
#undef STRUCT_FIELD_TO_STRING
#undef STRUCT_FROM_STRING
#undef STRUCT_INPUT_STREAM_OP
#undef STRUCT_OUTPUT_STREAM_OP
#undef STRUCT_STREAM_OPS
#undef VAR_LIST
#undef VAR_LIST_SEP
#undef VAR_LIST_SEP_P
#undef VAR_LIST_NUMBERED