125 lines
3.6 KiB
C++
125 lines
3.6 KiB
C++
#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>, "");
|