00001
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 {
00036
00037 class GenericDatum {
00038 Type type_;
00039 boost::any value_;
00040
00041 GenericDatum(Type t) : type_(t) { }
00042
00043 template <typename T>
00044 GenericDatum(Type t, const T& v) : type_(t), value_(v) { }
00045
00046 public:
00047 Type type() const {
00048 return type_;
00049 }
00050
00051 template<typename T>
00052 const T& value() const {
00053 return *boost::any_cast<T>(&value_);
00054 }
00055
00056 template<typename T>
00057 T& value() {
00058 return *boost::any_cast<T>(&value_);
00059 }
00060
00062 GenericDatum() : type_(AVRO_NULL) { }
00063
00065 GenericDatum(bool v) : type_(AVRO_BOOL), value_(v) { }
00066
00068 GenericDatum(int32_t v) : type_(AVRO_INT), value_(v) { }
00069
00071 GenericDatum(int64_t v) : type_(AVRO_LONG), value_(v) { }
00072
00074 GenericDatum(float v) : type_(AVRO_FLOAT), value_(v) { }
00075
00077 GenericDatum(double v) : type_(AVRO_DOUBLE), value_(v) { }
00078
00080 GenericDatum(const std::string& v) : type_(AVRO_STRING), value_(v) { }
00081
00084 GenericDatum(const std::vector<uint8_t>& v) :
00085 type_(AVRO_BYTES), value_(v) { }
00086
00087 GenericDatum(const NodePtr& schema);
00088 };
00089
00090 class GenericContainer {
00091 const NodePtr schema_;
00092 protected:
00093 GenericContainer(const NodePtr& s) : schema_(s) { }
00094
00095 static void assertSameType(const GenericDatum& v, const NodePtr& n);
00096 static void assertType(const NodePtr& schema, Type type,
00097 const char* message);
00098 public:
00100 const NodePtr& schema() const {
00101 return schema_;
00102 }
00103 };
00104
00105 class GenericRecord : public GenericContainer {
00106 std::vector<GenericDatum> fields_;
00107 public:
00108 GenericRecord(const NodePtr& schema);
00109
00110 size_t fieldCount() const {
00111 return fields_.size();
00112 }
00113
00114 const GenericDatum& fieldAt(size_t pos) const {
00115 return fields_[pos];
00116 }
00117
00118 GenericDatum& fieldAt(size_t pos) {
00119 return fields_[pos];
00120 }
00121
00122 void setFieldAt(size_t pos, const GenericDatum& v) {
00123 assertSameType(v, schema()->leafAt(pos));
00124 fields_[pos] = v;
00125 }
00126 };
00127
00128 class GenericArray : public GenericContainer {
00129 public:
00130 typedef std::vector<GenericDatum> Value;
00131
00132 GenericArray(const NodePtr& schema) : GenericContainer(schema) {
00133 if (schema->type() != AVRO_ARRAY) {
00134 throw Exception("Schema is not an array");
00135 }
00136 }
00137
00138 const Value& value() const {
00139 return value_;
00140 }
00141
00142 Value& value() {
00143 return value_;
00144 }
00145 private:
00146 Value value_;
00147 };
00148
00149 class GenericMap : public GenericContainer {
00150 public:
00151 typedef std::vector<std::pair<std::string, GenericDatum> > Value;
00152
00153 GenericMap(const NodePtr& schema) : GenericContainer(schema) {
00154 assertType(schema, AVRO_MAP, "Schema is not a map");
00155 }
00156
00157 const Value& value() const {
00158 return value_;
00159 }
00160
00161 Value& value() {
00162 return value_;
00163 }
00164 private:
00165 Value value_;
00166 };
00167
00168 class GenericEnum : public GenericContainer {
00169 size_t value_;
00170 public:
00171 GenericEnum(const NodePtr& schema) : GenericContainer(schema), value_(0) {
00172 }
00173
00174 const std::string& symbol(size_t n) {
00175 if (n < schema()->names()) {
00176 return schema()->nameAt(n);
00177 }
00178 throw Exception("Not as many symbols");
00179 }
00180
00181 size_t index(const std::string& symbol) const {
00182 size_t result;
00183 if (schema()->nameIndex(symbol, result)) {
00184 return result;
00185 }
00186 throw Exception("No such symbol");
00187 }
00188
00189 size_t set(const std::string& symbol) {
00190 return value_ = index(symbol);
00191 }
00192
00193 void set(size_t n) {
00194 if (n < schema()->names()) {
00195 value_ = n;
00196 return;
00197 }
00198 throw Exception("Not as many symbols");
00199 }
00200
00201 size_t value() const {
00202 return value_;
00203 }
00204
00205 const std::string& symbol() const {
00206 return schema()->nameAt(value_);
00207 }
00208 };
00209
00210 class GenericFixed : public GenericContainer {
00211 std::vector<uint8_t> value_;
00212 public:
00213 GenericFixed(const NodePtr& schema) : GenericContainer(schema) {
00214 value_.resize(schema->fixedSize());
00215 }
00216
00217 const std::vector<uint8_t>& value() const {
00218 return value_;
00219 }
00220
00221 std::vector<uint8_t>& value() {
00222 return value_;
00223 }
00224 };
00225
00226
00227 class GenericReader : boost::noncopyable {
00228 const ValidSchema schema_;
00229 const bool isResolving_;
00230 const DecoderPtr decoder_;
00231
00232 static void read(GenericDatum& datum, const NodePtr& n, Decoder& d,
00233 bool isResolving);
00234 public:
00235 GenericReader(const ValidSchema& s, const DecoderPtr& decoder);
00236 GenericReader(const ValidSchema& writerSchema,
00237 const ValidSchema& readerSchema, const DecoderPtr& decoder);
00238
00239 void read(GenericDatum& datum) const;
00240
00244 static void read(Decoder& d, GenericDatum& g, const ValidSchema& s);
00245 };
00246
00247
00248 class GenericWriter : boost::noncopyable {
00249 const ValidSchema schema_;
00250 const EncoderPtr encoder_;
00251
00252 static void write(const GenericDatum& datum, const NodePtr& n, Encoder& e);
00253 public:
00254 GenericWriter(const ValidSchema& s, const EncoderPtr& encoder);
00255
00256 void write(const GenericDatum& datum) const;
00257
00261 static void write(Encoder& e, const GenericDatum& g, const ValidSchema& s);
00262 };
00263
00264 template <typename T> struct codec_traits;
00265
00266 template <> struct codec_traits<std::pair<ValidSchema, GenericDatum> > {
00267 static void encode(Encoder& e,
00268 const std::pair<ValidSchema, GenericDatum>& p) {
00269 GenericWriter::write(e, p.second, p.first);
00270 }
00271
00272 static void decode(Decoder& d, std::pair<ValidSchema, GenericDatum>& p) {
00273 GenericReader::read(d, p.second, p.first);
00274 }
00275 };
00276 }
00277 #endif
00278