Avro C++
GenericDatum.hh
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * https://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef avro_GenericDatum_hh__
20 #define avro_GenericDatum_hh__
21 
22 #include <stdint.h>
23 #include <vector>
24 #include <map>
25 #include <string>
26 
27 #if __cplusplus >= 201703L
28 #include <any>
29 #else
30 #include "boost/any.hpp"
31 #endif
32 
33 #include "LogicalType.hh"
34 #include "Node.hh"
35 #include "ValidSchema.hh"
36 
37 namespace avro {
38 
61 class AVRO_DECL GenericDatum {
62 protected:
63  Type type_;
64  LogicalType logicalType_;
65 #if __cplusplus >= 201703L
66  std::any value_;
67 #else
68  boost::any value_;
69 #endif
70 
72  : type_(t), logicalType_(LogicalType::NONE) { }
73 
74  GenericDatum(Type t, LogicalType logicalType)
75  : type_(t), logicalType_(logicalType) { }
76 
77  template <typename T>
78  GenericDatum(Type t, LogicalType logicalType, const T& v)
79  : type_(t), logicalType_(logicalType), value_(v) { }
80 
81  void init(const NodePtr& schema);
82 public:
86  Type type() const;
87 
91  LogicalType logicalType() const;
92 
98  template<typename T> const T& value() const;
99 
109  template<typename T> T& value();
110 
114  bool isUnion() const { return type_ == AVRO_UNION; }
115 
120  size_t unionBranch() const;
121 
126  void selectBranch(size_t branch);
127 
129  GenericDatum() : type_(AVRO_NULL), logicalType_(LogicalType::NONE) { }
130 
132  GenericDatum(bool v)
133  : type_(AVRO_BOOL), logicalType_(LogicalType::NONE), value_(v) { }
134 
136  GenericDatum(int32_t v)
137  : type_(AVRO_INT), logicalType_(LogicalType::NONE), value_(v) { }
138 
140  GenericDatum(int64_t v)
141  : type_(AVRO_LONG), logicalType_(LogicalType::NONE), value_(v) { }
142 
144  GenericDatum(float v)
145  : type_(AVRO_FLOAT), logicalType_(LogicalType::NONE), value_(v) { }
146 
148  GenericDatum(double v)
149  : type_(AVRO_DOUBLE), logicalType_(LogicalType::NONE), value_(v) { }
150 
152  GenericDatum(const std::string& v)
153  : type_(AVRO_STRING), logicalType_(LogicalType::NONE), value_(v) { }
154 
157  GenericDatum(const std::vector<uint8_t>& v) :
158  type_(AVRO_BYTES), logicalType_(LogicalType::NONE), value_(v) { }
159 
166  GenericDatum(const NodePtr& schema);
167 
174  template<typename T>
175  GenericDatum(const NodePtr& schema, const T& v) :
176  type_(schema->type()), logicalType_(schema->logicalType()) {
177  init(schema);
178 #if __cplusplus >= 201703L
179  *std::any_cast<T>(&value_) = v;
180 #else
181  *boost::any_cast<T>(&value_) = v;
182 #endif
183  }
184 
191  GenericDatum(const ValidSchema& schema);
192 };
193 
197 class AVRO_DECL GenericContainer {
198  NodePtr schema_;
199  static void assertType(const NodePtr& schema, Type type);
200 protected:
204  GenericContainer(Type type, const NodePtr& s) : schema_(s) {
205  assertType(s, type);
206  }
207 
208 public:
210  const NodePtr& schema() const {
211  return schema_;
212  }
213 };
214 
218 class AVRO_DECL GenericUnion : public GenericContainer {
219  size_t curBranch_;
220  GenericDatum datum_;
221 
222 public:
228  GenericUnion(const NodePtr& schema) :
229  GenericContainer(AVRO_UNION, schema), curBranch_(schema->leaves()) {
230  selectBranch(0);
231  }
232 
236  size_t currentBranch() const { return curBranch_; }
237 
242  void selectBranch(size_t branch) {
243  if (curBranch_ != branch) {
244  datum_ = GenericDatum(schema()->leafAt(branch));
245  curBranch_ = branch;
246  }
247  }
248 
254  return datum_;
255  }
256 
261  const GenericDatum& datum() const {
262  return datum_;
263  }
264 };
265 
269 class AVRO_DECL GenericRecord : public GenericContainer {
270  std::vector<GenericDatum> fields_;
271 public:
276  GenericRecord(const NodePtr& schema);
277 
281  size_t fieldCount() const {
282  return fields_.size();
283  }
284 
288  size_t fieldIndex(const std::string& name) const {
289  size_t index = 0;
290  if (!schema()->nameIndex(name, index)) {
291  throw Exception("Invalid field name: " + name);
292  }
293  return index;
294  }
295 
300  bool hasField(const std::string& name) const {
301  size_t index = 0;
302  return schema()->nameIndex(name, index);
303  }
304 
308  const GenericDatum& field(const std::string& name) const {
309  return fieldAt(fieldIndex(name));
310  }
311 
316  GenericDatum& field(const std::string& name) {
317  return fieldAt(fieldIndex(name));
318  }
319 
323  const GenericDatum& fieldAt(size_t pos) const {
324  return fields_[pos];
325  }
326 
331  GenericDatum& fieldAt(size_t pos) {
332  return fields_[pos];
333  }
334 
338  void setFieldAt(size_t pos, const GenericDatum& v) {
339  // assertSameType(v, schema()->leafAt(pos));
340  fields_[pos] = v;
341  }
342 };
343 
347 class AVRO_DECL GenericArray : public GenericContainer {
348 public:
352  typedef std::vector<GenericDatum> Value;
353 
358  GenericArray(const NodePtr& schema) : GenericContainer(AVRO_ARRAY, schema) {
359  }
360 
364  const Value& value() const {
365  return value_;
366  }
367 
371  Value& value() {
372  return value_;
373  }
374 private:
375  Value value_;
376 };
377 
381 class AVRO_DECL GenericMap : public GenericContainer {
382 public:
386  typedef std::vector<std::pair<std::string, GenericDatum> > Value;
387 
392  GenericMap(const NodePtr& schema) : GenericContainer(AVRO_MAP, schema) {
393  }
394 
398  const Value& value() const {
399  return value_;
400  }
401 
405  Value& value() {
406  return value_;
407  }
408 private:
409  Value value_;
410 };
411 
415 class AVRO_DECL GenericEnum : public GenericContainer {
416  size_t value_;
417 
418  static size_t index(const NodePtr& schema, const std::string& symbol) {
419  size_t result;
420  if (schema->nameIndex(symbol, result)) {
421  return result;
422  }
423  throw Exception("No such symbol");
424  }
425 
426 public:
431  GenericEnum(const NodePtr& schema) :
432  GenericContainer(AVRO_ENUM, schema), value_(0) {
433  }
434 
435  GenericEnum(const NodePtr& schema, const std::string& symbol) :
436  GenericContainer(AVRO_ENUM, schema), value_(index(schema, symbol)) {
437  }
438 
443  const std::string& symbol(size_t n) {
444  if (n < schema()->names()) {
445  return schema()->nameAt(n);
446  }
447  throw Exception("Not as many symbols");
448  }
449 
454  size_t index(const std::string& symbol) const {
455  return index(schema(), symbol);
456  }
457 
461  size_t set(const std::string& symbol) {
462  return value_ = index(symbol);
463  }
464 
468  void set(size_t n) {
469  if (n < schema()->names()) {
470  value_ = n;
471  return;
472  }
473  throw Exception("Not as many symbols");
474  }
475 
479  size_t value() const {
480  return value_;
481  }
482 
486  const std::string& symbol() const {
487  return schema()->nameAt(value_);
488  }
489 };
490 
494 class AVRO_DECL GenericFixed : public GenericContainer {
495  std::vector<uint8_t> value_;
496 public:
501  GenericFixed(const NodePtr& schema) : GenericContainer(AVRO_FIXED, schema) {
502  value_.resize(schema->fixedSize());
503  }
504 
505  GenericFixed(const NodePtr& schema, const std::vector<uint8_t>& v) :
506  GenericContainer(AVRO_FIXED, schema), value_(v) { }
507 
511  const std::vector<uint8_t>& value() const {
512  return value_;
513  }
514 
518  std::vector<uint8_t>& value() {
519  return value_;
520  }
521 };
522 
523 inline Type GenericDatum::type() const {
524  return (type_ == AVRO_UNION) ?
525 #if __cplusplus >= 201703L
526  std::any_cast<GenericUnion>(&value_)->datum().type() :
527 #else
528  boost::any_cast<GenericUnion>(&value_)->datum().type() :
529 #endif
530  type_;
531 }
532 
534  return logicalType_;
535 }
536 
537 template<typename T> T& GenericDatum::value() {
538  return (type_ == AVRO_UNION) ?
539 #if __cplusplus >= 201703L
540  std::any_cast<GenericUnion>(&value_)->datum().value<T>() :
541  *std::any_cast<T>(&value_);
542 #else
543  boost::any_cast<GenericUnion>(&value_)->datum().value<T>() :
544  *boost::any_cast<T>(&value_);
545 #endif
546 }
547 
548 template<typename T> const T& GenericDatum::value() const {
549  return (type_ == AVRO_UNION) ?
550 #if __cplusplus >= 201703L
551  std::any_cast<GenericUnion>(&value_)->datum().value<T>() :
552  *std::any_cast<T>(&value_);
553 #else
554  boost::any_cast<GenericUnion>(&value_)->datum().value<T>() :
555  *boost::any_cast<T>(&value_);
556 #endif
557 }
558 
559 inline size_t GenericDatum::unionBranch() const {
560 #if __cplusplus >= 201703L
561  return std::any_cast<GenericUnion>(&value_)->currentBranch();
562 #else
563  return boost::any_cast<GenericUnion>(&value_)->currentBranch();
564 #endif
565 }
566 
567 inline void GenericDatum::selectBranch(size_t branch) {
568 #if __cplusplus >= 201703L
569  std::any_cast<GenericUnion>(&value_)->selectBranch(branch);
570 #else
571  boost::any_cast<GenericUnion>(&value_)->selectBranch(branch);
572 #endif
573 }
574 
575 } // namespace avro
576 #endif // avro_GenericDatum_hh__
std::vector< uint8_t > & value()
Returns the reference to the contents of this fixed.
Definition: GenericDatum.hh:518
Definition: Types.hh:37
GenericArray(const NodePtr &schema)
Constructs a generic array corresponding to the given schema schema, which should be of Avro type arr...
Definition: GenericDatum.hh:358
size_t currentBranch() const
Returns the index of the current branch.
Definition: GenericDatum.hh:236
Definition: Types.hh:45
GenericDatum & fieldAt(size_t pos)
Returns the reference to the field at the given position pos, which can be used to change the content...
Definition: GenericDatum.hh:331
Definition: Types.hh:40
size_t unionBranch() const
Returns the index of the current branch, if this is a union.
Definition: GenericDatum.hh:559
const Value & value() const
Returns the contents of this array.
Definition: GenericDatum.hh:364
The generic container for Avro maps.
Definition: GenericDatum.hh:381
Type
The "type" for the schema.
Definition: Types.hh:31
A bunch of templates and specializations for encoding and decoding specific types.
Definition: AvroParse.hh:30
Generic container for Avro enum.
Definition: GenericDatum.hh:415
const std::string & symbol() const
Returns the symbol for the current value of this enum.
Definition: GenericDatum.hh:486
GenericDatum(double v)
Makes a new AVRO_DOUBLE datum whose value is of type double.
Definition: GenericDatum.hh:148
const NodePtr & schema() const
Returns the schema for this object.
Definition: GenericDatum.hh:210
bool isUnion() const
Returns true if and only if this datum is a union.
Definition: GenericDatum.hh:114
GenericDatum(const std::string &v)
Makes a new AVRO_STRING datum whose value is of type std::string.
Definition: GenericDatum.hh:152
Definition: Types.hh:43
size_t fieldIndex(const std::string &name) const
Returns index of the field with the given name name.
Definition: GenericDatum.hh:288
Definition: Types.hh:39
The generic container for Avro arrays.
Definition: GenericDatum.hh:347
const std::string & symbol(size_t n)
Returns the symbol corresponding to the cardinal n.
Definition: GenericDatum.hh:443
size_t index(const std::string &symbol) const
Returns the cardinal for the given symbol symbol.
Definition: GenericDatum.hh:454
Value & value()
Returns the reference to the contents of this map.
Definition: GenericDatum.hh:405
Definition: Types.hh:33
std::vector< std::pair< std::string, GenericDatum > > Value
The contents type for the map.
Definition: GenericDatum.hh:386
GenericContainer(Type type, const NodePtr &s)
Constructs a container corresponding to the given schema.
Definition: GenericDatum.hh:204
const GenericDatum & fieldAt(size_t pos) const
Returns the field at the given position pos.
Definition: GenericDatum.hh:323
void setFieldAt(size_t pos, const GenericDatum &v)
Replaces the field at the given position pos with v.
Definition: GenericDatum.hh:338
Value & value()
Returns the reference to the contents of this array.
Definition: GenericDatum.hh:371
Definition: Types.hh:44
const T & value() const
Returns the value held by this datum.
Definition: GenericDatum.hh:548
GenericDatum(const std::vector< uint8_t > &v)
Makes a new AVRO_BYTES datum whose value is of type std::vector<uint8_t>.
Definition: GenericDatum.hh:157
GenericMap(const NodePtr &schema)
Constructs a generic map corresponding to the given schema schema, which should be of Avro type map...
Definition: GenericDatum.hh:392
GenericDatum(const NodePtr &schema, const T &v)
Constructs a datum corresponding to the given avro type and set the value.
Definition: GenericDatum.hh:175
size_t value() const
Returns the cardinal for the current value of this enum.
Definition: GenericDatum.hh:479
GenericEnum(const NodePtr &schema)
Constructs a generic enum corresponding to the given schema schema, which should be of Avro type enum...
Definition: GenericDatum.hh:431
GenericDatum()
Makes a new AVRO_NULL datum.
Definition: GenericDatum.hh:129
Definition: Types.hh:35
Definition: Types.hh:47
Definition: Types.hh:34
GenericDatum(float v)
Makes a new AVRO_FLOAT datum whose value is of type float.
Definition: GenericDatum.hh:144
GenericDatum(int32_t v)
Makes a new AVRO_INT datum whose value is of type int32_t.
Definition: GenericDatum.hh:136
GenericDatum & datum()
Returns the datum corresponding to the currently selected branch in this union.
Definition: GenericDatum.hh:253
Definition: LogicalType.hh:28
LogicalType logicalType() const
The avro logical type that augments the main data type this datum holds.
Definition: GenericDatum.hh:533
The generic container for Avro records.
Definition: GenericDatum.hh:269
GenericDatum & field(const std::string &name)
Returns the reference to the field with the given name name, which can be used to change the contents...
Definition: GenericDatum.hh:316
void selectBranch(size_t branch)
Selects a new branch.
Definition: GenericDatum.hh:242
Definition: Types.hh:38
size_t fieldCount() const
Returns the number of fields in the current record.
Definition: GenericDatum.hh:281
GenericDatum(bool v)
Makes a new AVRO_BOOL datum whose value is of type bool.
Definition: GenericDatum.hh:132
std::vector< GenericDatum > Value
The contents type for the array.
Definition: GenericDatum.hh:352
void selectBranch(size_t branch)
Selects a new branch in the union if this is a union.
Definition: GenericDatum.hh:567
const GenericDatum & datum() const
Returns the datum corresponding to the currently selected branch in this union.
Definition: GenericDatum.hh:261
Wrapper for std::runtime_error that provides convenience constructor for boost::format objects...
Definition: Exception.hh:31
Type type() const
The avro data type this datum holds.
Definition: GenericDatum.hh:523
A ValidSchema is basically a non-mutable Schema that has passed some minumum of sanity checks...
Definition: ValidSchema.hh:40
const GenericDatum & field(const std::string &name) const
Returns the field with the given name name.
Definition: GenericDatum.hh:308
The base class for all generic type for containers.
Definition: GenericDatum.hh:197
Generic container for Avro fixed.
Definition: GenericDatum.hh:494
Definition: Types.hh:46
Generic container for unions.
Definition: GenericDatum.hh:218
const Value & value() const
Returns the contents of this map.
Definition: GenericDatum.hh:398
const std::vector< uint8_t > & value() const
Returns the contents of this fixed.
Definition: GenericDatum.hh:511
bool hasField(const std::string &name) const
Returns true if a field with the given name name is located in this r false otherwise.
Definition: GenericDatum.hh:300
Definition: Types.hh:36
GenericDatum(int64_t v)
Makes a new AVRO_LONG datum whose value is of type int64_t.
Definition: GenericDatum.hh:140
GenericFixed(const NodePtr &schema)
Constructs a generic enum corresponding to the given schema schema, which should be of Avro type fixe...
Definition: GenericDatum.hh:501
Generic datum which can hold any Avro type.
Definition: GenericDatum.hh:61
GenericUnion(const NodePtr &schema)
Constructs a generic union corresponding to the given schema schema, and the given value...
Definition: GenericDatum.hh:228