client-cpp  0.6.3
AvroDatumsComparator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 CyberVision, 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 AVRODATUMSCOMPARATOR_HPP_
18 #define AVRODATUMSCOMPARATOR_HPP_
19 
20 #include "kaa/KaaDefaults.hpp"
21 
22 #ifdef KAA_USE_CONFIGURATION
23 
24 #include <avro/Generic.hh>
25 #include <cstdint>
26 
28 
29 namespace kaa {
30 
31 struct avro_comparator {
32 
33 bool operator ()(const avro::GenericDatum &left, const avro::GenericDatum &right)
34 {
35  return compareDatumsLess(left, right);
36 }
37 
38 private:
39 
40 bool compareDatumsLess(const avro::GenericDatum &left, const avro::GenericDatum &right)
41 {
42  int ltype = left.type(), rtype = right.type();
43  if (ltype != rtype) {
44  if (avro::Type::AVRO_RECORD > avro::Type::AVRO_STRING) {
45  if (ltype < avro::Type::AVRO_RECORD) {
46  ltype += avro::Type::AVRO_RECORD;
47  } else {
48  ltype -= avro::Type::AVRO_RECORD;
49  }
50 
51  if (rtype < avro::Type::AVRO_RECORD) {
52  rtype += avro::Type::AVRO_RECORD;
53  } else {
54  rtype -= avro::Type::AVRO_RECORD;
55  }
56  }
57 
58  return ltype < rtype;
59  }
60  avro::Type type = left.type();
61  switch (type) {
62  case avro::Type::AVRO_STRING:
63  return std::less<std::string>()(left.value<std::string>(), right.value<std::string>());
64  case avro::Type::AVRO_INT:
65  return std::less<std::int32_t>()(left.value<std::int32_t>(), right.value<std::int32_t>());
66  case avro::Type::AVRO_LONG:
67  return std::less<std::int64_t>()(left.value<std::int64_t>(), right.value<std::int64_t>());
68  case avro::Type::AVRO_FLOAT:
69  return std::less<float>()(left.value<float>(), right.value<float>());
70  case avro::Type::AVRO_DOUBLE:
71  return std::less<double>()(left.value<double>(), right.value<double>());
72  case avro::Type::AVRO_BOOL:
73  return std::less<bool>()(left.value<bool>(), right.value<bool>());
74  case avro::Type::AVRO_BYTES: {
75  std::vector<std::uint8_t> l_vec = left.value<std::vector<std::uint8_t> >();
76  std::vector<std::uint8_t> r_vec = right.value<std::vector<std::uint8_t> >();
77  return std::less<std::vector<std::uint8_t> >()(l_vec, r_vec);
78  }
79 
80  case avro::Type::AVRO_RECORD: {
81  const avro::GenericRecord &leftRecord = left.value<avro::GenericRecord>();
82  const avro::GenericRecord &rightRecord = right.value<avro::GenericRecord>();
83 
84  size_t leftFieldCount = leftRecord.schema()->names();
85  size_t rightFieldCount = rightRecord.schema()->names();
86  if (leftFieldCount != rightFieldCount) {
87  throw KaaException("Can not compare records with different count of fields");
88  }
89 
90  for (size_t l = 0; l < leftFieldCount; ++l) {
91  std::string fieldName = leftRecord.schema()->nameAt(l);
92  bool isLess = compareDatumsLess(leftRecord.field(fieldName), rightRecord.field(fieldName));
93  if ( !(!isLess && !compareDatumsLess(rightRecord.field(fieldName), leftRecord.field(fieldName)))) {
94  return isLess;
95  }
96  }
97  return false;
98  }
99  case avro::Type::AVRO_ENUM: {
100  return left.value<avro::GenericEnum>().value() < right.value<avro::GenericEnum>().value();
101  }
102  case avro::Type::AVRO_ARRAY: {
103  const avro::GenericArray &leftArray = left.value<avro::GenericArray>();
104  const avro::GenericArray &rightArray = right.value<avro::GenericArray>();
105  const avro::GenericArray::Value l_value = leftArray.value();
106  const avro::GenericArray::Value r_value = rightArray.value();
107  for (size_t l = 0, r = 0; l < l_value.size() && r < r_value.size(); ++l, ++r) {
108  bool isLess = compareDatumsLess(l_value[l], r_value[r]);
109  if (!(!isLess && !compareDatumsLess(r_value[r], l_value[l]))) {
110  return isLess;
111  }
112  }
113  return l_value.size() > r_value.size();
114  }
115 
116  case avro::Type::AVRO_FIXED: {
117  std::vector<std::uint8_t> l_vec = left.value<avro::GenericFixed>().value();
118  std::vector<std::uint8_t> r_vec = right.value<avro::GenericFixed>().value();
119  return std::less<std::vector<std::uint8_t> >()(l_vec, r_vec);
120  }
121 
122  case avro::Type::AVRO_NULL:
123  return false;
124 
125  case avro::Type::AVRO_MAP:
126  case avro::Type::AVRO_UNION:
127  default:
128  throw KaaException(boost::format("Can not compare datums of \"%1%\" type") % avro::toString(type));
129  }
130 }
131 
132 };
133 
134 } // namespace kaa
135 
136 #endif
137 
138 #endif /* AVRODATUMSCOMPARATOR_HPP_ */