Avro C++
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the 00007 * "License"); you may not use this file except in compliance 00008 * with the License. You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 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 "Config.hh" 00030 #include "Node.hh" 00031 #include "Types.hh" 00032 #include "Encoder.hh" 00033 #include "Decoder.hh" 00034 #include "ValidSchema.hh" 00035 00036 namespace avro { 00059 class AVRO_DECL GenericDatum { 00060 Type type_; 00061 boost::any value_; 00062 00063 GenericDatum(Type t) : type_(t) { } 00064 00065 template <typename T> 00066 GenericDatum(Type t, const T& v) : type_(t), value_(v) { } 00067 00068 void init(const NodePtr& schema); 00069 public: 00073 Type type() const; 00074 00080 template<typename T> const T& value() const; 00081 00091 template<typename T> T& value(); 00092 00096 bool isUnion() const { return type_ == AVRO_UNION; } 00097 00102 size_t unionBranch() const; 00103 00108 void selectBranch(size_t branch); 00109 00111 GenericDatum() : type_(AVRO_NULL) { } 00112 00114 GenericDatum(bool v) : type_(AVRO_BOOL), value_(v) { } 00115 00117 GenericDatum(int32_t v) : type_(AVRO_INT), value_(v) { } 00118 00120 GenericDatum(int64_t v) : type_(AVRO_LONG), value_(v) { } 00121 00123 GenericDatum(float v) : type_(AVRO_FLOAT), value_(v) { } 00124 00126 GenericDatum(double v) : type_(AVRO_DOUBLE), value_(v) { } 00127 00129 GenericDatum(const std::string& v) : type_(AVRO_STRING), value_(v) { } 00130 00133 GenericDatum(const std::vector<uint8_t>& v) : 00134 type_(AVRO_BYTES), value_(v) { } 00135 00142 GenericDatum(const NodePtr& schema); 00143 00150 GenericDatum(const ValidSchema& schema); 00151 }; 00152 00156 class AVRO_DECL GenericContainer { 00157 NodePtr schema_; 00158 static void assertType(const NodePtr& schema, Type type); 00159 protected: 00163 GenericContainer(Type type, const NodePtr& s) : schema_(s) { 00164 assertType(s, type); 00165 } 00166 00167 public: 00169 const NodePtr& schema() const { 00170 return schema_; 00171 } 00172 }; 00173 00177 class AVRO_DECL GenericUnion : public GenericContainer { 00178 size_t curBranch_; 00179 GenericDatum datum_; 00180 00181 public: 00187 GenericUnion(const NodePtr& schema) : 00188 GenericContainer(AVRO_UNION, schema), curBranch_(schema->leaves()) { 00189 } 00190 00194 size_t currentBranch() const { return curBranch_; } 00195 00200 void selectBranch(size_t branch) { 00201 if (curBranch_ != branch) { 00202 datum_ = GenericDatum(schema()->leafAt(branch)); 00203 curBranch_ = branch; 00204 } 00205 } 00206 00210 Type type() const { 00211 return datum_.type(); 00212 } 00213 00217 template<typename T> 00218 const T& value() const { 00219 return datum_.value<T>(); 00220 } 00221 00225 template<typename T> 00226 T& value() { 00227 return datum_.value<T>(); 00228 } 00229 00230 }; 00231 00235 class AVRO_DECL GenericRecord : public GenericContainer { 00236 std::vector<GenericDatum> fields_; 00237 public: 00242 GenericRecord(const NodePtr& schema); 00243 00247 size_t fieldCount() const { 00248 return fields_.size(); 00249 } 00250 00254 size_t fieldIndex(const std::string& name) const { 00255 size_t index = 0; 00256 if (!schema()->nameIndex(name, index)) { 00257 throw Exception("Invalid field name: " + name); 00258 } 00259 return index; 00260 } 00261 00266 bool hasField(const std::string& name) const { 00267 size_t index = 0; 00268 return schema()->nameIndex(name, index); 00269 } 00270 00274 const GenericDatum& field(const std::string& name) const { 00275 return fieldAt(fieldIndex(name)); 00276 } 00277 00282 GenericDatum& field(const std::string& name) { 00283 return fieldAt(fieldIndex(name)); 00284 } 00285 00289 const GenericDatum& fieldAt(size_t pos) const { 00290 return fields_[pos]; 00291 } 00292 00297 GenericDatum& fieldAt(size_t pos) { 00298 return fields_[pos]; 00299 } 00300 00304 void setField(const std::string& name, const GenericDatum& v) { 00305 // assertSameType(v, schema()->leafAt(pos)); 00306 return setFieldAt(fieldIndex(name), v); 00307 } 00308 00312 void setFieldAt(size_t pos, const GenericDatum& v) { 00313 // assertSameType(v, schema()->leafAt(pos)); 00314 fields_[pos] = v; 00315 } 00316 }; 00317 00321 class AVRO_DECL GenericArray : public GenericContainer { 00322 public: 00326 typedef std::vector<GenericDatum> Value; 00327 00332 GenericArray(const NodePtr& schema) : GenericContainer(AVRO_ARRAY, schema) { 00333 } 00334 00338 const Value& value() const { 00339 return value_; 00340 } 00341 00345 Value& value() { 00346 return value_; 00347 } 00348 private: 00349 Value value_; 00350 }; 00351 00355 class AVRO_DECL GenericMap : public GenericContainer { 00356 public: 00360 typedef std::vector<std::pair<std::string, GenericDatum> > Value; 00361 00366 GenericMap(const NodePtr& schema) : GenericContainer(AVRO_MAP, schema) { 00367 } 00368 00372 const Value& value() const { 00373 return value_; 00374 } 00375 00379 Value& value() { 00380 return value_; 00381 } 00382 private: 00383 Value value_; 00384 }; 00385 00389 class AVRO_DECL GenericEnum : public GenericContainer { 00390 size_t value_; 00391 public: 00396 GenericEnum(const NodePtr& schema) : 00397 GenericContainer(AVRO_ENUM, schema), value_(0) { 00398 } 00399 00404 const std::string& symbol(size_t n) { 00405 if (n < schema()->names()) { 00406 return schema()->nameAt(n); 00407 } 00408 throw Exception("Not as many symbols"); 00409 } 00410 00415 size_t index(const std::string& symbol) const { 00416 size_t result; 00417 if (schema()->nameIndex(symbol, result)) { 00418 return result; 00419 } 00420 throw Exception("No such symbol"); 00421 } 00422 00426 size_t set(const std::string& symbol) { 00427 return value_ = index(symbol); 00428 } 00429 00433 void set(size_t n) { 00434 if (n < schema()->names()) { 00435 value_ = n; 00436 return; 00437 } 00438 throw Exception("Not as many symbols"); 00439 } 00440 00444 size_t value() const { 00445 return value_; 00446 } 00447 00451 const std::string& symbol() const { 00452 return schema()->nameAt(value_); 00453 } 00454 }; 00455 00459 class AVRO_DECL GenericFixed : public GenericContainer { 00460 std::vector<uint8_t> value_; 00461 public: 00466 GenericFixed(const NodePtr& schema) : GenericContainer(AVRO_FIXED, schema) { 00467 value_.resize(schema->fixedSize()); 00468 } 00469 00473 const std::vector<uint8_t>& value() const { 00474 return value_; 00475 } 00476 00480 std::vector<uint8_t>& value() { 00481 return value_; 00482 } 00483 }; 00484 00485 00489 class AVRO_DECL GenericReader : boost::noncopyable { 00490 const ValidSchema schema_; 00491 const bool isResolving_; 00492 const DecoderPtr decoder_; 00493 00494 static void read(GenericDatum& datum, Decoder& d, bool isResolving); 00495 public: 00499 GenericReader(const ValidSchema& s, const DecoderPtr& decoder); 00500 00506 GenericReader(const ValidSchema& writerSchema, 00507 const ValidSchema& readerSchema, const DecoderPtr& decoder); 00508 00512 void read(GenericDatum& datum) const; 00513 00517 static void read(Decoder& d, GenericDatum& g); 00518 00522 static void read(Decoder& d, GenericDatum& g, const ValidSchema& s); 00523 }; 00524 00525 00529 class AVRO_DECL GenericWriter : boost::noncopyable { 00530 const ValidSchema schema_; 00531 const EncoderPtr encoder_; 00532 00533 static void write(const GenericDatum& datum, Encoder& e); 00534 public: 00538 GenericWriter(const ValidSchema& s, const EncoderPtr& encoder); 00539 00543 void write(const GenericDatum& datum) const; 00544 00548 static void write(Encoder& e, const GenericDatum& g); 00549 00554 static void write(Encoder& e, const GenericDatum& g, const ValidSchema&) { 00555 write(e, g); 00556 } 00557 }; 00558 00559 inline Type AVRO_DECL GenericDatum::type() const { 00560 return (type_ == AVRO_UNION) ? 00561 boost::any_cast<GenericUnion>(&value_)->type() : type_; 00562 } 00563 00564 template<typename T> 00565 const T& GenericDatum::value() const { 00566 return (type_ == AVRO_UNION) ? 00567 boost::any_cast<GenericUnion>(&value_)->value<T>() : 00568 *boost::any_cast<T>(&value_); 00569 } 00570 00571 template<typename T> 00572 T& GenericDatum::value() { 00573 return (type_ == AVRO_UNION) ? 00574 boost::any_cast<GenericUnion>(&value_)->value<T>() : 00575 *boost::any_cast<T>(&value_); 00576 } 00577 00578 inline size_t GenericDatum::unionBranch() const { 00579 return boost::any_cast<GenericUnion>(&value_)->currentBranch(); 00580 } 00581 00582 inline void GenericDatum::selectBranch(size_t branch) { 00583 boost::any_cast<GenericUnion>(&value_)->selectBranch(branch); 00584 } 00585 00586 template <typename T> struct codec_traits; 00587 00593 template <> struct codec_traits<std::pair<ValidSchema, GenericDatum> > { 00595 static void encode(Encoder& e, 00596 const std::pair<ValidSchema, GenericDatum>& p) { 00597 GenericWriter::write(e, p.second, p.first); 00598 } 00599 00601 static void decode(Decoder& d, std::pair<ValidSchema, GenericDatum>& p) { 00602 GenericReader::read(d, p.second, p.first); 00603 } 00604 }; 00605 00609 template <> struct codec_traits<GenericDatum> { 00611 static void encode(Encoder& e, const GenericDatum& g) { 00612 GenericWriter::write(e, g); 00613 } 00614 00616 static void decode(Decoder& d, GenericDatum& g) { 00617 GenericReader::read(d, g); 00618 } 00619 }; 00620 00621 } // namespace avro 00622 #endif 00623