Generic.hh

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 }   // namespace avro
00277 #endif
00278