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_GenericDatum_hh__ 00020 #define avro_GenericDatum_hh__ 00021 00022 #include <stdint.h> 00023 #include <vector> 00024 #include <map> 00025 #include <string> 00026 00027 #include <boost/any.hpp> 00028 00029 #include "Node.hh" 00030 #include "ValidSchema.hh" 00031 00032 namespace avro { 00055 class AVRO_DECL GenericDatum { 00056 Type type_; 00057 boost::any value_; 00058 00059 GenericDatum(Type t) : type_(t) { } 00060 00061 template <typename T> 00062 GenericDatum(Type t, const T& v) : type_(t), value_(v) { } 00063 00064 void init(const NodePtr& schema); 00065 public: 00069 Type type() const { 00070 return type_; 00071 } 00072 00078 template<typename T> const T& value() const { 00079 return *boost::any_cast<T>(&value_); 00080 } 00081 00091 template<typename T> T& value() { 00092 return *boost::any_cast<T>(&value_); 00093 } 00094 00098 bool isUnion() const { return type_ == AVRO_UNION; } 00099 00104 size_t unionBranch() const; 00105 00110 void selectBranch(size_t branch); 00111 00113 GenericDatum() : type_(AVRO_NULL) { } 00114 00116 GenericDatum(bool v) : type_(AVRO_BOOL), value_(v) { } 00117 00119 GenericDatum(int32_t v) : type_(AVRO_INT), value_(v) { } 00120 00122 GenericDatum(int64_t v) : type_(AVRO_LONG), value_(v) { } 00123 00125 GenericDatum(float v) : type_(AVRO_FLOAT), value_(v) { } 00126 00128 GenericDatum(double v) : type_(AVRO_DOUBLE), value_(v) { } 00129 00131 GenericDatum(const std::string& v) : type_(AVRO_STRING), value_(v) { } 00132 00135 GenericDatum(const std::vector<uint8_t>& v) : 00136 type_(AVRO_BYTES), value_(v) { } 00137 00144 GenericDatum(const NodePtr& schema); 00145 00152 template<typename T> 00153 GenericDatum(const NodePtr& schema, const T& v) : 00154 type_(schema->type()) { 00155 init(schema); 00156 value<T>() = v; 00157 } 00158 00165 GenericDatum(const ValidSchema& schema); 00166 }; 00167 00171 class AVRO_DECL GenericContainer { 00172 NodePtr schema_; 00173 static void assertType(const NodePtr& schema, Type type); 00174 protected: 00178 GenericContainer(Type type, const NodePtr& s) : schema_(s) { 00179 assertType(s, type); 00180 } 00181 00182 public: 00184 const NodePtr& schema() const { 00185 return schema_; 00186 } 00187 }; 00188 00192 class AVRO_DECL GenericUnion : public GenericContainer { 00193 size_t curBranch_; 00194 GenericDatum datum_; 00195 00196 public: 00202 GenericUnion(const NodePtr& schema) : 00203 GenericContainer(AVRO_UNION, schema), curBranch_(schema->leaves()) { 00204 } 00205 00209 size_t currentBranch() const { return curBranch_; } 00210 00215 void selectBranch(size_t branch) { 00216 if (curBranch_ != branch) { 00217 datum_ = GenericDatum(schema()->leafAt(branch)); 00218 curBranch_ = branch; 00219 } 00220 } 00221 00226 GenericDatum& datum() { 00227 return datum_; 00228 } 00229 00234 const GenericDatum& datum() const { 00235 return datum_; 00236 } 00237 }; 00238 00242 class AVRO_DECL GenericRecord : public GenericContainer { 00243 std::vector<GenericDatum> fields_; 00244 public: 00249 GenericRecord(const NodePtr& schema); 00250 00254 size_t fieldCount() const { 00255 return fields_.size(); 00256 } 00257 00261 size_t fieldIndex(const std::string& name) const { 00262 size_t index = 0; 00263 if (!schema()->nameIndex(name, index)) { 00264 throw Exception("Invalid field name: " + name); 00265 } 00266 return index; 00267 } 00268 00273 bool hasField(const std::string& name) const { 00274 size_t index = 0; 00275 return schema()->nameIndex(name, index); 00276 } 00277 00281 const GenericDatum& field(const std::string& name) const { 00282 return fieldAt(fieldIndex(name)); 00283 } 00284 00289 GenericDatum& field(const std::string& name) { 00290 return fieldAt(fieldIndex(name)); 00291 } 00292 00296 const GenericDatum& fieldAt(size_t pos) const { 00297 return fields_[pos]; 00298 } 00299 00304 GenericDatum& fieldAt(size_t pos) { 00305 return fields_[pos]; 00306 } 00307 00311 void setFieldAt(size_t pos, const GenericDatum& v) { 00312 // assertSameType(v, schema()->leafAt(pos)); 00313 fields_[pos] = v; 00314 } 00315 }; 00316 00320 class AVRO_DECL GenericArray : public GenericContainer { 00321 public: 00325 typedef std::vector<GenericDatum> Value; 00326 00331 GenericArray(const NodePtr& schema) : GenericContainer(AVRO_ARRAY, schema) { 00332 } 00333 00337 const Value& value() const { 00338 return value_; 00339 } 00340 00344 Value& value() { 00345 return value_; 00346 } 00347 private: 00348 Value value_; 00349 }; 00350 00354 class AVRO_DECL GenericMap : public GenericContainer { 00355 public: 00359 typedef std::vector<std::pair<std::string, GenericDatum> > Value; 00360 00365 GenericMap(const NodePtr& schema) : GenericContainer(AVRO_MAP, schema) { 00366 } 00367 00371 const Value& value() const { 00372 return value_; 00373 } 00374 00378 Value& value() { 00379 return value_; 00380 } 00381 private: 00382 Value value_; 00383 }; 00384 00388 class AVRO_DECL GenericEnum : public GenericContainer { 00389 size_t value_; 00390 00391 static size_t index(const NodePtr& schema, const std::string& symbol) { 00392 size_t result; 00393 if (schema->nameIndex(symbol, result)) { 00394 return result; 00395 } 00396 throw Exception("No such symbol"); 00397 } 00398 00399 public: 00404 GenericEnum(const NodePtr& schema) : 00405 GenericContainer(AVRO_ENUM, schema), value_(0) { 00406 } 00407 00408 GenericEnum(const NodePtr& schema, const std::string& symbol) : 00409 GenericContainer(AVRO_ENUM, schema), value_(index(schema, symbol)) { 00410 } 00411 00416 const std::string& symbol(size_t n) { 00417 if (n < schema()->names()) { 00418 return schema()->nameAt(n); 00419 } 00420 throw Exception("Not as many symbols"); 00421 } 00422 00427 size_t index(const std::string& symbol) const { 00428 return index(schema(), symbol); 00429 } 00430 00434 size_t set(const std::string& symbol) { 00435 return value_ = index(symbol); 00436 } 00437 00441 void set(size_t n) { 00442 if (n < schema()->names()) { 00443 value_ = n; 00444 return; 00445 } 00446 throw Exception("Not as many symbols"); 00447 } 00448 00452 size_t value() const { 00453 return value_; 00454 } 00455 00459 const std::string& symbol() const { 00460 return schema()->nameAt(value_); 00461 } 00462 }; 00463 00467 class AVRO_DECL GenericFixed : public GenericContainer { 00468 std::vector<uint8_t> value_; 00469 public: 00474 GenericFixed(const NodePtr& schema) : GenericContainer(AVRO_FIXED, schema) { 00475 value_.resize(schema->fixedSize()); 00476 } 00477 00478 GenericFixed(const NodePtr& schema, const std::vector<uint8_t>& v) : 00479 GenericContainer(AVRO_FIXED, schema), value_(v) { } 00480 00484 const std::vector<uint8_t>& value() const { 00485 return value_; 00486 } 00487 00491 std::vector<uint8_t>& value() { 00492 return value_; 00493 } 00494 }; 00495 00496 inline size_t GenericDatum::unionBranch() const { 00497 return boost::any_cast<GenericUnion>(&value_)->currentBranch(); 00498 } 00499 00500 inline void GenericDatum::selectBranch(size_t branch) { 00501 boost::any_cast<GenericUnion>(&value_)->selectBranch(branch); 00502 } 00503 00504 } // namespace avro 00505 #endif // avro_GenericDatum_hh__