Last active
May 7, 2018 13:08
-
-
Save sasq64/6e5e431824597fd2bdfcb8a0c4c5098e to your computer and use it in GitHub Desktop.
Serialization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <tuple> | |
#include <cstdio> | |
template<typename UnaryFunction> | |
void invoke_with_arg(UnaryFunction) | |
{} | |
/** | |
* Invoke the unary function with each of the arguments in turn. | |
*/ | |
template<typename UnaryFunction, typename Arg0, typename... Args> | |
void invoke_with_arg(UnaryFunction f, Arg0&& a0, Args&&... as) | |
{ | |
f(std::forward<Arg0>(a0)); | |
invoke_with_arg(std::move(f), std::forward<Args>(as)...); | |
} | |
template<typename Tuple, typename UnaryFunction, std::size_t... Indices> | |
void for_each_helper(Tuple&& t, UnaryFunction f, std::index_sequence<Indices...>) | |
{ | |
using std::get; | |
invoke_with_arg(std::move(f), get<Indices>(std::forward<Tuple>(t))...); | |
} | |
/** | |
* Invoke the unary function for each of the elements of the tuple. | |
*/ | |
template<typename Tuple, typename UnaryFunction> | |
void for_each(Tuple&& t, UnaryFunction f) | |
{ | |
using size = std::tuple_size<typename std::remove_reference<Tuple>::type>; | |
for_each_helper( | |
std::forward<Tuple>(t), | |
std::move(f), | |
std::make_index_sequence<size::value>() | |
); | |
} | |
template <class... Ts> | |
using void_t = void; | |
template <class T, class=void> struct has_fields : std::false_type{}; | |
template <class T> struct has_fields<T, void_t<decltype(std::declval<T>().fields())>> : std::true_type{}; | |
template <class T, class=void> struct has_pre : std::false_type{}; | |
template <class T> struct has_pre<T, void_t<decltype(std::declval<T>().pre_serialize())>> : std::true_type{}; | |
template <typename T> void Write(FILE *fp, const T& t) { | |
fwrite(&t, 1, sizeof(T), fp); | |
} | |
template <> void Write(FILE *fp, const std::string& t) { | |
Write(fp, t.length()); | |
fwrite(&t[0], 1, t.length(), fp); | |
} | |
template <class T, std::enable_if_t<has_fields<T>::value>* = nullptr> | |
void write_all(FILE *fp, T& t) | |
{ | |
for_each(t.fields(), [=](auto x) { | |
Write(fp, x); | |
}); | |
} | |
template <class T, std::enable_if_t<!has_fields<T>::value>* = nullptr> | |
void write_all(FILE *fp, const T& t) | |
{ | |
Write(fp, t); | |
} | |
template <class T, std::enable_if_t<has_pre<T>::value>* = nullptr> | |
void serialize(FILE *fp, T& t) | |
{ | |
t.pre_serialize(); | |
write_all(fp, t); | |
} | |
template <class T, std::enable_if_t<!has_pre<T>::value>* = nullptr> | |
void serialize(FILE *fp, T& t) | |
{ | |
write_all(fp, t); | |
} | |
//// | |
struct Test { | |
int a; | |
char b; | |
std::string d; | |
float c; | |
int _private; | |
void pre_serialize() { | |
printf("PRE SER!\n"); | |
d = "hello"; | |
} | |
auto fields() { | |
return std::tie(a,b,c,d); | |
} | |
}; | |
int main() | |
{ | |
Test t; | |
auto* fp = fopen("test.dat", "wb"); | |
serialize(fp, t); | |
fclose(fp); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment