aboutsummaryrefslogtreecommitdiff
path: root/src/error.cc
blob: cb279c15d201f859c7604ef6ec00fa26a3133255 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 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& 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() << "(...): "
      << "Code=" << code << ", Message=" << message;
}
}  // anonymous namespace

ErrorPtr Error::Create(const tracked_objects::Location& location,
                       const std::string& code,
                       const std::string& message) {
  return Create(location, code, message, ErrorPtr());
}

ErrorPtr Error::Create(const tracked_objects::Location& location,
                       const std::string& code,
                       const std::string& message,
                       ErrorPtr inner_error) {
  LogError(location, code, message);
  return ErrorPtr(new Error(location, code, message, std::move(inner_error)));
}

Error::AddToTypeProxy Error::AddTo(ErrorPtr* error,
                                   const tracked_objects::Location& location,
                                   const std::string& code,
                                   const std::string& message) {
  if (error) {
    *error = Create(location, 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, code, message);
  }
  return {};
}

Error::AddToTypeProxy Error::AddToPrintf(
    ErrorPtr* error,
    const tracked_objects::Location& location,
    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, code, message);
  return {};
}

ErrorPtr Error::Clone() const {
  ErrorPtr inner_error = inner_error_ ? inner_error_->Clone() : nullptr;
  return ErrorPtr(
      new Error(location_, code_, message_, std::move(inner_error)));
}

bool Error::HasError(const std::string& code) const {
  return FindError(this, 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& code,
             const std::string& message,
             ErrorPtr inner_error)
    : Error{tracked_objects::LocationSnapshot{location}, code, message,
            std::move(inner_error)} {}

Error::Error(const tracked_objects::LocationSnapshot& location,
             const std::string& code,
             const std::string& message,
             ErrorPtr inner_error)
    : code_(code),
      message_(message),
      location_(location),
      inner_error_(std::move(inner_error)) {}

const Error* Error::FindError(const Error* error_chain_start,
                              const std::string& code) {
  while (error_chain_start) {
    if (error_chain_start->GetCode() == code)
      break;
    error_chain_start = error_chain_start->GetInnerError();
  }
  return error_chain_start;
}

}  // namespace weave