blob: b3fa711ddebc0f7b9d45ea5b2ed3df5348f76f80 [file] [log] [blame]
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -07001// 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
Alex Vakulenko15104662014-08-27 11:00:57 -07005#include <chromeos/errors/error.h>
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -07006
7#include <base/logging.h>
8#include <base/strings/stringprintf.h>
9
10using chromeos::Error;
11using chromeos::ErrorPtr;
12
Alex Vakulenko8f815f52014-11-11 11:42:05 -080013namespace {
14inline 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 chromeos/errors/error.cc(22).
Alex Vakulenko05d29042015-01-13 09:39:25 -080022 logging::LogMessage(
23 location.file_name(), location.line_number(), logging::LOG_ERROR).stream()
Alex Vakulenko8f815f52014-11-11 11:42:05 -080024 << location.function_name() << "(...): "
Alex Vakulenko05d29042015-01-13 09:39:25 -080025 << "Domain=" << domain << ", Code=" << code << ", Message=" << message;
Alex Vakulenko8f815f52014-11-11 11:42:05 -080026}
27} // anonymous namespace
28
29ErrorPtr Error::Create(const tracked_objects::Location& location,
30 const std::string& domain,
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070031 const std::string& code,
32 const std::string& message) {
Alex Vakulenko8f815f52014-11-11 11:42:05 -080033 return Create(location, domain, code, message, ErrorPtr());
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070034}
35
Alex Vakulenko8f815f52014-11-11 11:42:05 -080036ErrorPtr Error::Create(const tracked_objects::Location& location,
37 const std::string& domain,
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070038 const std::string& code,
39 const std::string& message,
40 ErrorPtr inner_error) {
Alex Vakulenko8f815f52014-11-11 11:42:05 -080041 LogError(location, domain, code, message);
Alex Vakulenko05d29042015-01-13 09:39:25 -080042 return ErrorPtr(
43 new Error(location, domain, code, message, std::move(inner_error)));
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070044}
45
Alex Vakulenko8f815f52014-11-11 11:42:05 -080046void 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) {
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070051 if (error) {
Alex Vakulenko8f815f52014-11-11 11:42:05 -080052 *error = Create(location, domain, code, message, std::move(*error));
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070053 } else {
54 // Create already logs the error, but if |error| is nullptr,
55 // we still want to log the error...
Alex Vakulenko8f815f52014-11-11 11:42:05 -080056 LogError(location, domain, code, message);
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070057 }
58}
59
Alex Vakulenko8f815f52014-11-11 11:42:05 -080060void Error::AddToPrintf(ErrorPtr* error,
61 const tracked_objects::Location& location,
62 const std::string& domain,
63 const std::string& code,
Alex Vakulenko05d29042015-01-13 09:39:25 -080064 const char* format,
65 ...) {
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070066 va_list ap;
67 va_start(ap, format);
68 std::string message = base::StringPrintV(format, ap);
69 va_end(ap);
Alex Vakulenko8f815f52014-11-11 11:42:05 -080070 AddTo(error, location, domain, code, message);
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070071}
72
Vitaly Bukac3458582015-03-23 17:58:02 -070073ErrorPtr 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
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070079bool Error::HasDomain(const std::string& domain) const {
Alex Vakulenkob068aeb2014-09-30 12:54:10 -070080 return FindErrorOfDomain(this, domain) != nullptr;
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070081}
82
83bool Error::HasError(const std::string& domain, const std::string& code) const {
Alex Vakulenkob068aeb2014-09-30 12:54:10 -070084 return FindError(this, domain, code) != nullptr;
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -070085}
86
87const Error* Error::GetFirstError() const {
88 const Error* err = this;
89 while (err->GetInnerError())
90 err = err->GetInnerError();
91 return err;
92}
93
Alex Vakulenko8f815f52014-11-11 11:42:05 -080094Error::Error(const tracked_objects::Location& location,
95 const std::string& domain,
96 const std::string& code,
97 const std::string& message,
Alex Vakulenko05d29042015-01-13 09:39:25 -080098 ErrorPtr inner_error)
Vitaly Bukac3458582015-03-23 17:58:02 -070099 : Error{tracked_objects::LocationSnapshot{location},
100 domain,
101 code,
102 message,
103 std::move(inner_error)} {
104}
105
106Error::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)
Alex Vakulenko05d29042015-01-13 09:39:25 -0800111 : domain_(domain),
112 code_(code),
113 message_(message),
114 location_(location),
115 inner_error_(std::move(inner_error)) {
Alex Vakulenkoc909a9f2014-08-14 17:54:04 -0700116}
Alex Vakulenkob068aeb2014-09-30 12:54:10 -0700117
118const 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
128const 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}