Как предложено πάντα ῥεῖ, функции ntohx()
/ htonx()
могут помочь вам преобразовать 16- и 32-битные беззнаковые интегралы из сетевого байтового порядка в хостовый порядок байтов и обратно.
Были некоторые проекты для включения шаблонов для ntoh()
и hton()
в заголовок C ++ <net>
, но, на самом деле, нет успеха.Вы, вероятно, найдете функции C в <Winsock2.h>
или <arpa/inet.h>
, чтобы вы могли создавать шаблоны самостоятельно.Пример:
#include <cstdint>
#ifdef _WIN32
#include <Winsock2.h>
#else
#include <arpa/inet.h>
#endif
template <class T>
T hton(T host) noexcept = delete;
template <>
uint8_t hton(uint8_t host) noexcept {
return host;
}
template <>
uint16_t hton(uint16_t host) noexcept {
return htons(host);
}
template <>
uint32_t hton(uint32_t host) noexcept {
return htonl(host);
}
template <class T>
T ntoh(T network) noexcept = delete;
template <>
uint8_t ntoh(uint8_t network) noexcept {
return network;
}
template <>
uint16_t ntoh(uint16_t network) noexcept {
return ntohs(network);
}
template <>
uint32_t ntoh(uint32_t network) noexcept {
return ntohl(network);
}
Имея их, вы можете создать шаблон класса-оболочки для ваших векторов с помощью потоковых операторов для сохранения и восстановления данных.Ниже приведен очень простой пример.При необходимости добавьте операторов и т. Д.
template <typename T>
class Data {
std::vector<T> m_data;
public:
Data() : m_data{} {}
template< class... Args >
auto emplace_back( Args&&... args ) {
return m_data.emplace_back(std::forward<Args>(args)...);
}
void reserve(typename std::vector<T>::size_type size) {
m_data.reserve(size);
}
bool operator==(const Data& o) {
return m_data == o.m_data;
}
template <typename V>
friend std::ostream& operator<<(std::ostream&, const Data<V>&);
template <typename V>
friend std::istream& operator>>(std::istream&, Data<V>&);
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const Data<T>& d) {
// write the number of entries first
const uint32_t count = hton(static_cast<const uint32_t>(d.m_data.size()));
os.write(reinterpret_cast<const char*>(&count), sizeof(count));
// write all the entries, converted to network byte order
for(auto v : d.m_data) {
v = hton(v);
os.write(reinterpret_cast<const char*>(&v), sizeof(v));
}
return os;
}
template <typename T>
std::istream& operator>>(std::istream& is, Data<T>& d) {
// read the number of entries first
uint32_t count;
is.read(reinterpret_cast<char*>(&count), sizeof(count));
d.m_data.resize(ntoh(count));
// read all the entries and convert to host byte order
for(auto& v : d.m_data) {
is.read(reinterpret_cast<char*>(&v), sizeof(v));
v = ntoh(v);
}
return is;
}
Тест:
#include <iostream>
#include <vector>
#include <sstream>
int main() {
Data<unsigned> orig;
Data<unsigned> copy;
std::stringstream ss;
orig.reserve(1024*1024);
for(unsigned i=0; i<1024*1024; ++i) orig.emplace_back(i);
ss << orig; // save to stream
// the data in 'ss' is now in network byte order
ss >> copy; // restore from stream
if(orig==copy) std::cout << "happy\n";
}