#ifndef _PORTABLE_BINARY_OARCHIVE_H
#define _PORTABLE_BINARY_OARCHIVE_H

#include <stdint.h>
#include <vector>

namespace detail {

template<class T>
class primitive {
  public:
    template<class A>
    primitive(A & ar, const T &value)
    {
    ar.write((const char *) &value, sizeof(T));
    }
};

/** specialization for long: always 64 bit on every architecture */
template<>
class primitive<long> {
  public:
    template<class A>
    primitive(A & ar, const long &value)
    {
    int64_t tmp = value;
    ar.write((const char *) &tmp, sizeof(int64_t));
    }
};

/** partial specialization for std::vector */
template<class T>
class primitive< std::vector<T> > {
  public:
    template<class A>
    primitive(A & ar, const std::vector<T> &v)
    {
    uint32_t size = v.size();
    ar.write((const char *) &size, sizeof(uint32_t));
    ar.write((const char *) &v[0], sizeof(T) * size);
    }
};

}

/** A simple class to serialize object */
class binary_portable_oarchive {
  std::streambuf & fp;
  public:
       binary_portable_oarchive( std::ostream & os) : fp(*os.rdbuf()) { }
       ~binary_portable_oarchive() { }
       
  inline void write(const char *buf, int size)
  {
    fp.sputn(buf, size);
  }
  
  template<class T>
  inline void operator & (const T & value)
    {
      detail::primitive<T>(*this, value);
    }
};



/* HOW TO USE:

struct Object {
  int param1;
  int param2;
  int param3;
  int param4;

  template<class Archive>
  void serialize(Archive & ar)
    {
      ar & param1;
      ar & param2;
      ar & param3;
      ar & param4;
    }

};



  {
  std::ofstream stream("filename.bin");
  binary_portable_oarchive archive(stream);
  for(unsigned i=0;i<NumObj;i++)
      mem[i].serialize(archive);
  }
  
  */

#endif