00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef avro_Generic_hh__
00020 #define avro_Generic_hh__
00021
00022 #include <vector>
00023 #include <map>
00024 #include <string>
00025
00026 #include <boost/any.hpp>
00027 #include <boost/utility.hpp>
00028
00029 #include "Node.hh"
00030 #include "Types.hh"
00031 #include "Encoder.hh"
00032 #include "Decoder.hh"
00033 #include "ValidSchema.hh"
00034
00035 namespace avro {
00058 class GenericDatum {
00059 Type type_;
00060 boost::any value_;
00061
00062 GenericDatum(Type t) : type_(t) { }
00063
00064 template <typename T>
00065 GenericDatum(Type t, const T& v) : type_(t), value_(v) { }
00066
00067 void init(const NodePtr& schema);
00068 public:
00072 Type type() const;
00073
00079 template<typename T> const T& value() const;
00080
00090 template<typename T> T& value();
00091
00095 bool isUnion() const { return type_ == AVRO_UNION; }
00096
00101 size_t unionBranch() const;
00102
00107 void selectBranch(size_t branch);
00108
00110 GenericDatum() : type_(AVRO_NULL) { }
00111
00113 GenericDatum(bool v) : type_(AVRO_BOOL), value_(v) { }
00114
00116 GenericDatum(int32_t v) : type_(AVRO_INT), value_(v) { }
00117
00119 GenericDatum(int64_t v) : type_(AVRO_LONG), value_(v) { }
00120
00122 GenericDatum(float v) : type_(AVRO_FLOAT), value_(v) { }
00123
00125 GenericDatum(double v) : type_(AVRO_DOUBLE), value_(v) { }
00126
00128 GenericDatum(const std::string& v) : type_(AVRO_STRING), value_(v) { }
00129
00132 GenericDatum(const std::vector<uint8_t>& v) :
00133 type_(AVRO_BYTES), value_(v) { }
00134
00141 GenericDatum(const NodePtr& schema);
00142
00149 GenericDatum(const ValidSchema& schema);
00150 };
00151
00155 class GenericContainer {
00156 NodePtr schema_;
00157 static void assertType(const NodePtr& schema, Type type);
00158 protected:
00162 GenericContainer(Type type, const NodePtr& s) : schema_(s) {
00163 assertType(s, type);
00164 }
00165
00169 static void assertSameType(const GenericDatum& v, const NodePtr& n);
00170
00171 public:
00173 const NodePtr& schema() const {
00174 return schema_;
00175 }
00176 };
00177
00181 class GenericUnion : public GenericContainer {
00182 size_t curBranch_;
00183 GenericDatum datum_;
00184
00185 public:
00191 GenericUnion(const NodePtr& schema) :
00192 GenericContainer(AVRO_UNION, schema), curBranch_(schema->leaves()) {
00193 }
00194
00198 size_t currentBranch() const { return curBranch_; }
00199
00204 void selectBranch(size_t branch) {
00205 if (curBranch_ != branch) {
00206 datum_ = GenericDatum(schema()->leafAt(branch));
00207 curBranch_ = branch;
00208 }
00209 }
00210
00214 Type type() const {
00215 return datum_.type();
00216 }
00217
00221 template<typename T>
00222 const T& value() const {
00223 return datum_.value<T>();
00224 }
00225
00229 template<typename T>
00230 T& value() {
00231 return datum_.value<T>();
00232 }
00233
00234 };
00235
00239 class GenericRecord : public GenericContainer {
00240 std::vector<GenericDatum> fields_;
00241 public:
00246 GenericRecord(const NodePtr& schema);
00247
00251 size_t fieldCount() const {
00252 return fields_.size();
00253 }
00254
00258 const GenericDatum& fieldAt(size_t pos) const {
00259 return fields_[pos];
00260 }
00261
00266 GenericDatum& fieldAt(size_t pos) {
00267 return fields_[pos];
00268 }
00269
00273 void setFieldAt(size_t pos, const GenericDatum& v) {
00274 assertSameType(v, schema()->leafAt(pos));
00275 fields_[pos] = v;
00276 }
00277 };
00278
00282 class GenericArray : public GenericContainer {
00283 public:
00287 typedef std::vector<GenericDatum> Value;
00288
00293 GenericArray(const NodePtr& schema) : GenericContainer(AVRO_ARRAY, schema) {
00294 }
00295
00299 const Value& value() const {
00300 return value_;
00301 }
00302
00306 Value& value() {
00307 return value_;
00308 }
00309 private:
00310 Value value_;
00311 };
00312
00316 class GenericMap : public GenericContainer {
00317 public:
00321 typedef std::vector<std::pair<std::string, GenericDatum> > Value;
00322
00327 GenericMap(const NodePtr& schema) : GenericContainer(AVRO_MAP, schema) {
00328 }
00329
00333 const Value& value() const {
00334 return value_;
00335 }
00336
00340 Value& value() {
00341 return value_;
00342 }
00343 private:
00344 Value value_;
00345 };
00346
00350 class GenericEnum : public GenericContainer {
00351 size_t value_;
00352 public:
00357 GenericEnum(const NodePtr& schema) :
00358 GenericContainer(AVRO_ENUM, schema), value_(0) {
00359 }
00360
00365 const std::string& symbol(size_t n) {
00366 if (n < schema()->names()) {
00367 return schema()->nameAt(n);
00368 }
00369 throw Exception("Not as many symbols");
00370 }
00371
00376 size_t index(const std::string& symbol) const {
00377 size_t result;
00378 if (schema()->nameIndex(symbol, result)) {
00379 return result;
00380 }
00381 throw Exception("No such symbol");
00382 }
00383
00387 size_t set(const std::string& symbol) {
00388 return value_ = index(symbol);
00389 }
00390
00394 void set(size_t n) {
00395 if (n < schema()->names()) {
00396 value_ = n;
00397 return;
00398 }
00399 throw Exception("Not as many symbols");
00400 }
00401
00405 size_t value() const {
00406 return value_;
00407 }
00408
00412 const std::string& symbol() const {
00413 return schema()->nameAt(value_);
00414 }
00415 };
00416
00420 class GenericFixed : public GenericContainer {
00421 std::vector<uint8_t> value_;
00422 public:
00427 GenericFixed(const NodePtr& schema) : GenericContainer(AVRO_FIXED, schema) {
00428 value_.resize(schema->fixedSize());
00429 }
00430
00434 const std::vector<uint8_t>& value() const {
00435 return value_;
00436 }
00437
00441 std::vector<uint8_t>& value() {
00442 return value_;
00443 }
00444 };
00445
00446
00450 class GenericReader : boost::noncopyable {
00451 const ValidSchema schema_;
00452 const bool isResolving_;
00453 const DecoderPtr decoder_;
00454
00455 static void read(GenericDatum& datum, Decoder& d, bool isResolving);
00456 public:
00460 GenericReader(const ValidSchema& s, const DecoderPtr& decoder);
00461
00467 GenericReader(const ValidSchema& writerSchema,
00468 const ValidSchema& readerSchema, const DecoderPtr& decoder);
00469
00473 void read(GenericDatum& datum) const;
00474
00478 static void read(Decoder& d, GenericDatum& g);
00479
00483 static void read(Decoder& d, GenericDatum& g, const ValidSchema& s);
00484 };
00485
00486
00490 class GenericWriter : boost::noncopyable {
00491 const ValidSchema schema_;
00492 const EncoderPtr encoder_;
00493
00494 static void write(const GenericDatum& datum, Encoder& e);
00495 public:
00499 GenericWriter(const ValidSchema& s, const EncoderPtr& encoder);
00500
00504 void write(const GenericDatum& datum) const;
00505
00509 static void write(Encoder& e, const GenericDatum& g);
00510
00515 static void write(Encoder& e, const GenericDatum& g, const ValidSchema&) {
00516 write(e, g);
00517 }
00518 };
00519
00520 inline Type GenericDatum::type() const {
00521 return (type_ == AVRO_UNION) ?
00522 boost::any_cast<GenericUnion>(&value_)->type() : type_;
00523 }
00524
00525 template<typename T>
00526 const T& GenericDatum::value() const {
00527 return (type_ == AVRO_UNION) ?
00528 boost::any_cast<GenericUnion>(&value_)->value<T>() :
00529 *boost::any_cast<T>(&value_);
00530 }
00531
00532 template<typename T>
00533 T& GenericDatum::value() {
00534 return (type_ == AVRO_UNION) ?
00535 boost::any_cast<GenericUnion>(&value_)->value<T>() :
00536 *boost::any_cast<T>(&value_);
00537 }
00538
00539 inline size_t GenericDatum::unionBranch() const {
00540 return boost::any_cast<GenericUnion>(&value_)->currentBranch();
00541 }
00542
00543 inline void GenericDatum::selectBranch(size_t branch) {
00544 boost::any_cast<GenericUnion>(&value_)->selectBranch(branch);
00545 }
00546
00547 template <typename T> struct codec_traits;
00548
00554 template <> struct codec_traits<std::pair<ValidSchema, GenericDatum> > {
00556 static void encode(Encoder& e,
00557 const std::pair<ValidSchema, GenericDatum>& p) {
00558 GenericWriter::write(e, p.second, p.first);
00559 }
00560
00562 static void decode(Decoder& d, std::pair<ValidSchema, GenericDatum>& p) {
00563 GenericReader::read(d, p.second, p.first);
00564 }
00565 };
00566
00570 template <> struct codec_traits<GenericDatum> {
00572 static void encode(Encoder& e, const GenericDatum& g) {
00573 GenericWriter::write(e, g);
00574 }
00575
00577 static void decode(Decoder& d, GenericDatum& g) {
00578 GenericReader::read(d, g);
00579 }
00580 };
00581
00582 }
00583 #endif
00584