97 lines
2.8 KiB
C++
97 lines
2.8 KiB
C++
#ifndef YERBACON_HPP
|
|
#define YERBACON_HPP
|
|
|
|
#ifndef YBCON_VERSION
|
|
#warning "YBCON_VERSION is unknown and will therefore be set to a default value"
|
|
#define YBCON_VERSION "UNKNOWN"
|
|
#endif
|
|
|
|
#ifndef YBCON_FLAGS
|
|
#define YBCON_FLAGS "none"
|
|
#endif
|
|
|
|
#ifndef YBCON_COMPILER
|
|
#define YBCON_COMPILER "unknown"
|
|
#endif
|
|
|
|
#ifdef __STDC_NO_THREADS__
|
|
#error "A valid std::threads implementation is required"
|
|
#endif
|
|
|
|
#include <version>
|
|
#if not defined(__cpp_lib_concepts) || not defined(__cpp_lib_integer_comparison_functions)
|
|
#error "The current standard library is incomplete"
|
|
#endif
|
|
|
|
#define token_expansion(X) #X
|
|
#define make_string(X) token_expansion(X)
|
|
|
|
#include <exception>
|
|
#include <string_view>
|
|
#include <string>
|
|
#include <optional>
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#ifdef EMSCRIPTEN
|
|
#include <emscripten.h>
|
|
static bool is_node;
|
|
void emscripten_exit(int status) {
|
|
MAIN_THREAD_EM_ASM("yerbacon_output = Module.get_cout();");
|
|
if (not is_node) emscripten_exit_with_live_runtime();
|
|
std::exit(status);
|
|
}
|
|
#define exit(status) emscripten_exit(status)
|
|
#include <sstream>
|
|
static std::ostringstream string_cout;
|
|
#define cout (is_node ? std::cout : string_cout)
|
|
#define cerr (is_node ? std::cerr : string_cout)
|
|
std::string get_cout() {
|
|
static size_t previous_cout_size = 0;
|
|
std::string output = string_cout.str();
|
|
const size_t current_size = output.size();
|
|
output = output.substr(previous_cout_size, current_size);
|
|
previous_cout_size = current_size;
|
|
return output;
|
|
}
|
|
#include <emscripten/bind.h>
|
|
EMSCRIPTEN_BINDINGS() {
|
|
emscripten::function("get_cout", &get_cout);
|
|
}
|
|
#else
|
|
using std::exit;
|
|
using std::cout;
|
|
#endif
|
|
|
|
namespace Yerbacon {
|
|
consteval const char* getVersion() noexcept { return YBCON_VERSION; }
|
|
consteval const char* getBuildInfo() noexcept { return
|
|
"Build info:\n"
|
|
" Optimization flags: " YBCON_FLAGS "\n"
|
|
" Compiler: " YBCON_COMPILER "\n"
|
|
" C++ standard: " make_string(__cplusplus);
|
|
}
|
|
static void fail(const std::initializer_list<const char*> reason) {
|
|
std::for_each(reason.begin(), reason.end(), [](const char* current_string){
|
|
cout << current_string;
|
|
});
|
|
cout << std::endl;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
inline void fail(const char* reason) { fail({reason}); }
|
|
class Exception: public std::exception {
|
|
std::string exceptionCause;
|
|
public:
|
|
[[nodiscard]] const char* what() const noexcept final {
|
|
return exceptionCause.data();
|
|
}
|
|
explicit Exception(const std::string_view& cause): exceptionCause(cause) {
|
|
if (!cause.ends_with('\n')) exceptionCause += '\n';
|
|
}
|
|
Exception(const std::string_view& cause, unsigned long line): Exception(('L' + std::to_string(line) + ": ").append(cause)) {}
|
|
};
|
|
}
|
|
|
|
#undef YBCON_VERSION
|
|
#undef YBCON_FLAGS
|
|
#undef YBCON_COMPILER
|
|
#endif |