/*----------------------------------------------------------------------------*/ /* 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_