書きかけ及びパラメータパックの習作
std::format
という安全なsprintf
があるならばP言語のpack
/unpack
も比較的安全に作れるのでは?という思いつき
(boostのiotreams使えばいいという話もある)
cpp20
#include <iostream>
#include <vector>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <string>
#include <type_traits>
#include <concepts>
#include <array>
template<typename T>
concept Serializable = std::copyable<T> && !std::is_pointer_v<T>;
template<Serializable T>
std::vector<uint8_t> _pack(T num){
std::vector<uint8_t> r(sizeof(num));
memcpy(r.data(), &num, sizeof(num));
return r;
}
template<Serializable T, std::integral Tn, Tn m>
std::vector<uint8_t> _pack(T (&n)[m]){
auto size = sizeof(n);
std::vector<uint8_t> r(size);
memcpy(r.data(), n, size);
return r;
}
template<std::integral T>
struct rev{
const T &val;
};
template<std::integral T>
std::vector<uint8_t> _pack(rev<T> n){
auto size = sizeof(T);
std::vector<uint8_t> r(size);
auto b = _pack(n.val);
for(size_t i = 0; i < size; i++){
r[i] = b[size-i-1];
}
return r;
}
std::vector<uint8_t> _pack(std::vector<uint8_t> a){ return a; }
std::vector<uint8_t> _pack(std::string_view s){
std::vector<uint8_t> r(s.size()+1);
memcpy(r.data(), s.data(), s.size());
r[s.size()] = 0;
return r;
}
template<typename ... T>
std::vector<uint8_t> pack(T ...args){
std::vector<std::vector<uint8_t>> tmp{ _pack(args)... };
size_t total_size = 0;
for(const auto& it : tmp){ total_size += size(it); }
std::vector<uint8_t> result(total_size);
size_t offset = 0;
uint8_t* ptr = result.data();
for(const auto& it : tmp){
memcpy(ptr + offset, it.data(), size(it));
offset += size(it);
}
return result;
}
void display(std::vector<uint8_t> buf){
printf("length: %zu\n", buf.size());
for(const uint8_t& b : buf)
printf("%02X ", b);
puts("");
}
int main(){
uint16_t a[] = {1,2,3,4,0xFFEF};
auto b = pack(std::to_array(a), "1234567", rev<uint32_t>{0x123456}, uint32_t(0x987654));
display(b);
}