File indexing completed on 2025-09-13 09:10:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RError
0015 #define ROOT_RError
0016
0017 #include <ROOT/RConfig.hxx> // for R__[un]likely
0018 #include <ROOT/RLogger.hxx> // for R__LOG_PRETTY_FUNCTION
0019
0020 #include <cstddef>
0021 #include <memory>
0022 #include <new>
0023 #include <optional>
0024 #include <stdexcept>
0025 #include <string>
0026 #include <string_view>
0027 #include <utility>
0028 #include <vector>
0029
0030 namespace ROOT {
0031
0032
0033
0034
0035
0036
0037
0038
0039 class RError {
0040 public:
0041 struct RLocation {
0042 RLocation() = default;
0043 RLocation(const char *func, const char *file, unsigned int line)
0044 : fFunction(func), fSourceFile(file), fSourceLine(line)
0045 {
0046 }
0047
0048
0049 const char *fFunction;
0050 const char *fSourceFile;
0051 unsigned int fSourceLine;
0052 };
0053
0054 private:
0055
0056 std::string fMessage;
0057
0058 std::vector<RLocation> fStackTrace;
0059
0060 public:
0061
0062 RError(std::string_view message, RLocation &&sourceLocation);
0063
0064 void AddFrame(RLocation &&sourceLocation);
0065
0066 void AppendToMessage(std::string_view info) { fMessage += info; }
0067
0068 std::string GetReport() const;
0069 const std::vector<RLocation> &GetStackTrace() const { return fStackTrace; }
0070 };
0071
0072
0073
0074
0075
0076
0077
0078
0079 class RException : public std::runtime_error {
0080 RError fError;
0081
0082 public:
0083 explicit RException(const RError &error) : std::runtime_error(error.GetReport()), fError(error) {}
0084 const RError &GetError() const { return fError; }
0085 };
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 class RResultBase {
0099 protected:
0100
0101 std::unique_ptr<RError> fError;
0102
0103 bool fIsChecked{false};
0104
0105 RResultBase() = default;
0106 explicit RResultBase(RError &&error) : fError(std::make_unique<RError>(std::move(error))) {}
0107
0108
0109 bool Check()
0110 {
0111 fIsChecked = true;
0112 return !fError;
0113 }
0114
0115 public:
0116 RResultBase(const RResultBase &other) = delete;
0117 RResultBase(RResultBase &&other) = default;
0118 RResultBase &operator=(const RResultBase &other) = delete;
0119 RResultBase &operator=(RResultBase &&other) = default;
0120
0121 ~RResultBase() noexcept(false);
0122
0123 std::optional<RError> GetError() const { return fError ? *fError : std::optional<RError>(); }
0124
0125 void Throw();
0126
0127
0128 static RError ForwardError(RResultBase &&result, RError::RLocation &&sourceLocation)
0129 {
0130 if (!result.fError) {
0131 return RError("internal error: attempt to forward error of successful operation", std::move(sourceLocation));
0132 }
0133 result.fError->AddFrame(std::move(sourceLocation));
0134 return *result.fError;
0135 }
0136 };
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 template <typename T>
0197 class RResult : public RResultBase {
0198 private:
0199
0200 T fValue;
0201
0202
0203 inline void ThrowOnError()
0204 {
0205 if (R__unlikely(fError)) {
0206
0207
0208
0209
0210 fIsChecked = true;
0211
0212 fError->AppendToMessage(" (unchecked RResult access!)");
0213 throw RException(*fError);
0214 }
0215 }
0216
0217 public:
0218 RResult(const T &value) : fValue(value) {}
0219 RResult(T &&value) : fValue(std::move(value)) {}
0220 RResult(RError &&error) : RResultBase(std::move(error)) {}
0221
0222 RResult(const RResult &other) = delete;
0223 RResult(RResult &&other) = default;
0224 RResult &operator=(const RResult &other) = delete;
0225 RResult &operator=(RResult &&other) = default;
0226
0227 ~RResult() = default;
0228
0229
0230 RResult &Forward(RError::RLocation &&sourceLocation)
0231 {
0232 if (fError)
0233 fError->AddFrame(std::move(sourceLocation));
0234 return *this;
0235 }
0236
0237
0238
0239 const T &Inspect()
0240 {
0241 ThrowOnError();
0242 return fValue;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252 T Unwrap()
0253 {
0254 ThrowOnError();
0255 return std::move(fValue);
0256 }
0257
0258 explicit operator bool() { return Check(); }
0259 };
0260
0261
0262 template <>
0263 class RResult<void> : public RResultBase {
0264 private:
0265 RResult() = default;
0266
0267 public:
0268
0269 static RResult Success() { return RResult(); }
0270 RResult(RError &&error) : RResultBase(std::move(error)) {}
0271
0272 RResult(const RResult &other) = delete;
0273 RResult(RResult &&other) = default;
0274 RResult &operator=(const RResult &other) = delete;
0275 RResult &operator=(RResult &&other) = default;
0276
0277 ~RResult() = default;
0278
0279
0280 RResult &Forward(RError::RLocation &&sourceLocation)
0281 {
0282 if (fError)
0283 fError->AddFrame(std::move(sourceLocation));
0284 return *this;
0285 }
0286
0287
0288
0289 void ThrowOnError()
0290 {
0291 if (!Check())
0292 Throw();
0293 }
0294
0295 explicit operator bool() { return Check(); }
0296 };
0297
0298
0299 #define R__FAIL(msg) ROOT::RError(msg, {R__LOG_PRETTY_FUNCTION, __FILE__, __LINE__})
0300
0301 #define R__FORWARD_RESULT(res) std::move(res.Forward({R__LOG_PRETTY_FUNCTION, __FILE__, __LINE__}))
0302
0303 #define R__FORWARD_ERROR(res) res.ForwardError(std::move(res), {R__LOG_PRETTY_FUNCTION, __FILE__, __LINE__})
0304
0305 }
0306
0307 #endif