/* -*- c++ -*- */
#ifndef AKAXISO_MEMBER_H__
#define AKAXISO_MEMBER_H__

#include <akaxiso/classes/qname.h>
#include <vector>

namespace aka2 {

  template<class V>
  V* get_member_ptr(const void *element, int offset) {
    return reinterpret_cast<V*>(reinterpret_cast<int>(element) + offset);
  }

  template <class P, class T, class V>
  int get_member_offset(V T::* member) {
    P* p = reinterpret_cast<P*>(1024);
    return reinterpret_cast<int>(& (p->*member)) - reinterpret_cast<int>(p);
  }

  enum getter_type {
    accessor_type = 1,
    ptr_type,
    null_type
  };

  struct member_getter {
    member_getter(getter_type t) : type_(t) {}
    virtual ~member_getter(){}
    getter_type get_type() const { return type_; }
  private:
    getter_type type_;
  };

  struct ptr_getter : public member_getter {
    ptr_getter(int offset) : member_getter(ptr_type), offset_(offset) {}
    void* get_member(void *e) const {
      return get_member_ptr<void>(e, offset_);
    }
    const void* get_member(const void* e) const {
      return get_member_ptr<const void>(e, offset_);
    }
  protected:
    int offset_;
  };

  struct accessor_getter : public member_getter {
    accessor_getter() : member_getter(accessor_type) {}
    virtual void get(const void *elm, void *cache) const = 0;
    virtual void set(void *elm, const void *cache) const = 0;
  };


  template<class P, class T, class V>
  inline member_getter *create_ptr_getter(const P *, V T::* m) {
    int offset = get_member_offset<P, T, V>(m);
    return new ptr_getter(offset);
  }

  struct null_getter : public member_getter {
     null_getter() : member_getter(null_type) {}
  };

}


#endif
