Squashed 'third_party/ntcore_2016/' content from commit d8de5e4

Change-Id: Id4839f41b6a620d8bae58dcf1710016671cc4992
git-subtree-dir: third_party/ntcore_2016
git-subtree-split: d8de5e4f19e612e7102172c0dbf152ce82d3d63a
diff --git a/include/nt_Value.h b/include/nt_Value.h
new file mode 100644
index 0000000..a45e180
--- /dev/null
+++ b/include/nt_Value.h
@@ -0,0 +1,181 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2015. 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.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#ifndef NT_VALUE_H_
+#define NT_VALUE_H_
+
+#include <cassert>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "llvm/ArrayRef.h"
+#include "llvm/StringRef.h"
+
+#include "ntcore_c.h"
+
+namespace nt {
+
+using llvm::ArrayRef;
+using llvm::StringRef;
+
+/** NetworkTables Entry Value */
+class Value {
+  struct private_init {};
+
+ public:
+  Value();
+  Value(NT_Type type, const private_init&);
+  ~Value();
+
+  NT_Type type() const { return m_val.type; }
+  const NT_Value& value() const { return m_val; }
+  unsigned long long last_change() const { return m_val.last_change; }
+
+  /*
+   * Type Checkers
+   */
+  bool IsBoolean() const { return m_val.type == NT_BOOLEAN; }
+  bool IsDouble() const { return m_val.type == NT_DOUBLE; }
+  bool IsString() const { return m_val.type == NT_STRING; }
+  bool IsRaw() const { return m_val.type == NT_RAW; }
+  bool IsRpc() const { return m_val.type == NT_RPC; }
+  bool IsBooleanArray() const { return m_val.type == NT_BOOLEAN_ARRAY; }
+  bool IsDoubleArray() const { return m_val.type == NT_DOUBLE_ARRAY; }
+  bool IsStringArray() const { return m_val.type == NT_STRING_ARRAY; }
+
+  /*
+   * Type-Safe Getters
+   */
+  bool GetBoolean() const {
+    assert(m_val.type == NT_BOOLEAN);
+    return m_val.data.v_boolean != 0;
+  }
+  double GetDouble() const {
+    assert(m_val.type == NT_DOUBLE);
+    return m_val.data.v_double;
+  }
+  StringRef GetString() const {
+    assert(m_val.type == NT_STRING);
+    return m_string;
+  }
+  StringRef GetRaw() const {
+    assert(m_val.type == NT_RAW);
+    return m_string;
+  }
+  StringRef GetRpc() const {
+    assert(m_val.type == NT_RPC);
+    return m_string;
+  }
+  ArrayRef<int> GetBooleanArray() const {
+    assert(m_val.type == NT_BOOLEAN_ARRAY);
+    return ArrayRef<int>(m_val.data.arr_boolean.arr,
+                         m_val.data.arr_boolean.size);
+  }
+  ArrayRef<double> GetDoubleArray() const {
+    assert(m_val.type == NT_DOUBLE_ARRAY);
+    return ArrayRef<double>(m_val.data.arr_double.arr,
+                            m_val.data.arr_double.size);
+  }
+  ArrayRef<std::string> GetStringArray() const {
+    assert(m_val.type == NT_STRING_ARRAY);
+    return m_string_array;
+  }
+
+  static std::shared_ptr<Value> MakeBoolean(bool value) {
+    auto val = std::make_shared<Value>(NT_BOOLEAN, private_init());
+    val->m_val.data.v_boolean = value;
+    return val;
+  }
+  static std::shared_ptr<Value> MakeDouble(double value) {
+    auto val = std::make_shared<Value>(NT_DOUBLE, private_init());
+    val->m_val.data.v_double = value;
+    return val;
+  }
+  static std::shared_ptr<Value> MakeString(StringRef value) {
+    auto val = std::make_shared<Value>(NT_STRING, private_init());
+    val->m_string = value;
+    val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_string.len = val->m_string.size();
+    return val;
+  }
+#ifdef _MSC_VER
+  template <typename T, typename = std::enable_if_t<std::is_same<T, std::string>>>
+#else
+  template <typename T,
+            typename std::enable_if<std::is_same<T, std::string>::value>::type>
+#endif
+  static std::shared_ptr<Value> MakeString(T&& value) {
+    auto val = std::make_shared<Value>(NT_STRING, private_init());
+    val->m_string = std::move(value);
+    val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_string.len = val->m_string.size();
+    return val;
+  }
+  static std::shared_ptr<Value> MakeRaw(StringRef value) {
+    auto val = std::make_shared<Value>(NT_RAW, private_init());
+    val->m_string = value;
+    val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_raw.len = val->m_string.size();
+    return val;
+  }
+#ifdef _MSC_VER
+  template <typename T, typename = std::enable_if_t<std::is_same<T, std::string>>>
+#else
+  template <typename T,
+            typename std::enable_if<std::is_same<T, std::string>::value>::type>
+#endif
+  static std::shared_ptr<Value> MakeRaw(T&& value) {
+    auto val = std::make_shared<Value>(NT_RAW, private_init());
+    val->m_string = std::move(value);
+    val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_raw.len = val->m_string.size();
+    return val;
+  }
+  static std::shared_ptr<Value> MakeRpc(StringRef value) {
+    auto val = std::make_shared<Value>(NT_RPC, private_init());
+    val->m_string = value;
+    val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_raw.len = val->m_string.size();
+    return val;
+  }
+  template <typename T>
+  static std::shared_ptr<Value> MakeRpc(T&& value) {
+    auto val = std::make_shared<Value>(NT_RPC, private_init());
+    val->m_string = std::move(value);
+    val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
+    val->m_val.data.v_raw.len = val->m_string.size();
+    return val;
+  }
+
+  static std::shared_ptr<Value> MakeBooleanArray(ArrayRef<int> value);
+  static std::shared_ptr<Value> MakeDoubleArray(ArrayRef<double> value);
+  static std::shared_ptr<Value> MakeStringArray(ArrayRef<std::string> value);
+
+  // Note: This function moves the values out of the vector.
+  static std::shared_ptr<Value> MakeStringArray(
+      std::vector<std::string>&& value);
+
+  Value(const Value&) = delete;
+  Value& operator=(const Value&) = delete;
+  friend bool operator==(const Value& lhs, const Value& rhs);
+
+ private:
+  NT_Value m_val;
+  std::string m_string;
+  std::vector<std::string> m_string_array;
+};
+
+bool operator==(const Value& lhs, const Value& rhs);
+inline bool operator!=(const Value& lhs, const Value& rhs) {
+  return !(lhs == rhs);
+}
+
+}  // namespace nt
+
+#endif  // NT_VALUE_H_