blob: 8095fa9dffa8a1607ef018ce77e92bdfa8142fb7 [file] [log] [blame]
Brian Silvermanf7bd1c22015-12-24 16:07:11 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2015. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "nt_Value.h"
9#include "Value_internal.h"
10#include "support/timestamp.h"
11
12using namespace nt;
13
14Value::Value() {
15 m_val.type = NT_UNASSIGNED;
16 m_val.last_change = Now();
17}
18
19Value::Value(NT_Type type, const private_init&) {
20 m_val.type = type;
21 m_val.last_change = Now();
22 if (m_val.type == NT_BOOLEAN_ARRAY)
23 m_val.data.arr_boolean.arr = nullptr;
24 else if (m_val.type == NT_DOUBLE_ARRAY)
25 m_val.data.arr_double.arr = nullptr;
26 else if (m_val.type == NT_STRING_ARRAY)
27 m_val.data.arr_string.arr = nullptr;
28}
29
30Value::~Value() {
31 if (m_val.type == NT_BOOLEAN_ARRAY)
32 delete[] m_val.data.arr_boolean.arr;
33 else if (m_val.type == NT_DOUBLE_ARRAY)
34 delete[] m_val.data.arr_double.arr;
35 else if (m_val.type == NT_STRING_ARRAY)
36 delete[] m_val.data.arr_string.arr;
37}
38
39std::shared_ptr<Value> Value::MakeBooleanArray(llvm::ArrayRef<int> value) {
40 auto val = std::make_shared<Value>(NT_BOOLEAN_ARRAY, private_init());
41 val->m_val.data.arr_boolean.arr = new int[value.size()];
42 val->m_val.data.arr_boolean.size = value.size();
43 std::copy(value.begin(), value.end(), val->m_val.data.arr_boolean.arr);
44 return val;
45}
46
47std::shared_ptr<Value> Value::MakeDoubleArray(llvm::ArrayRef<double> value) {
48 auto val = std::make_shared<Value>(NT_DOUBLE_ARRAY, private_init());
49 val->m_val.data.arr_double.arr = new double[value.size()];
50 val->m_val.data.arr_double.size = value.size();
51 std::copy(value.begin(), value.end(), val->m_val.data.arr_double.arr);
52 return val;
53}
54
55std::shared_ptr<Value> Value::MakeStringArray(
56 llvm::ArrayRef<std::string> value) {
57 auto val = std::make_shared<Value>(NT_STRING_ARRAY, private_init());
58 val->m_string_array = value;
59 // point NT_Value to the contents in the vector.
60 val->m_val.data.arr_string.arr = new NT_String[value.size()];
61 val->m_val.data.arr_string.size = val->m_string_array.size();
62 for (std::size_t i=0; i<value.size(); ++i) {
63 val->m_val.data.arr_string.arr[i].str = const_cast<char*>(value[i].c_str());
64 val->m_val.data.arr_string.arr[i].len = value[i].size();
65 }
66 return val;
67}
68
69std::shared_ptr<Value> Value::MakeStringArray(
70 std::vector<std::string>&& value) {
71 auto val = std::make_shared<Value>(NT_STRING_ARRAY, private_init());
72 val->m_string_array = std::move(value);
73 value.clear();
74 // point NT_Value to the contents in the vector.
75 val->m_val.data.arr_string.arr = new NT_String[val->m_string_array.size()];
76 val->m_val.data.arr_string.size = val->m_string_array.size();
77 for (std::size_t i=0; i<val->m_string_array.size(); ++i) {
78 val->m_val.data.arr_string.arr[i].str =
79 const_cast<char*>(val->m_string_array[i].c_str());
80 val->m_val.data.arr_string.arr[i].len = val->m_string_array[i].size();
81 }
82 return val;
83}
84
85void nt::ConvertToC(const Value& in, NT_Value* out) {
86 out->type = NT_UNASSIGNED;
87 switch (in.type()) {
88 case NT_UNASSIGNED:
89 return;
90 case NT_BOOLEAN:
91 out->data.v_boolean = in.GetBoolean() ? 1 : 0;
92 break;
93 case NT_DOUBLE:
94 out->data.v_double = in.GetDouble();
95 break;
96 case NT_STRING:
97 ConvertToC(in.GetString(), &out->data.v_string);
98 break;
99 case NT_RAW:
100 ConvertToC(in.GetRaw(), &out->data.v_raw);
101 break;
102 case NT_RPC:
103 ConvertToC(in.GetRpc(), &out->data.v_raw);
104 break;
105 case NT_BOOLEAN_ARRAY: {
106 auto v = in.GetBooleanArray();
107 out->data.arr_boolean.arr =
108 static_cast<int*>(std::malloc(v.size() * sizeof(int)));
109 out->data.arr_boolean.size = v.size();
110 std::copy(v.begin(), v.end(), out->data.arr_boolean.arr);
111 break;
112 }
113 case NT_DOUBLE_ARRAY: {
114 auto v = in.GetDoubleArray();
115 out->data.arr_double.arr =
116 static_cast<double*>(std::malloc(v.size() * sizeof(double)));
117 out->data.arr_double.size = v.size();
118 std::copy(v.begin(), v.end(), out->data.arr_double.arr);
119 break;
120 }
121 case NT_STRING_ARRAY: {
122 auto v = in.GetStringArray();
123 out->data.arr_string.arr =
124 static_cast<NT_String*>(std::malloc(v.size()*sizeof(NT_String)));
125 for (size_t i = 0; i < v.size(); ++i)
126 ConvertToC(v[i], &out->data.arr_string.arr[i]);
127 out->data.arr_string.size = v.size();
128 break;
129 }
130 default:
131 // assert(false && "unknown value type");
132 return;
133 }
134 out->type = in.type();
135}
136
137void nt::ConvertToC(llvm::StringRef in, NT_String* out) {
138 out->len = in.size();
139 out->str = static_cast<char*>(std::malloc(in.size()+1));
140 std::memcpy(out->str, in.data(), in.size());
141 out->str[in.size()] = '\0';
142}
143
144std::shared_ptr<Value> nt::ConvertFromC(const NT_Value& value) {
145 switch (value.type) {
146 case NT_UNASSIGNED:
147 return nullptr;
148 case NT_BOOLEAN:
149 return Value::MakeBoolean(value.data.v_boolean != 0);
150 case NT_DOUBLE:
151 return Value::MakeDouble(value.data.v_double);
152 case NT_STRING:
153 return Value::MakeString(ConvertFromC(value.data.v_string));
154 case NT_RAW:
155 return Value::MakeRaw(ConvertFromC(value.data.v_raw));
156 case NT_RPC:
157 return Value::MakeRpc(ConvertFromC(value.data.v_raw));
158 case NT_BOOLEAN_ARRAY:
159 return Value::MakeBooleanArray(llvm::ArrayRef<int>(
160 value.data.arr_boolean.arr, value.data.arr_boolean.size));
161 case NT_DOUBLE_ARRAY:
162 return Value::MakeDoubleArray(llvm::ArrayRef<double>(
163 value.data.arr_double.arr, value.data.arr_double.size));
164 case NT_STRING_ARRAY: {
165 std::vector<std::string> v;
166 v.reserve(value.data.arr_string.size);
167 for (size_t i=0; i<value.data.arr_string.size; ++i)
168 v.push_back(ConvertFromC(value.data.arr_string.arr[i]));
169 return Value::MakeStringArray(std::move(v));
170 }
171 default:
172 // assert(false && "unknown value type");
173 return nullptr;
174 }
175}
176
177bool nt::operator==(const Value& lhs, const Value& rhs) {
178 if (lhs.type() != rhs.type()) return false;
179 switch (lhs.type()) {
180 case NT_UNASSIGNED:
181 return true; // XXX: is this better being false instead?
182 case NT_BOOLEAN:
183 return lhs.m_val.data.v_boolean == rhs.m_val.data.v_boolean;
184 case NT_DOUBLE:
185 return lhs.m_val.data.v_double == rhs.m_val.data.v_double;
186 case NT_STRING:
187 case NT_RAW:
188 case NT_RPC:
189 return lhs.m_string == rhs.m_string;
190 case NT_BOOLEAN_ARRAY:
191 if (lhs.m_val.data.arr_boolean.size != rhs.m_val.data.arr_boolean.size)
192 return false;
193 return std::memcmp(lhs.m_val.data.arr_boolean.arr,
194 rhs.m_val.data.arr_boolean.arr,
195 lhs.m_val.data.arr_boolean.size *
196 sizeof(lhs.m_val.data.arr_boolean.arr[0])) == 0;
197 case NT_DOUBLE_ARRAY:
198 if (lhs.m_val.data.arr_double.size != rhs.m_val.data.arr_double.size)
199 return false;
200 return std::memcmp(lhs.m_val.data.arr_double.arr,
201 rhs.m_val.data.arr_double.arr,
202 lhs.m_val.data.arr_double.size *
203 sizeof(lhs.m_val.data.arr_double.arr[0])) == 0;
204 case NT_STRING_ARRAY:
205 return lhs.m_string_array == rhs.m_string_array;
206 default:
207 // assert(false && "unknown value type");
208 return false;
209 }
210}