Squashed 'third_party/allwpilib_2017/' content from commit 35ac87d

Change-Id: I7bb6f5556c30d3f5a092e68de0be9c710c60c9f4
git-subtree-dir: third_party/allwpilib_2017
git-subtree-split: 35ac87d6ff8b7f061c4f18c9ea316e5dccd4888a
diff --git a/wpilibc/shared/src/ErrorBase.cpp b/wpilibc/shared/src/ErrorBase.cpp
new file mode 100644
index 0000000..3323fe2
--- /dev/null
+++ b/wpilibc/shared/src/ErrorBase.cpp
@@ -0,0 +1,231 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008-2017. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "ErrorBase.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <iomanip>
+#include <sstream>
+
+#define WPI_ERRORS_DEFINE_STRINGS
+#include "WPIErrors.h"
+
+using namespace frc;
+
+priority_mutex ErrorBase::_globalErrorMutex;
+Error ErrorBase::_globalError;
+
+/**
+ * @brief Retrieve the current error.
+ * Get the current error information associated with this sensor.
+ */
+Error& ErrorBase::GetError() { return m_error; }
+
+const Error& ErrorBase::GetError() const { return m_error; }
+
+/**
+ * @brief Clear the current error information associated with this sensor.
+ */
+void ErrorBase::ClearError() const { m_error.Clear(); }
+
+/**
+ * @brief Set error information associated with a C library call that set an
+ * error to the "errno" global variable.
+ *
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename       Filename of the error source
+ * @param function       Function of the error source
+ * @param lineNumber     Line number of the error source
+ */
+void ErrorBase::SetErrnoError(llvm::StringRef contextMessage,
+                              llvm::StringRef filename,
+                              llvm::StringRef function, int lineNumber) const {
+  std::string err;
+  int errNo = errno;
+  if (errNo == 0) {
+    err = "OK: ";
+    err += contextMessage;
+  } else {
+    std::ostringstream oss;
+    oss << std::strerror(errNo) << " (0x" << std::setfill('0') << std::hex
+        << std::uppercase << std::setw(8) << errNo << "): " << contextMessage;
+    err = oss.str();
+  }
+
+  // Set the current error information for this object.
+  m_error.Set(-1, err, filename, function, lineNumber, this);
+
+  // Update the global error if there is not one already set.
+  std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+  if (_globalError.GetCode() == 0) {
+    _globalError.Clone(m_error);
+  }
+}
+
+/**
+ * @brief Set the current error information associated from the nivision Imaq
+ * API.
+ *
+ * @param success        The return from the function
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename       Filename of the error source
+ * @param function       Function of the error source
+ * @param lineNumber     Line number of the error source
+ */
+void ErrorBase::SetImaqError(int success, llvm::StringRef contextMessage,
+                             llvm::StringRef filename, llvm::StringRef function,
+                             int lineNumber) const {
+  // If there was an error
+  if (success <= 0) {
+    std::stringstream err;
+    err << success << ": " << contextMessage;
+
+    // Set the current error information for this object.
+    m_error.Set(success, err.str(), filename, function, lineNumber, this);
+
+    // Update the global error if there is not one already set.
+    std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+    if (_globalError.GetCode() == 0) {
+      _globalError.Clone(m_error);
+    }
+  }
+}
+
+/**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param code           The error code
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename       Filename of the error source
+ * @param function       Function of the error source
+ * @param lineNumber     Line number of the error source
+ */
+void ErrorBase::SetError(Error::Code code, llvm::StringRef contextMessage,
+                         llvm::StringRef filename, llvm::StringRef function,
+                         int lineNumber) const {
+  //  If there was an error
+  if (code != 0) {
+    //  Set the current error information for this object.
+    m_error.Set(code, contextMessage, filename, function, lineNumber, this);
+
+    // Update the global error if there is not one already set.
+    std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+    if (_globalError.GetCode() == 0) {
+      _globalError.Clone(m_error);
+    }
+  }
+}
+
+/**
+ * @brief Set the current error information associated with this sensor.
+ * Range versions use for initialization code.
+ *
+ * @param code           The error code
+ * @param minRange       The minimum allowed allocation range
+ * @param maxRange       The maximum allowed allocation range
+ * @param requestedValue The requested value to allocate
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename       Filename of the error source
+ * @param function       Function of the error source
+ * @param lineNumber     Line number of the error source
+ */
+void ErrorBase::SetErrorRange(Error::Code code, int32_t minRange,
+                              int32_t maxRange, int32_t requestedValue,
+                              llvm::StringRef contextMessage,
+                              llvm::StringRef filename,
+                              llvm::StringRef function, int lineNumber) const {
+  //  If there was an error
+  if (code != 0) {
+    size_t size = contextMessage.size() + 100;
+    char* buf = new char[size];
+    std::snprintf(
+        buf, size,
+        "%s, Minimum Value: %d, Maximum Value: %d, Requested Value: %d",
+        contextMessage.data(), minRange, maxRange, requestedValue);
+    //  Set the current error information for this object.
+    m_error.Set(code, buf, filename, function, lineNumber, this);
+    delete[] buf;
+
+    // Update the global error if there is not one already set.
+    std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+    if (_globalError.GetCode() == 0) {
+      _globalError.Clone(m_error);
+    }
+  }
+}
+
+/**
+ * @brief Set the current error information associated with this sensor.
+ *
+ * @param errorMessage   The error message from WPIErrors.h
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename       Filename of the error source
+ * @param function       Function of the error source
+ * @param lineNumber     Line number of the error source
+ */
+void ErrorBase::SetWPIError(llvm::StringRef errorMessage, Error::Code code,
+                            llvm::StringRef contextMessage,
+                            llvm::StringRef filename, llvm::StringRef function,
+                            int lineNumber) const {
+  std::string err = errorMessage.str() + ": " + contextMessage.str();
+
+  //  Set the current error information for this object.
+  m_error.Set(code, err, filename, function, lineNumber, this);
+
+  // Update the global error if there is not one already set.
+  std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+  if (_globalError.GetCode() == 0) {
+    _globalError.Clone(m_error);
+  }
+}
+
+void ErrorBase::CloneError(const ErrorBase& rhs) const {
+  m_error.Clone(rhs.GetError());
+}
+
+/**
+ * @brief Check if the current error code represents a fatal error.
+ *
+ * @return true if the current error is fatal.
+ */
+bool ErrorBase::StatusIsFatal() const { return m_error.GetCode() < 0; }
+
+void ErrorBase::SetGlobalError(Error::Code code, llvm::StringRef contextMessage,
+                               llvm::StringRef filename,
+                               llvm::StringRef function, int lineNumber) {
+  // If there was an error
+  if (code != 0) {
+    std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+
+    // Set the current error information for this object.
+    _globalError.Set(code, contextMessage, filename, function, lineNumber,
+                     nullptr);
+  }
+}
+
+void ErrorBase::SetGlobalWPIError(llvm::StringRef errorMessage,
+                                  llvm::StringRef contextMessage,
+                                  llvm::StringRef filename,
+                                  llvm::StringRef function, int lineNumber) {
+  std::string err = errorMessage.str() + ": " + contextMessage.str();
+
+  std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+  if (_globalError.GetCode() != 0) {
+    _globalError.Clear();
+  }
+  _globalError.Set(-1, err, filename, function, lineNumber, nullptr);
+}
+
+/**
+ * Retrieve the current global error.
+ */
+Error& ErrorBase::GetGlobalError() {
+  std::lock_guard<priority_mutex> mutex(_globalErrorMutex);
+  return _globalError;
+}