1 /*
2 Copyright (c) DataStax, Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #include "value.hpp"
18
19 #include "collection_iterator.hpp"
20 #include "data_type.hpp"
21 #include "external.hpp"
22 #include "serialization.hpp"
23
24 #define CHECK_RESULT(result) \
25 if (!(result)) return false;
26 #define CHECK_VALUE(result) \
27 do { \
28 if ((result)) { \
29 return CASS_OK; \
30 } else { \
31 return CASS_ERROR_LIB_NOT_ENOUGH_DATA; \
32 } \
33 } while (0)
34
35 using namespace datastax;
36 using namespace datastax::internal;
37 using namespace datastax::internal::core;
38
39 extern "C" {
40
cass_value_data_type(const CassValue * value)41 const CassDataType* cass_value_data_type(const CassValue* value) {
42 return CassDataType::to(value->data_type().get());
43 }
44
cass_value_get_int8(const CassValue * value,cass_int8_t * output)45 CassError cass_value_get_int8(const CassValue* value, cass_int8_t* output) {
46 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
47 if (value->value_type() != CASS_VALUE_TYPE_TINY_INT) {
48 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
49 }
50 CHECK_VALUE(value->decoder().as_int8(output));
51 }
52
cass_value_get_int16(const CassValue * value,cass_int16_t * output)53 CassError cass_value_get_int16(const CassValue* value, cass_int16_t* output) {
54 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
55 if (value->value_type() != CASS_VALUE_TYPE_SMALL_INT) {
56 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
57 }
58 CHECK_VALUE(value->decoder().as_int16(output));
59 }
60
cass_value_get_int32(const CassValue * value,cass_int32_t * output)61 CassError cass_value_get_int32(const CassValue* value, cass_int32_t* output) {
62 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
63 if (value->value_type() != CASS_VALUE_TYPE_INT) {
64 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
65 }
66 CHECK_VALUE(value->decoder().as_int32(output));
67 }
68
cass_value_get_uint32(const CassValue * value,cass_uint32_t * output)69 CassError cass_value_get_uint32(const CassValue* value, cass_uint32_t* output) {
70 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
71 if (value->value_type() != CASS_VALUE_TYPE_DATE) {
72 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
73 }
74 CHECK_VALUE(value->decoder().as_uint32(output));
75 }
76
cass_value_get_int64(const CassValue * value,cass_int64_t * output)77 CassError cass_value_get_int64(const CassValue* value, cass_int64_t* output) {
78 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
79 if (!is_int64_type(value->value_type())) {
80 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
81 }
82 CHECK_VALUE(value->decoder().as_int64(output));
83 }
84
cass_value_get_float(const CassValue * value,cass_float_t * output)85 CassError cass_value_get_float(const CassValue* value, cass_float_t* output) {
86 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
87 if (value->value_type() != CASS_VALUE_TYPE_FLOAT) {
88 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
89 }
90 CHECK_VALUE(value->decoder().as_float(output));
91 }
92
cass_value_get_double(const CassValue * value,cass_double_t * output)93 CassError cass_value_get_double(const CassValue* value, cass_double_t* output) {
94 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
95 if (value->value_type() != CASS_VALUE_TYPE_DOUBLE) {
96 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
97 }
98 CHECK_VALUE(value->decoder().as_double(output));
99 }
100
cass_value_get_bool(const CassValue * value,cass_bool_t * output)101 CassError cass_value_get_bool(const CassValue* value, cass_bool_t* output) {
102 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
103 if (value->value_type() != CASS_VALUE_TYPE_BOOLEAN) {
104 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
105 }
106 bool decode_value = false;
107 if (!value->decoder().as_bool(&decode_value)) {
108 return CASS_ERROR_LIB_NOT_ENOUGH_DATA;
109 }
110 *output = decode_value ? cass_true : cass_false;
111 return CASS_OK;
112 }
113
cass_value_get_uuid(const CassValue * value,CassUuid * output)114 CassError cass_value_get_uuid(const CassValue* value, CassUuid* output) {
115 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
116 if (!is_uuid_type(value->value_type())) {
117 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
118 }
119 CHECK_VALUE(value->decoder().as_uuid(output));
120 }
121
cass_value_get_inet(const CassValue * value,CassInet * output)122 CassError cass_value_get_inet(const CassValue* value, CassInet* output) {
123 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
124 if (value->value_type() != CASS_VALUE_TYPE_INET) {
125 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
126 }
127 if (!value->decoder().as_inet(value->size(), output)) {
128 return CASS_ERROR_LIB_INVALID_DATA;
129 }
130 return CASS_OK;
131 }
132
cass_value_get_string(const CassValue * value,const char ** output,size_t * output_length)133 CassError cass_value_get_string(const CassValue* value, const char** output,
134 size_t* output_length) {
135 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
136 StringRef buffer = value->decoder().as_string_ref();
137 *output = buffer.data();
138 *output_length = buffer.size();
139 return CASS_OK;
140 }
141
cass_value_get_bytes(const CassValue * value,const cass_byte_t ** output,size_t * output_size)142 CassError cass_value_get_bytes(const CassValue* value, const cass_byte_t** output,
143 size_t* output_size) {
144 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
145 StringRef buffer = value->decoder().as_string_ref();
146 *output = reinterpret_cast<const cass_byte_t*>(buffer.data());
147 *output_size = buffer.size();
148 return CASS_OK;
149 }
150
cass_value_get_duration(const CassValue * value,cass_int32_t * months,cass_int32_t * days,cass_int64_t * nanos)151 CassError cass_value_get_duration(const CassValue* value, cass_int32_t* months, cass_int32_t* days,
152 cass_int64_t* nanos) {
153 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
154 if (!cass_value_is_duration(value)) return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
155 CHECK_VALUE(value->decoder().as_duration(months, days, nanos));
156 }
157
cass_value_get_decimal(const CassValue * value,const cass_byte_t ** varint,size_t * varint_size,cass_int32_t * scale)158 CassError cass_value_get_decimal(const CassValue* value, const cass_byte_t** varint,
159 size_t* varint_size, cass_int32_t* scale) {
160 if (value == NULL || value->is_null()) return CASS_ERROR_LIB_NULL_VALUE;
161 if (value->value_type() != CASS_VALUE_TYPE_DECIMAL) {
162 return CASS_ERROR_LIB_INVALID_VALUE_TYPE;
163 }
164 CHECK_VALUE(value->decoder().as_decimal(varint, varint_size, scale));
165 }
166
cass_value_type(const CassValue * value)167 CassValueType cass_value_type(const CassValue* value) { return value->value_type(); }
168
cass_value_is_null(const CassValue * value)169 cass_bool_t cass_value_is_null(const CassValue* value) {
170 return static_cast<cass_bool_t>(value->is_null());
171 }
172
cass_value_is_collection(const CassValue * value)173 cass_bool_t cass_value_is_collection(const CassValue* value) {
174 return static_cast<cass_bool_t>(value->is_collection());
175 }
176
cass_value_is_duration(const CassValue * value)177 cass_bool_t cass_value_is_duration(const CassValue* value) {
178 IsValidDataType<CassDuration> is_valid;
179 CassDuration dummy(0, 0, 0);
180 return static_cast<cass_bool_t>(is_valid(dummy, value->data_type()));
181 }
182
cass_value_item_count(const CassValue * collection)183 size_t cass_value_item_count(const CassValue* collection) { return collection->count(); }
184
cass_value_primary_sub_type(const CassValue * collection)185 CassValueType cass_value_primary_sub_type(const CassValue* collection) {
186 return collection->primary_value_type();
187 }
188
cass_value_secondary_sub_type(const CassValue * collection)189 CassValueType cass_value_secondary_sub_type(const CassValue* collection) {
190 return collection->secondary_value_type();
191 }
192
193 } // extern "C"
194
Value(const DataType::ConstPtr & data_type,Decoder decoder)195 Value::Value(const DataType::ConstPtr& data_type, Decoder decoder)
196 : data_type_(data_type)
197 , count_(0)
198 , decoder_(decoder)
199 , is_null_(false) {
200 assert(!data_type->is_collection());
201 if (data_type->is_tuple()) {
202 SharedRefPtr<const CompositeType> composite_type(data_type);
203 count_ = composite_type->types().size();
204 } else if (data_type->is_user_type()) {
205 UserType::ConstPtr user_type(data_type);
206 count_ = user_type->fields().size();
207 } else {
208 count_ = 0;
209 }
210 }
211
as_bool() const212 bool Value::as_bool() const {
213 assert(!is_null() && value_type() == CASS_VALUE_TYPE_BOOLEAN);
214 bool value = false;
215 bool result = decoder_.as_bool(&value);
216 UNUSED_(result);
217 assert(result);
218 return value;
219 }
220
as_int32() const221 int32_t Value::as_int32() const {
222 assert(!is_null() && value_type() == CASS_VALUE_TYPE_INT);
223 int32_t value = 0;
224 bool result = decoder_.as_int32(&value);
225 UNUSED_(result);
226 assert(result);
227 return value;
228 }
229
as_uuid() const230 CassUuid Value::as_uuid() const {
231 assert(!is_null() &&
232 (value_type() == CASS_VALUE_TYPE_UUID || value_type() == CASS_VALUE_TYPE_TIMEUUID));
233 CassUuid value = { 0, 0 };
234 bool result = decoder_.as_uuid(&value);
235 UNUSED_(result);
236 assert(result);
237 return value;
238 }
239
as_stringlist() const240 StringVec Value::as_stringlist() const {
241 assert(!is_null() &&
242 (value_type() == CASS_VALUE_TYPE_LIST || value_type() == CASS_VALUE_TYPE_SET) &&
243 primary_value_type() == CASS_VALUE_TYPE_VARCHAR);
244 StringVec stringlist;
245 CollectionIterator iterator(this);
246 while (iterator.next()) {
247 stringlist.push_back(iterator.value()->to_string());
248 }
249 return stringlist;
250 }
251