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 #ifndef __TEST_SET_HPP__
18 #define __TEST_SET_HPP__
19 #include "nullable_value.hpp"
20 #include "test_utils.hpp"
21
22 namespace test { namespace driver {
23
24 /**
25 * Set wrapped value
26 */
27 template <typename T>
28 class Set
29 : public Collection
30 , Comparable<Set<T> > {
31 public:
Set()32 Set()
33 : Collection(CASS_COLLECTION_TYPE_SET) {}
34
Set(const std::set<T> & set)35 Set(const std::set<T>& set)
36 : Collection(CASS_COLLECTION_TYPE_SET, set.size())
37 , set_(set) {
38 // Create the collection
39 for (typename std::set<T>::const_iterator iterator = set.begin(); iterator != set.end();
40 ++iterator) {
41 T value = *iterator;
42 Collection::append<T>(value);
43 set_.insert(value);
44 primary_sub_type_ = value.value_type();
45 secondary_sub_type_ = primary_sub_type_;
46 }
47 }
48
Set(const std::vector<T> & set)49 Set(const std::vector<T>& set)
50 : Collection(CASS_COLLECTION_TYPE_SET, set.size()) {
51 // Create the collection
52 for (typename std::vector<T>::const_iterator iterator = set.begin(); iterator < set.end();
53 ++iterator) {
54 T value = *iterator;
55 Collection::append<T>(value);
56 set_.insert(value);
57 primary_sub_type_ = value.value_type();
58 secondary_sub_type_ = primary_sub_type_;
59 }
60 }
61
Set(const CassValue * value)62 Set(const CassValue* value)
63 : Collection(CASS_COLLECTION_TYPE_SET) {
64 initialize(value);
65 }
66
append(Collection collection)67 void append(Collection collection) { Collection::append(collection); }
68
cql_type() const69 std::string cql_type() const {
70 std::string cql_type = "set<" + (*set_.begin()).cql_type() + ">";
71 return cql_type;
72 }
73
cql_value() const74 std::string cql_value() const { return str(); }
75
is_null() const76 bool is_null() const { return Collection::is_null_; }
77
78 /**
79 * Comparison operation for driver value set. This comparison is performed in
80 * lexicographical order.
81 *
82 * @param rhs Right hand side to compare
83 * @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
84 */
compare(const std::set<T> & rhs) const85 int compare(const std::set<T>& rhs) const {
86 // Ensure they are the same size
87 if (set_.size() < rhs.size()) return -1;
88 if (set_.size() > rhs.size()) return 1;
89
90 // Iterate and compare (sets are already sorted)
91 typename std::set<T>::const_iterator rhs_iterator = rhs.begin();
92 for (typename std::set<T>::const_iterator iterator = set_.begin(); iterator != set_.end();
93 ++iterator) {
94 int comparison = (*iterator).compare(*rhs_iterator);
95 if (comparison != 0) return comparison;
96 ++rhs_iterator;
97 }
98 return 0;
99 }
100
101 /**
102 * Comparison operation for driver value set. This comparison is performed in
103 * lexicographical order.
104 *
105 * @param rhs Right hand side to compare
106 * @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
107 */
compare(const Set & rhs) const108 int compare(const Set& rhs) const { return compare(rhs.set_); }
109
set(Tuple tuple,size_t index)110 void set(Tuple tuple, size_t index) { Collection::set(tuple, index); }
111
set(UserType user_type,const std::string & name)112 void set(UserType user_type, const std::string& name) { Collection::set(user_type, name); }
113
114 /**
115 * Get the size of the set
116 *
117 * @return The number of values in the set
118 */
size() const119 size_t size() const { return set_.size(); }
120
statement_bind(Statement statement,size_t index)121 void statement_bind(Statement statement, size_t index) {
122 if (is_null()) {
123 ASSERT_EQ(CASS_OK, cass_statement_bind_null(statement.get(), index));
124 } else {
125 ASSERT_EQ(CASS_OK, cass_statement_bind_collection(statement.get(), index, get()));
126 }
127 }
128
statement_bind(Statement statement,const std::string & name)129 void statement_bind(Statement statement, const std::string& name) {
130 if (is_null()) {
131 ASSERT_EQ(CASS_OK, cass_statement_bind_null_by_name(statement.get(), name.c_str()));
132 } else {
133 ASSERT_EQ(CASS_OK,
134 cass_statement_bind_collection_by_name(statement.get(), name.c_str(), get()));
135 }
136 }
137
str() const138 std::string str() const {
139 if (is_null()) {
140 return "null";
141 } else if (set_.empty()) {
142 return "{}";
143 } else {
144 std::stringstream set_string;
145 set_string << "{";
146 for (typename std::set<T>::const_iterator iterator = set_.begin(); iterator != set_.end();
147 ++iterator) {
148 set_string << (*iterator).cql_value();
149
150 // Add a comma separation to the set (unless the last element)
151 if (iterator != --set_.end()) {
152 set_string << ", ";
153 }
154 }
155 set_string << "}";
156 return set_string.str();
157 }
158 }
159
value() const160 std::set<T> value() const { return set_; }
161
collection_type() const162 CassCollectionType collection_type() const { return collection_type_; }
163
value_type() const164 CassValueType value_type() const { return primary_sub_type_; }
165
166 private:
167 /**
168 * Values used in the set
169 */
170 std::set<T> set_;
171
initialize(const CassValue * value)172 void initialize(const CassValue* value) {
173 // Call the parent class
174 Collection::initialize(value);
175
176 // Add the values to the set
177 if (!is_null_) {
178 const CassValue* current_value = next();
179 while (current_value) {
180 set_.insert(T(current_value));
181 current_value = next();
182 }
183 }
184 }
185 };
186
187 template <class T>
operator <<(std::ostream & os,const Set<T> & set)188 inline std::ostream& operator<<(std::ostream& os, const Set<T>& set) {
189 os << set.cql_value();
190 return os;
191 }
192
193 }} // namespace test::driver
194
195 #endif // __TEST_SET_HPP__
196