blob: 89071df949895cedd03f3c2d1492981ad41ead9e [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka0801a1f2015-08-14 10:03:46 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <weave/error.h>
6
7#include <base/logging.h>
8#include <base/strings/stringprintf.h>
9
10namespace weave {
11
12namespace {
13inline void LogError(const tracked_objects::Location& location,
14 const std::string& domain,
15 const std::string& code,
16 const std::string& message) {
17 // Use logging::LogMessage() directly instead of LOG(ERROR) to substitute
18 // the current error location with the location passed in to the Error object.
19 // This way the log will contain the actual location of the error, and not
20 // as if it always comes from chromeos/errors/error.cc(22).
21 logging::LogMessage(location.file_name(), location.line_number(),
22 logging::LOG_ERROR)
23 .stream()
24 << location.function_name() << "(...): "
25 << "Domain=" << domain << ", Code=" << code << ", Message=" << message;
26}
27} // anonymous namespace
28
29ErrorPtr 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
36ErrorPtr 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
46void 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
60void 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
73ErrorPtr 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
79bool Error::HasDomain(const std::string& domain) const {
80 return FindErrorOfDomain(this, domain) != nullptr;
81}
82
83bool Error::HasError(const std::string& domain, const std::string& code) const {
84 return FindError(this, domain, code) != nullptr;
85}
86
87const Error* Error::GetFirstError() const {
88 const Error* err = this;
89 while (err->GetInnerError())
90 err = err->GetInnerError();
91 return err;
92}
93
94Error::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}, domain, code, message,
100 std::move(inner_error)} {}
101
102Error::Error(const tracked_objects::LocationSnapshot& location,
103 const std::string& domain,
104 const std::string& code,
105 const std::string& message,
106 ErrorPtr inner_error)
107 : domain_(domain),
108 code_(code),
109 message_(message),
110 location_(location),
111 inner_error_(std::move(inner_error)) {}
112
113const Error* Error::FindErrorOfDomain(const Error* error_chain_start,
114 const std::string& domain) {
115 while (error_chain_start) {
116 if (error_chain_start->GetDomain() == domain)
117 break;
118 error_chain_start = error_chain_start->GetInnerError();
119 }
120 return error_chain_start;
121}
122
123const Error* Error::FindError(const Error* error_chain_start,
124 const std::string& domain,
125 const std::string& code) {
126 while (error_chain_start) {
127 if (error_chain_start->GetDomain() == domain &&
128 error_chain_start->GetCode() == code)
129 break;
130 error_chain_start = error_chain_start->GetInnerError();
131 }
132 return error_chain_start;
133}
134
135} // namespace weave