How to store data from std :: vector <short> to std :: vector <uint8_t>
I want to save data in std::vector<short> in std::vector<uint8_t> , dividing each short into two uint8_t values. I need to do this because I have a network application that will only send std::vector<uint8_t> , so I need to convert to uint8_t to send and then convert back when I get the uint8_t vector.
Usually what I would do (and what I saw when I was looking for the problem):
std::vector<uint8_t> newVec(oldvec.begin(),oldvec.end());
However, if I understand correctly, this will take every single short value, crop to uint8_t size and make a new vector with half the amount of data and with the same number of records, when what I want is the same amount of data with twice as many records.
solutions that include a way to reverse the process and that avoiding copying would help as much as possible. Thanks!
I need to do this because I have a network application 1 which will send std :: vector
In addition to masking and shifting bits, you must consider entericity when sending material over the cable.
The network representation of data is usually large. Therefore, you can always transfer MSB. Provide a simple function, for example:
std::vector<uint8_t> networkSerialize(const std::vector<uint16_t>& input) { std::vector<uint8_t> output; output.reserve(input.size() * sizeof(uint16_t)); // Pre-allocate for sake of // performance for(auto snumber : input) { output.push_back((snumber & 0xFF00) >> 8); // Extract the MSB output.push_back((snumber & 0xFF)); // Extract the LSB } return output; } and use it like
std::vector<uint8_t> newVec = networkSerialize(oldvec); Watch a live demo .
1) Focus on
For splitting and merging, you must have the following:
unsigned short oldShort; uint8_t char1 = oldShort & 0xFF; // lower byte uint8_t char2 = oldShort >> 8; // upper byte Then click the two parts on the vector and send them to your network library. On the receiving side, during reassembly, you should read the next two bytes from the vector and combine them back into a short one.
Note. Make sure that the resulting vector has an even number of elements, so that during transportation you did not receive corrupted / modified data.
// Read off the next two characters and merge them again unsigned short mergedShort = (char2 << 8) | char1; Disclaimer: People talk about "network order." If you send something more than 1 byte, of course, you need to take into account the network endian . However, as I understand it, the restriction "network application that will only send std::vector<uint8_t> " explicitly indicates that "I do not want to interfere with any of these things." uint8_t already one byte, and if you send a sequence of bytes in the same order, you must return them in exactly the same order. This is useful: sending an array through a socket.
There may be a different system entity on the client and server machines, but the OP did not say anything about it, so this is a different story ...
Regarding the answer: Assuming all questions of "endianness" are closed. If you just want to send a short vector, I believe the VTT answer will work best. However, if std::vector<short> is just a special case, you can use the pack() function from my answer to a similar question . It packs any iterable container, string, C-string and much more ... into a byte vector and does not execute any endinnes shenanigans.
Just enable byte_pack.h , and then you can use it like this:
#include "byte_pack.h" void cout_bytes(const std::vector<std::uint8_t>& bytes) { for(unsigned byte : bytes) { std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex << byte << " "; } std::cout << std::endl; } int main() { std::vector<short> test = { (short) 0xaabb, (short) 0xccdd }; std::vector<std::uint8_t> test_result = pack(test); cout_bytes(test_result); // -> 0xbb 0xaa 0xdd 0xcc (remember of endianness) return 0; }