#include <iostream>
#include <fstream>
#include <string>
#include <vector>




template <class V>
void serialize(std::ofstream &outfile, std::vector<V> *v) {
    std::cout << "serialize vector" << std::endl;
    size_t b = v->size();
    outfile.write((char*)&b, sizeof(size_t));
    for (typename std::vector<V>::iterator iter = v->begin();
         iter != v->end();
         iter++) {
        V e = *iter;
        serialize(outfile, &e);
    }

    return;
}

template <class V>
void unserialize(std::ifstream &infile, std::vector<V> *v) {
    std::cout << "unserialize vector" << std::endl;

    size_t size;

    v->clear();

    infile.read((char *)(&size), sizeof(size_t));
    v->reserve(size);
    std::cout << "reserved size " << size << std::endl;
    for (size_t i = 0; i < size; i++) {
        V e;

        unserialize(infile, &e);
        v->push_back(e);
    }

    return;
}

template <typename V>
void serialize(std::ofstream &outfile, V *v) {
    std::cout << "serialize misc" << std::endl;
    outfile.write((char *)v, sizeof(V));
    return;
}

template <typename V>
void unserialize(std::ifstream &infile, V *v) {
    infile.read((char *)v, sizeof(V));
    std::cout << "unserialize thing '" << *v << "'" << std::endl;
    return;
}


template <>
void serialize<std::string>(std::ofstream &outfile, std::string *v) {
    std::cout << "serialize string '" << *v << "'" << std::endl;
    size_t len = v->length();
    serialize(outfile, &len);
    outfile.write((char *)(v->data()), sizeof(char) * len);
    return;
}

template <>
void unserialize<std::string>(std::ifstream &infile, std::string *v) {
    size_t r;
    unserialize(infile, &r);
    char *a = new char[r];
    infile.read(a, sizeof(char) * r);
    v->assign(a, r);

    std::cout << "unserialize string '" << a << "' == '" << *v << "'"<< std::endl;
    delete a;

    return;
}




int main() {
    int x = 4;
    std::string s = "w00t";
    size_t b = 232323243;
    std::vector<std::string> v;
    v.push_back("first");
    v.push_back("second");

    std::string filename = "user.serialized";
    std::ofstream outfile;
    outfile.open(filename.c_str());
    serialize(outfile, &x);
    serialize(outfile, &s);
    serialize(outfile, &b);
    serialize(outfile, &v);
    outfile.close();

    x = 666;
    v.clear();
    s.clear();
    b = 0;

    std::ifstream infile;
    infile.open(filename.c_str());
    unserialize(infile, &x);
    unserialize(infile, &s);
    unserialize(infile, &b);
    std::cout << "v size = " << v.size() << std::endl;
    unserialize(infile, &v);
    std::cout << "v size = " << v.size() << std::endl;
    infile.close();


    std::cout << x << std::endl;
    std::cout << s << std::endl;
    std::cout << b << std::endl;
    for(std::vector<std::string>::iterator iter = v.begin();
        iter != v.end();
        iter++) {
        std::cout << "[" << *iter << "] ";
    }
    std::cout << std::endl;

    return 0;
}
