blob: c1e41d85b31bf0221cf6b871f075056af8390e18 [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
7
8#include "ErrorBase.h"
9#define WPI_ERRORS_DEFINE_STRINGS
10#include "WPIErrors.h"
11
12#include <errno.h>
13#include <cstring>
14#include <cstdio>
15#include <sstream>
16
17priority_mutex ErrorBase::_globalErrorMutex;
18Error ErrorBase::_globalError;
19
20/**
21 * @brief Retrieve the current error.
22 * Get the current error information associated with this sensor.
23 */
24Error& ErrorBase::GetError() { return m_error; }
25
26const Error& ErrorBase::GetError() const { return m_error; }
27
28/**
29 * @brief Clear the current error information associated with this sensor.
30 */
31void ErrorBase::ClearError() const { m_error.Clear(); }
32
33/**
34 * @brief Set error information associated with a C library call that set an
35 * error to the "errno" global variable.
36 *
37 * @param contextMessage A custom message from the code that set the error.
38 * @param filename Filename of the error source
39 * @param function Function of the error source
40 * @param lineNumber Line number of the error source
41 */
42void ErrorBase::SetErrnoError(llvm::StringRef contextMessage,
43 llvm::StringRef filename,
44 llvm::StringRef function,
45 uint32_t lineNumber) const {
46 std::string err;
47 int errNo = errno;
48 if (errNo == 0) {
49 err = "OK: ";
50 err += contextMessage;
51 } else {
52 char buf[256];
53 snprintf(buf, 256, "%s (0x%08X): %.*s", strerror(errNo), errNo,
54 contextMessage.size(), contextMessage.data());
55 err = buf;
56 }
57
58 // Set the current error information for this object.
59 m_error.Set(-1, err, filename, function, lineNumber, this);
60
61 // Update the global error if there is not one already set.
62 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
63 if (_globalError.GetCode() == 0) {
64 _globalError.Clone(m_error);
65 }
66}
67
68/**
69 * @brief Set the current error information associated from the nivision Imaq
70 * API.
71 *
72 * @param success The return from the function
73 * @param contextMessage A custom message from the code that set the error.
74 * @param filename Filename of the error source
75 * @param function Function of the error source
76 * @param lineNumber Line number of the error source
77 */
78void ErrorBase::SetImaqError(int success, llvm::StringRef contextMessage,
79 llvm::StringRef filename, llvm::StringRef function,
80 uint32_t lineNumber) const {
81 // If there was an error
82 if (success <= 0) {
83 std::stringstream err;
84 err << success << ": " << contextMessage;
85
86 // Set the current error information for this object.
87 m_error.Set(success, err.str(), filename, function, lineNumber, this);
88
89 // Update the global error if there is not one already set.
90 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
91 if (_globalError.GetCode() == 0) {
92 _globalError.Clone(m_error);
93 }
94 }
95}
96
97/**
98 * @brief Set the current error information associated with this sensor.
99 *
100 * @param code The error code
101 * @param contextMessage A custom message from the code that set the error.
102 * @param filename Filename of the error source
103 * @param function Function of the error source
104 * @param lineNumber Line number of the error source
105 */
106void ErrorBase::SetError(Error::Code code, llvm::StringRef contextMessage,
107 llvm::StringRef filename, llvm::StringRef function,
108 uint32_t lineNumber) const {
109 // If there was an error
110 if (code != 0) {
111 // Set the current error information for this object.
112 m_error.Set(code, contextMessage, filename, function, lineNumber, this);
113
114 // Update the global error if there is not one already set.
115 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
116 if (_globalError.GetCode() == 0) {
117 _globalError.Clone(m_error);
118 }
119 }
120}
121
122/**
123 * @brief Set the current error information associated with this sensor.
124 *
125 * @param errorMessage The error message from WPIErrors.h
126 * @param contextMessage A custom message from the code that set the error.
127 * @param filename Filename of the error source
128 * @param function Function of the error source
129 * @param lineNumber Line number of the error source
130 */
131void ErrorBase::SetWPIError(llvm::StringRef errorMessage, Error::Code code,
132 llvm::StringRef contextMessage,
133 llvm::StringRef filename, llvm::StringRef function,
134 uint32_t lineNumber) const {
135 std::string err = errorMessage.str() + ": " + contextMessage.str();
136
137 // Set the current error information for this object.
138 m_error.Set(code, err, filename, function, lineNumber, this);
139
140 // Update the global error if there is not one already set.
141 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
142 if (_globalError.GetCode() == 0) {
143 _globalError.Clone(m_error);
144 }
145}
146
147void ErrorBase::CloneError(const ErrorBase& rhs) const {
148 m_error.Clone(rhs.GetError());
149}
150
151/**
152@brief Check if the current error code represents a fatal error.
153
154@return true if the current error is fatal.
155*/
156bool ErrorBase::StatusIsFatal() const { return m_error.GetCode() < 0; }
157
158void ErrorBase::SetGlobalError(Error::Code code, llvm::StringRef contextMessage,
159 llvm::StringRef filename,
160 llvm::StringRef function, uint32_t lineNumber) {
161 // If there was an error
162 if (code != 0) {
163 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
164
165 // Set the current error information for this object.
166 _globalError.Set(code, contextMessage, filename, function, lineNumber,
167 nullptr);
168 }
169}
170
171void ErrorBase::SetGlobalWPIError(llvm::StringRef errorMessage,
172 llvm::StringRef contextMessage,
173 llvm::StringRef filename,
174 llvm::StringRef function,
175 uint32_t lineNumber) {
176 std::string err = errorMessage.str() + ": " + contextMessage.str();
177
178 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
179 if (_globalError.GetCode() != 0) {
180 _globalError.Clear();
181 }
182 _globalError.Set(-1, err, filename, function, lineNumber, nullptr);
183}
184
185/**
186 * Retrieve the current global error.
187*/
188Error& ErrorBase::GetGlobalError() {
189 std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
190 return _globalError;
191}