1// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBBRILLO_BRILLO_ERRORS_ERROR_H_
6#define LIBBRILLO_BRILLO_ERRORS_ERROR_H_
7
8#include <memory>
9#include <string>
10
11#include <base/macros.h>
12#include <base/tracked_objects.h>
13#include <brillo/brillo_export.h>
14
15namespace brillo {
16
17class Error;  // Forward declaration.
18
19using ErrorPtr = std::unique_ptr<Error>;
20
21class BRILLO_EXPORT Error {
22 public:
23  virtual ~Error() = default;
24
25  // Creates an instance of Error class.
26  static ErrorPtr Create(const tracked_objects::Location& location,
27                         const std::string& domain,
28                         const std::string& code,
29                         const std::string& message);
30  static ErrorPtr Create(const tracked_objects::Location& location,
31                         const std::string& domain,
32                         const std::string& code,
33                         const std::string& message,
34                         ErrorPtr inner_error);
35  // If |error| is not nullptr, creates another instance of Error class,
36  // initializes it with specified arguments and adds it to the head of
37  // the error chain pointed to by |error|.
38  static void AddTo(ErrorPtr* error,
39                    const tracked_objects::Location& location,
40                    const std::string& domain,
41                    const std::string& code,
42                    const std::string& message);
43  // Same as the Error::AddTo above, but allows to pass in a printf-like
44  // format string and optional parameters to format the error message.
45  static void AddToPrintf(ErrorPtr* error,
46                          const tracked_objects::Location& location,
47                          const std::string& domain,
48                          const std::string& code,
49                          const char* format,
50                          ...) PRINTF_FORMAT(5, 6);
51
52  // Clones error with all inner errors.
53  ErrorPtr Clone() const;
54
55  // Returns the error domain, code and message
56  const std::string& GetDomain() const { return domain_; }
57  const std::string& GetCode() const { return code_; }
58  const std::string& GetMessage() const { return message_; }
59
60  // Returns the location of the error in the source code.
61  const tracked_objects::LocationSnapshot& GetLocation() const {
62    return location_;
63  }
64
65  // Checks if this or any of the inner errors in the chain has the specified
66  // error domain.
67  bool HasDomain(const std::string& domain) const;
68
69  // Checks if this or any of the inner errors in the chain matches the
70  // specified error domain and code.
71  bool HasError(const std::string& domain, const std::string& code) const;
72
73  // Gets a pointer to the inner error, if present. Returns nullptr otherwise.
74  const Error* GetInnerError() const { return inner_error_.get(); }
75
76  // Gets a pointer to the first error occurred.
77  // Returns itself if no inner error are available.
78  const Error* GetFirstError() const;
79
80  // Finds an error object of particular domain in the error chain stating at
81  // |error_chain_start|. Returns the a pointer to the first matching error
82  // object found.
83  // Returns nullptr if no match is found.
84  // This method is safe to call on a nullptr |error_chain_start| in which case
85  // the result will also be nullptr.
86  static const Error* FindErrorOfDomain(const Error* error_chain_start,
87                                        const std::string& domain);
88  // Finds an error of particular domain with the given code in the error chain
89  // stating at |error_chain_start|. Returns the pointer to the first matching
90  // error object.
91  // Returns nullptr if no match is found or if |error_chain_start| is nullptr.
92  static const Error* FindError(const Error* error_chain_start,
93                                const std::string& domain,
94                                const std::string& code);
95
96 protected:
97  // Constructor is protected since this object is supposed to be
98  // created via the Create factory methods.
99  Error(const tracked_objects::Location& location,
100        const std::string& domain,
101        const std::string& code,
102        const std::string& message,
103        ErrorPtr inner_error);
104
105  Error(const tracked_objects::LocationSnapshot& location,
106        const std::string& domain,
107        const std::string& code,
108        const std::string& message,
109        ErrorPtr inner_error);
110
111  // Error domain. The domain defines the scopes for error codes.
112  // Two errors with the same code but different domains are different errors.
113  std::string domain_;
114  // Error code. A unique error code identifier within the given domain.
115  std::string code_;
116  // Human-readable error message.
117  std::string message_;
118  // Error origin in the source code.
119  tracked_objects::LocationSnapshot location_;
120  // Pointer to inner error, if any. This forms a chain of errors.
121  ErrorPtr inner_error_;
122
123 private:
124  DISALLOW_COPY_AND_ASSIGN(Error);
125};
126
127}  // namespace brillo
128
129#endif  // LIBBRILLO_BRILLO_ERRORS_ERROR_H_
130