Skip to content
This repository was archived by the owner on Feb 13, 2024. It is now read-only.

Commit a3412bc

Browse files
committed
Introduce a polymorphic BaseError class and Error wrapper (lib)
1 parent 74093f6 commit a3412bc

File tree

4 files changed

+97
-2
lines changed

4 files changed

+97
-2
lines changed

src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ set(LIBRARY_SOURCE_FILES
4040
util/random.cc
4141
util/rectangle.cc
4242
util/json.cc
43+
util/error.cc
4344

4445
database/database.cc
4546
database/migrations.cc

src/types.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55

66
#include <string>
77

8+
#include "util/error.h"
9+
810
namespace toggl {
911

1012
typedef std::string error;
11-
12-
const error noError = "";
13+
const error noError { "" };
1314

1415
typedef std::string guid;
1516

src/util/error.cc

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include "error.h"
2+

src/util/error.h

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#ifndef ERROR_H
2+
#define ERROR_H
3+
4+
#include "types.h"
5+
6+
#include <memory>
7+
#include <ostream>
8+
9+
namespace toggl {
10+
11+
class ErrorBase {
12+
public:
13+
virtual std::string Class() const = 0;
14+
virtual int Type() const { return 0; }
15+
virtual bool IsError() const { return true; };
16+
virtual std::string LogMessage() const = 0;
17+
virtual std::string UserMessage() const { return ""; }
18+
19+
bool operator==(const ErrorBase &o) const {
20+
return IsError() == o.IsError() &&
21+
UserMessage() == o.UserMessage();
22+
}
23+
};
24+
25+
class NoError : public ErrorBase {
26+
public:
27+
virtual std::string Class() const override { return "NoError"; }
28+
virtual bool IsError() const override { return false; }
29+
virtual std::string LogMessage() const override { return {}; }
30+
virtual std::string UserMessage() const override { return {}; }
31+
};
32+
33+
class Error {
34+
public:
35+
template<class T> Error(T &&e) : data_(std::make_shared<T>(std::move(e))) { }
36+
template<class T> Error(const T &e) : data_(std::make_shared<T>(e)) { }
37+
Error(Error &&o) : data_(std::move(o.data_)) { }
38+
Error(const Error &o) : data_(o.data_) { }
39+
Error &operator=(const Error &o) {
40+
data_ = o.data_;
41+
return *this;
42+
}
43+
ErrorBase *operator->() { return data_.get(); }
44+
const ErrorBase *operator->() const { return data_.get(); }
45+
ErrorBase &operator*() { return *data_.get(); }
46+
const ErrorBase &operator*() const { return *data_.get(); }
47+
bool operator==(const Error &o) const {
48+
return *data_ == *o.data_;
49+
}
50+
operator std::string() const {
51+
return data_->LogMessage();
52+
}
53+
/**
54+
* This method is to be used to access the actual derived type,
55+
* not just the stuff that's exposed by the ErrorBase interface
56+
*
57+
* @return a shared pointer to a derived error type
58+
*/
59+
template<class T> std::shared_ptr<T> promote() {
60+
return std::dynamic_pointer_cast<T>(data_);
61+
}
62+
private:
63+
std::shared_ptr<ErrorBase> data_;
64+
};
65+
66+
inline std::ostream &operator<<(std::ostream &out, const Error &err) {
67+
out << err->UserMessage();
68+
out << std::string(" ");
69+
out << err->LogMessage();
70+
return out;
71+
}
72+
73+
/* TODO WARNING
74+
* These operators exist only to provide backward compatibility with the string-based error class
75+
* They should be removed once all of string-based error is gone
76+
*/
77+
inline bool operator==(const Error &l, const std::string &r) {
78+
return l->LogMessage() == r;
79+
}
80+
inline bool operator!=(const Error &l, const std::string &r) {
81+
return l->LogMessage() != r;
82+
}
83+
inline bool operator==(const std::string &l, const Error &r) {
84+
return l == r->LogMessage();
85+
}
86+
inline bool operator!=(const std::string &l, const Error &r) {
87+
return l != r->LogMessage();
88+
}
89+
}
90+
91+
#endif // ERROR_H

0 commit comments

Comments
 (0)