| // Copyright 2015 The Weave Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <weave/error.h> | |
| #include <base/logging.h> | |
| #include <base/strings/stringprintf.h> | |
| namespace weave { | |
| namespace { | |
| inline void LogError(const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message) { | |
| // Use logging::LogMessage() directly instead of LOG(ERROR) to substitute | |
| // the current error location with the location passed in to the Error object. | |
| // This way the log will contain the actual location of the error, and not | |
| // as if it always comes from chromeos/errors/error.cc(22). | |
| logging::LogMessage(location.file_name(), location.line_number(), | |
| logging::LOG_ERROR) | |
| .stream() | |
| << location.function_name() << "(...): " | |
| << "Domain=" << domain << ", Code=" << code << ", Message=" << message; | |
| } | |
| } // anonymous namespace | |
| ErrorPtr Error::Create(const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message) { | |
| return Create(location, domain, code, message, ErrorPtr()); | |
| } | |
| ErrorPtr Error::Create(const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message, | |
| ErrorPtr inner_error) { | |
| LogError(location, domain, code, message); | |
| return ErrorPtr( | |
| new Error(location, domain, code, message, std::move(inner_error))); | |
| } | |
| void Error::AddTo(ErrorPtr* error, | |
| const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message) { | |
| if (error) { | |
| *error = Create(location, domain, code, message, std::move(*error)); | |
| } else { | |
| // Create already logs the error, but if |error| is nullptr, | |
| // we still want to log the error... | |
| LogError(location, domain, code, message); | |
| } | |
| } | |
| void Error::AddToPrintf(ErrorPtr* error, | |
| const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const char* format, | |
| ...) { | |
| va_list ap; | |
| va_start(ap, format); | |
| std::string message = base::StringPrintV(format, ap); | |
| va_end(ap); | |
| AddTo(error, location, domain, code, message); | |
| } | |
| ErrorPtr Error::Clone() const { | |
| ErrorPtr inner_error = inner_error_ ? inner_error_->Clone() : nullptr; | |
| return ErrorPtr( | |
| new Error(location_, domain_, code_, message_, std::move(inner_error))); | |
| } | |
| bool Error::HasDomain(const std::string& domain) const { | |
| return FindErrorOfDomain(this, domain) != nullptr; | |
| } | |
| bool Error::HasError(const std::string& domain, const std::string& code) const { | |
| return FindError(this, domain, code) != nullptr; | |
| } | |
| const Error* Error::GetFirstError() const { | |
| const Error* err = this; | |
| while (err->GetInnerError()) | |
| err = err->GetInnerError(); | |
| return err; | |
| } | |
| Error::Error(const tracked_objects::Location& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message, | |
| ErrorPtr inner_error) | |
| : Error{tracked_objects::LocationSnapshot{location}, domain, code, message, | |
| std::move(inner_error)} {} | |
| Error::Error(const tracked_objects::LocationSnapshot& location, | |
| const std::string& domain, | |
| const std::string& code, | |
| const std::string& message, | |
| ErrorPtr inner_error) | |
| : domain_(domain), | |
| code_(code), | |
| message_(message), | |
| location_(location), | |
| inner_error_(std::move(inner_error)) {} | |
| const Error* Error::FindErrorOfDomain(const Error* error_chain_start, | |
| const std::string& domain) { | |
| while (error_chain_start) { | |
| if (error_chain_start->GetDomain() == domain) | |
| break; | |
| error_chain_start = error_chain_start->GetInnerError(); | |
| } | |
| return error_chain_start; | |
| } | |
| const Error* Error::FindError(const Error* error_chain_start, | |
| const std::string& domain, | |
| const std::string& code) { | |
| while (error_chain_start) { | |
| if (error_chain_start->GetDomain() == domain && | |
| error_chain_start->GetCode() == code) | |
| break; | |
| error_chain_start = error_chain_start->GetInnerError(); | |
| } | |
| return error_chain_start; | |
| } | |
| } // namespace weave |