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 "collection.hpp"
18
19 #include "constants.hpp"
20 #include "external.hpp"
21 #include "macros.hpp"
22 #include "tuple.hpp"
23 #include "user_type_value.hpp"
24
25 #include <string.h>
26
27 using namespace datastax;
28 using namespace datastax::internal::core;
29
30 extern "C" {
31
cass_collection_new(CassCollectionType type,size_t item_count)32 CassCollection* cass_collection_new(CassCollectionType type, size_t item_count) {
33 Collection* collection = new Collection(type, item_count);
34 collection->inc_ref();
35 return CassCollection::to(collection);
36 }
37
cass_collection_new_from_data_type(const CassDataType * data_type,size_t item_count)38 CassCollection* cass_collection_new_from_data_type(const CassDataType* data_type,
39 size_t item_count) {
40 if (!data_type->is_collection()) {
41 return NULL;
42 }
43 Collection* collection = new Collection(DataType::ConstPtr(data_type), item_count);
44 collection->inc_ref();
45 return CassCollection::to(collection);
46 }
47
cass_collection_free(CassCollection * collection)48 void cass_collection_free(CassCollection* collection) { collection->dec_ref(); }
49
cass_collection_data_type(const CassCollection * collection)50 const CassDataType* cass_collection_data_type(const CassCollection* collection) {
51 return CassDataType::to(collection->data_type().get());
52 }
53
54 #define CASS_COLLECTION_APPEND(Name, Params, Value) \
55 CassError cass_collection_append_##Name(CassCollection* collection Params) { \
56 return collection->append(Value); \
57 }
58
CASS_COLLECTION_APPEND(null,ZERO_PARAMS_ (),CassNull ())59 CASS_COLLECTION_APPEND(null, ZERO_PARAMS_(), CassNull())
60 CASS_COLLECTION_APPEND(int8, ONE_PARAM_(cass_int8_t value), value)
61 CASS_COLLECTION_APPEND(int16, ONE_PARAM_(cass_int16_t value), value)
62 CASS_COLLECTION_APPEND(int32, ONE_PARAM_(cass_int32_t value), value)
63 CASS_COLLECTION_APPEND(uint32, ONE_PARAM_(cass_uint32_t value), value)
64 CASS_COLLECTION_APPEND(int64, ONE_PARAM_(cass_int64_t value), value)
65 CASS_COLLECTION_APPEND(float, ONE_PARAM_(cass_float_t value), value)
66 CASS_COLLECTION_APPEND(double, ONE_PARAM_(cass_double_t value), value)
67 CASS_COLLECTION_APPEND(bool, ONE_PARAM_(cass_bool_t value), value)
68 CASS_COLLECTION_APPEND(uuid, ONE_PARAM_(CassUuid value), value)
69 CASS_COLLECTION_APPEND(inet, ONE_PARAM_(CassInet value), value)
70 CASS_COLLECTION_APPEND(collection, ONE_PARAM_(const CassCollection* value), value)
71 CASS_COLLECTION_APPEND(tuple, ONE_PARAM_(const CassTuple* value), value)
72 CASS_COLLECTION_APPEND(user_type, ONE_PARAM_(const CassUserType* value), value)
73 CASS_COLLECTION_APPEND(bytes, TWO_PARAMS_(const cass_byte_t* value, size_t value_size),
74 CassBytes(value, value_size))
75 CASS_COLLECTION_APPEND(decimal,
76 THREE_PARAMS_(const cass_byte_t* varint, size_t varint_size, int scale),
77 CassDecimal(varint, varint_size, scale))
78 CASS_COLLECTION_APPEND(duration,
79 THREE_PARAMS_(cass_int32_t months, cass_int32_t days, cass_int64_t nanos),
80 CassDuration(months, days, nanos))
81
82 #undef CASS_COLLECTION_APPEND
83
84 CassError cass_collection_append_string(CassCollection* collection, const char* value) {
85 return collection->append(CassString(value, SAFE_STRLEN(value)));
86 }
87
cass_collection_append_string_n(CassCollection * collection,const char * value,size_t value_length)88 CassError cass_collection_append_string_n(CassCollection* collection, const char* value,
89 size_t value_length) {
90 return collection->append(CassString(value, value_length));
91 }
92
cass_collection_append_custom(CassCollection * collection,const char * class_name,const cass_byte_t * value,size_t value_size)93 CassError cass_collection_append_custom(CassCollection* collection, const char* class_name,
94 const cass_byte_t* value, size_t value_size) {
95 return collection->append(CassCustom(StringRef(class_name), value, value_size));
96 }
97
cass_collection_append_custom_n(CassCollection * collection,const char * class_name,size_t class_name_length,const cass_byte_t * value,size_t value_size)98 CassError cass_collection_append_custom_n(CassCollection* collection, const char* class_name,
99 size_t class_name_length, const cass_byte_t* value,
100 size_t value_size) {
101 return collection->append(
102 CassCustom(StringRef(class_name, class_name_length), value, value_size));
103 }
104
105 } // extern "C"
106
append(CassNull value)107 CassError Collection::append(CassNull value) {
108 CASS_COLLECTION_CHECK_TYPE(value);
109 items_.push_back(Buffer());
110 return CASS_OK;
111 }
112
append(const Collection * value)113 CassError Collection::append(const Collection* value) {
114 CASS_COLLECTION_CHECK_TYPE(value);
115 items_.push_back(value->encode());
116 return CASS_OK;
117 }
118
append(const Tuple * value)119 CassError Collection::append(const Tuple* value) {
120 CASS_COLLECTION_CHECK_TYPE(value);
121 items_.push_back(value->encode());
122 return CASS_OK;
123 }
124
append(const UserTypeValue * value)125 CassError Collection::append(const UserTypeValue* value) {
126 CASS_COLLECTION_CHECK_TYPE(value);
127 items_.push_back(value->encode());
128 return CASS_OK;
129 }
130
get_items_size() const131 size_t Collection::get_items_size() const {
132 size_t size = 0;
133 for (BufferVec::const_iterator i = items_.begin(), end = items_.end(); i != end; ++i) {
134 size += sizeof(int32_t);
135 size += i->size();
136 }
137 return size;
138 }
139
encode_items(char * buf) const140 void Collection::encode_items(char* buf) const {
141 for (BufferVec::const_iterator i = items_.begin(), end = items_.end(); i != end; ++i) {
142 encode_int32(buf, i->size());
143 buf += sizeof(int32_t);
144 memcpy(buf, i->data(), i->size());
145 buf += i->size();
146 }
147 }
148
get_size() const149 size_t Collection::get_size() const { return sizeof(int32_t) + get_items_size(); }
150
get_size_with_length() const151 size_t Collection::get_size_with_length() const { return sizeof(int32_t) + get_size(); }
152
encode() const153 Buffer Collection::encode() const {
154 Buffer buf(get_size());
155 size_t pos = buf.encode_int32(0, get_count());
156 encode_items(buf.data() + pos);
157 return buf;
158 }
159
encode_with_length() const160 Buffer Collection::encode_with_length() const {
161 size_t internal_size = get_size();
162 Buffer buf(sizeof(int32_t) + internal_size);
163 size_t pos = buf.encode_int32(0, internal_size);
164 pos = buf.encode_int32(pos, get_count());
165 encode_items(buf.data() + pos);
166 return buf;
167 }
168