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