• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <brillo/errors/error.h>
6 
7 #include <base/logging.h>
8 #include <base/strings/stringprintf.h>
9 
10 using brillo::Error;
11 using brillo::ErrorPtr;
12 
13 namespace {
LogError(const tracked_objects::Location & location,const std::string & domain,const std::string & code,const std::string & message)14 inline void LogError(const tracked_objects::Location& location,
15                      const std::string& domain,
16                      const std::string& code,
17                      const std::string& message) {
18   // Use logging::LogMessage() directly instead of LOG(ERROR) to substitute
19   // the current error location with the location passed in to the Error object.
20   // This way the log will contain the actual location of the error, and not
21   // as if it always comes from brillo/errors/error.cc(22).
22   logging::LogMessage(
23       location.file_name(), location.line_number(), logging::LOG_ERROR).stream()
24       << location.function_name() << "(...): "
25       << "Domain=" << domain << ", Code=" << code << ", Message=" << message;
26 }
27 }  // anonymous namespace
28 
Create(const tracked_objects::Location & location,const std::string & domain,const std::string & code,const std::string & message)29 ErrorPtr Error::Create(const tracked_objects::Location& location,
30                        const std::string& domain,
31                        const std::string& code,
32                        const std::string& message) {
33   return Create(location, domain, code, message, ErrorPtr());
34 }
35 
Create(const tracked_objects::Location & location,const std::string & domain,const std::string & code,const std::string & message,ErrorPtr inner_error)36 ErrorPtr Error::Create(const tracked_objects::Location& location,
37                        const std::string& domain,
38                        const std::string& code,
39                        const std::string& message,
40                        ErrorPtr inner_error) {
41   LogError(location, domain, code, message);
42   return ErrorPtr(
43       new Error(location, domain, code, message, std::move(inner_error)));
44 }
45 
AddTo(ErrorPtr * error,const tracked_objects::Location & location,const std::string & domain,const std::string & code,const std::string & message)46 void Error::AddTo(ErrorPtr* error,
47                   const tracked_objects::Location& location,
48                   const std::string& domain,
49                   const std::string& code,
50                   const std::string& message) {
51   if (error) {
52     *error = Create(location, domain, code, message, std::move(*error));
53   } else {
54     // Create already logs the error, but if |error| is nullptr,
55     // we still want to log the error...
56     LogError(location, domain, code, message);
57   }
58 }
59 
AddToPrintf(ErrorPtr * error,const tracked_objects::Location & location,const std::string & domain,const std::string & code,const char * format,...)60 void Error::AddToPrintf(ErrorPtr* error,
61                         const tracked_objects::Location& location,
62                         const std::string& domain,
63                         const std::string& code,
64                         const char* format,
65                         ...) {
66   va_list ap;
67   va_start(ap, format);
68   std::string message = base::StringPrintV(format, ap);
69   va_end(ap);
70   AddTo(error, location, domain, code, message);
71 }
72 
Clone() const73 ErrorPtr Error::Clone() const {
74   ErrorPtr inner_error = inner_error_ ? inner_error_->Clone() : nullptr;
75   return ErrorPtr(
76       new Error(location_, domain_, code_, message_, std::move(inner_error)));
77 }
78 
HasDomain(const std::string & domain) const79 bool Error::HasDomain(const std::string& domain) const {
80   return FindErrorOfDomain(this, domain) != nullptr;
81 }
82 
HasError(const std::string & domain,const std::string & code) const83 bool Error::HasError(const std::string& domain, const std::string& code) const {
84   return FindError(this, domain, code) != nullptr;
85 }
86 
GetFirstError() const87 const Error* Error::GetFirstError() const {
88   const Error* err = this;
89   while (err->GetInnerError())
90     err = err->GetInnerError();
91   return err;
92 }
93 
Error(const tracked_objects::Location & location,const std::string & domain,const std::string & code,const std::string & message,ErrorPtr inner_error)94 Error::Error(const tracked_objects::Location& location,
95              const std::string& domain,
96              const std::string& code,
97              const std::string& message,
98              ErrorPtr inner_error)
99     : Error{tracked_objects::LocationSnapshot{location},
100             domain,
101             code,
102             message,
103             std::move(inner_error)} {
104 }
105 
Error(const tracked_objects::LocationSnapshot & location,const std::string & domain,const std::string & code,const std::string & message,ErrorPtr inner_error)106 Error::Error(const tracked_objects::LocationSnapshot& location,
107              const std::string& domain,
108              const std::string& code,
109              const std::string& message,
110              ErrorPtr inner_error)
111     : domain_(domain),
112       code_(code),
113       message_(message),
114       location_(location),
115       inner_error_(std::move(inner_error)) {
116 }
117 
FindErrorOfDomain(const Error * error_chain_start,const std::string & domain)118 const Error* Error::FindErrorOfDomain(const Error* error_chain_start,
119                                       const std::string& domain) {
120   while (error_chain_start) {
121     if (error_chain_start->GetDomain() == domain)
122       break;
123     error_chain_start = error_chain_start->GetInnerError();
124   }
125   return error_chain_start;
126 }
127 
FindError(const Error * error_chain_start,const std::string & domain,const std::string & code)128 const Error* Error::FindError(const Error* error_chain_start,
129                               const std::string& domain,
130                               const std::string& code) {
131   while (error_chain_start) {
132     if (error_chain_start->GetDomain() == domain &&
133         error_chain_start->GetCode() == code)
134       break;
135     error_chain_start = error_chain_start->GetInnerError();
136   }
137   return error_chain_start;
138 }
139