LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
error.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_UTIL_ERROR_H
6#define LINE_UTIL_ERROR_H
7
8/**
9 * @file
10 * @ingroup line_util
11 * The exception types the port throws.
12 *
13 * `Error` and its five refinements, one per category of the cross-codebase
14 * error vocabulary (`_kb/17-error-vocabulary.md`): `InputError` for a malformed
15 * model or argument, `NumericError` for a computation that cannot produce an
16 * answer, `UnsupportedError` for a feature the chosen algorithm does not cover,
17 * `ExternalError` for a missing or failed tool, and `InternalError` for a bug. Nothing
18 * in the library calls `exit()` or writes to stderr on failure: the CLI catches
19 * these at `main` and the bindings map them to exceptions, so the same code path
20 * serves both.
21 */
22
23#include <cstddef>
24#include <stdexcept>
25#include <string>
26#include <utility>
27
28namespace line {
29
30/**
31 * The `<kind>` part of a `LINE:<category>:<kind>` identifier (see
32 * `_kb/17-error-vocabulary.md`): an identifier such as `Cache`,
33 * `SchedStrategy_PS`, `NonConvergence` or `Method`. A typed wrapper rather than a
34 * bare string so that `UnsupportedError(kind, what)` cannot be confused with the
35 * one-string constructor.
36 */
37struct ErrorKind {
38 std::string name;
39 explicit ErrorKind(std::string n) : name(std::move(n)) {}
40};
41
42namespace error_detail {
43
44/** True when `s` matches `[A-Za-z][A-Za-z0-9_]*`, the grammar of a kind. */
45inline bool valid_kind(const std::string& s) {
46 if (s.empty()) return false;
47 auto alpha = [](char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); };
48 auto digit = [](char c) { return c >= '0' && c <= '9'; };
49 if (!alpha(s[0])) return false;
50 for (char c : s)
51 if (!alpha(c) && !digit(c) && c != '_') return false;
52 return true;
53}
54
55/** `LINE:<category>:<kind>`, or `LINE:internal:BadErrorId` for a malformed kind. */
56inline std::string make_id(const char* category, const std::string& kind) {
57 if (!valid_kind(kind)) return "LINE:internal:BadErrorId";
58 return std::string("LINE:") + category + ":" + kind;
59}
60
61} // namespace error_detail
62
63/**
64 * Base error for the multiprecision C++ port. Nothing in the library calls
65 * exit() or prints to stderr on failure: the CLI catches these at main and the
66 * Python binding maps them to exceptions, so the same code path serves both.
67 *
68 * Every error carries an identifier from the cross-codebase vocabulary,
69 * `LINE:<category>:<kind>`, shared with MATLAB error ids, Java `LineException`
70 * and Python `LineError`. A bare `Error` is `LINE:Error`, the legacy
71 * unclassified id; the refinements below fix the category.
72 */
73class Error : public std::runtime_error {
74public:
75 explicit Error(const std::string& what) : std::runtime_error(what), id_("LINE:Error") {}
76
77 /** The full identifier, e.g. `LINE:unsupported:Cache`. */
78 const std::string& id() const noexcept { return id_; }
79
80 /** `unsupported`, `numerical`, `input`, `external`, `internal`, or empty for `LINE:Error`. */
81 std::string category() const {
82 const std::size_t a = id_.find(':');
83 const std::size_t b = id_.find(':', a + 1);
84 return b == std::string::npos ? std::string() : id_.substr(a + 1, b - a - 1);
85 }
86
87 /** The `<kind>` part, or empty for `LINE:Error`. */
88 std::string kind() const {
89 const std::size_t a = id_.find(':');
90 const std::size_t b = id_.find(':', a + 1);
91 return b == std::string::npos ? std::string() : id_.substr(b + 1);
92 }
93
94protected:
95 Error(const char* category, const std::string& kind, const std::string& what)
96 : std::runtime_error(what), id_(error_detail::make_id(category, kind)) {}
97
98private:
99 std::string id_;
100};
101
102/** Malformed or inconsistent input (dimensions, negative populations, ...): `LINE:input:<kind>`. */
103class InputError : public Error {
104public:
105 explicit InputError(const std::string& what) : Error("input", "Unspecified", what) {}
106 InputError(const ErrorKind& kind, const std::string& what) : Error("input", kind.name, what) {}
107};
108
109/** The algorithm cannot produce a trustworthy answer on this instance: `LINE:numerical:<kind>`. */
110class NumericError : public Error {
111public:
112 explicit NumericError(const std::string& what) : Error("numerical", "Unspecified", what) {}
113 NumericError(const ErrorKind& kind, const std::string& what) : Error("numerical", kind.name, what) {}
114};
115
116/** A refusal: the feature, method or analysis is not covered: `LINE:unsupported:<kind>`. */
117class UnsupportedError : public Error {
118public:
119 explicit UnsupportedError(const std::string& what) : Error("unsupported", "Unspecified", what) {}
120 UnsupportedError(const ErrorKind& kind, const std::string& what) : Error("unsupported", kind.name, what) {}
121};
122
123/** A tool, binary, service or bridge LINE depends on is missing or failed: `LINE:external:<kind>`. */
124class ExternalError : public Error {
125public:
126 explicit ExternalError(const std::string& what) : Error("external", "Unspecified", what) {}
127 ExternalError(const ErrorKind& kind, const std::string& what) : Error("external", kind.name, what) {}
128};
129
130/** An invariant LINE should guarantee was violated, i.e. a bug: `LINE:internal:<kind>`. */
131class InternalError : public Error {
132public:
133 explicit InternalError(const std::string& what) : Error("internal", "Unspecified", what) {}
134 InternalError(const ErrorKind& kind, const std::string& what) : Error("internal", kind.name, what) {}
135};
136
137} // namespace line
138
139#endif // LINE_UTIL_ERROR_H
Error(const char *category, const std::string &kind, const std::string &what)
Definition error.h:95
const std::string & id() const noexcept
The full identifier, e.g.
Definition error.h:78
Error(const std::string &what)
Definition error.h:75
std::string category() const
unsupported, numerical, input, external, internal, or empty for LINE:Error.
Definition error.h:81
std::string kind() const
The <kind> part, or empty for LINE:Error.
Definition error.h:88
ExternalError(const std::string &what)
Definition error.h:126
ExternalError(const ErrorKind &kind, const std::string &what)
Definition error.h:127
InputError(const std::string &what)
Definition error.h:105
InputError(const ErrorKind &kind, const std::string &what)
Definition error.h:106
InternalError(const ErrorKind &kind, const std::string &what)
Definition error.h:134
InternalError(const std::string &what)
Definition error.h:133
NumericError(const ErrorKind &kind, const std::string &what)
Definition error.h:113
NumericError(const std::string &what)
Definition error.h:112
UnsupportedError(const ErrorKind &kind, const std::string &what)
Definition error.h:120
UnsupportedError(const std::string &what)
Definition error.h:119
bool valid_kind(const std::string &s)
True when s matches [A-Za-z][A-Za-z0-9_]*, the grammar of a kind.
Definition error.h:45
std::string make_id(const char *category, const std::string &kind)
LINE:<category>:<kind>, or LINE:internal:BadErrorId for a malformed kind.
Definition error.h:56
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
Definition error.h:37
std::string name
Definition error.h:38
ErrorKind(std::string n)
Definition error.h:39