...
This commit is contained in:
124
mcc_error.h
Normal file
124
mcc_error.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* MOUNT CONTROL COMPONENTS LIBRARY *
|
||||
* *
|
||||
* *
|
||||
* IMPLEMENTATION OF OPERATIONAL ERROR *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <format>
|
||||
#include <sstream>
|
||||
#include <system_error>
|
||||
|
||||
#include "mcc_concepts.h"
|
||||
|
||||
namespace mcc::impl
|
||||
{
|
||||
|
||||
typedef std::error_code MccError; // library-wide definition of operational error
|
||||
|
||||
} // namespace mcc::impl
|
||||
|
||||
template <>
|
||||
struct std::formatter<mcc::impl::MccError, char> {
|
||||
template <class ParseContext>
|
||||
constexpr ParseContext::iterator parse(ParseContext& ctx)
|
||||
{
|
||||
auto it = ctx.begin();
|
||||
if (it == ctx.end()) {
|
||||
return it;
|
||||
}
|
||||
|
||||
_currFmt.clear();
|
||||
_delim = " ";
|
||||
|
||||
for (; it != ctx.end(); ++it) {
|
||||
switch (*it) {
|
||||
case '#': // numerical error value
|
||||
_currFmt.push_back(*it);
|
||||
break;
|
||||
case '@': // error category name
|
||||
_currFmt.push_back(*it);
|
||||
break;
|
||||
case '^': // error message
|
||||
_currFmt.push_back(*it);
|
||||
break;
|
||||
case '_':
|
||||
// while (it++ != ctx.end() || it++ != '}' || it++ != '_') {
|
||||
// _currFmt.push_back(*(++it));
|
||||
// }
|
||||
|
||||
if (it++ != ctx.end() || it++ != '}') {
|
||||
_delim = *(++it);
|
||||
}
|
||||
case '}':
|
||||
if (_currFmt.empty()) {
|
||||
_currFmt = "#@^";
|
||||
}
|
||||
return it;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class FmtContext>
|
||||
FmtContext::iterator format(mcc::impl::MccError const& err, FmtContext& ctx) const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
size_t idx = 0;
|
||||
for (auto const& fmt_sym : _currFmt) {
|
||||
switch (fmt_sym) {
|
||||
case '#':
|
||||
out << err.value();
|
||||
++idx;
|
||||
break;
|
||||
case '@':
|
||||
out << err.category().name();
|
||||
++idx;
|
||||
break;
|
||||
case '^':
|
||||
out << err.message();
|
||||
++idx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (idx < _currFmt.size()) {
|
||||
out << _delim;
|
||||
}
|
||||
}
|
||||
|
||||
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _currFmt{}, _delim{" "};
|
||||
};
|
||||
|
||||
|
||||
static_assert(mcc::mcc_error_c<mcc::impl::MccError>, "");
|
||||
|
||||
|
||||
// a helper formatter impelementation
|
||||
|
||||
template <typename T>
|
||||
requires std::is_enum_v<T>
|
||||
struct std::formatter<T, char> : std::formatter<std::underlying_type_t<T>, char> {
|
||||
auto format(T e, auto& ctx) const
|
||||
{
|
||||
return formatter<std::underlying_type_t<T>>::format(std::underlying_type_t<T>(e), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
enum class EE : int { A, B, C };
|
||||
|
||||
static_assert(mcc::mcc_error_c<EE>, "");
|
||||
Reference in New Issue
Block a user