С++ эквивалент Java ByteBuffer?
Я ищу С++-эквивалент Java ByteBuffer.
Мне, вероятно, не хватает очевидного или просто нужно использовать изолированный пример использования, чтобы уточнить. Я просмотрел семейство iostream, и похоже, что это может послужить основой. В частности, я хочу иметь возможность:
- создать буфер из байтового массива/точки и получить примитивы из буфера, например. getByte, getInt
- создать буфер с использованием примитивов, например. putByte, putInt, а затем получить байтовый массив/указатель.
Ответы
Ответ 1
У вас есть stringbuf
, filebuf
или вы можете использовать vector<char>
.
Это простой пример, используя stringbuf
:
std::stringbuf buf;
char data[] = {0, 1, 2, 3, 4, 5};
char tempbuf[sizeof data];
buf.sputn(data, sizeof data); // put data
buf.sgetn(tempbuf, sizeof data); // get data
Спасибо @Pete Kirkham за идею общих функций.
#include <sstream>
template <class Type>
std::stringbuf& put(std::stringbuf& buf, const Type& var)
{
buf.sputn(reinterpret_cast<const char*>(&var), sizeof var);
return buf;
}
template <class Type>
std::stringbuf& get(std::stringbuf& buf, Type& var)
{
buf.sgetn(reinterpret_cast<char*>(&var), sizeof(var));
return buf;
}
int main()
{
std::stringbuf mybuf;
char byte = 0;
int var;
put(mybuf, byte++);
put(mybuf, byte++);
put(mybuf, byte++);
put(mybuf, byte++);
get(mybuf, var);
}
Ответ 2
stringstream
предоставляет основные неформатированные операции get
и write
для записи блоков символов. Специализировать на T
любом подклассе или обернуть его или предоставить бесплатные постоянные функции шаблонов для использования памяти с соответствующим размером.
template <typename T>
std::stringstream& put ( std::stringstream& str, const T& value )
{
union coercion { T value; char data[ sizeof ( T ) ]; };
coercion c;
c.value = value;
str.write ( c.data, sizeof ( T ) );
return str;
}
template <typename T>
std::stringstream& get ( std::stringstream& str, T& value )
{
union coercion { T value; char data[ sizeof ( T ) ]; };
coercion c;
c.value = value;
str.read ( c.data, sizeof ( T ) );
value = c.value;
return str;
}
Вы можете написать такие шаблоны для любого другого потока или вектора, который вы хотите - в векторном случае ему нужно будет использовать вставку, а не запись.
Ответ 3
Я написал это некоторое время назад, чтобы сделать именно то, о чем вы просите. Сделайте снимок:
https://code.google.com/p/bytebuffer-cpp/
Ответ 4
std::vector<char> bytes;
bytes.push_back( some_val ); // put
char x = bytes[N]; // get
const char* ptr = &bytes[0]; // pointer to array
Ответ 5
Спасибо за все входные данные, это привело к этому довольно простому решению:
class ByteBuffer : std::stringbuf
{
public:
template
size_t get( T &out)
{
union coercion { T value; char data[ sizeof ( T ) ]; };
coercion c;
size_t s= xsgetn( c.data, sizeof(T));
out= c.value;
return s;
}
template
size_t put( T &in)
{
union coercion { T value; char data[ sizeof ( T ) ]; };
coercion c;
c.value= in;
return xsputn( c.data, sizeof(T));
}
size_t get( uint8_t *out, size_t count)
{
return xsgetn((char *)out, count);
}
size_t put( uint8_t *out, size_t count)
{
return xsputn((char *)out, count);
}
};
Чтобы использовать, например:
void ByteBufferTest( void)
{
ByteBuffer bb;
float f= 4;
uint8_t u8= 1;
uint16_t u16= 2;
uint32_t u32= 4;
uint64_t u64= 8;
bb.put(f);
bb.put(u8);
bb.put(u16);
bb.put(u32);
bb.put(u64);
uint8_t array[19];
bb.get( array, 19);
// or
bb.get(f);
bb.get(u8);
bb.get(u16);
bb.get(u32);
bb.get(u64);
}
Ответ 6
для std::vector более эффективным является метод
push_back(T)
Вы можете найти больше здесь:
http://www.cppreference.com/wiki/stl/vector/start
и вообще о cpp stl libs
http://www.cppreference.com/wiki/stl/start
Существует много контейнеров, зависит от того, что вам нужно,
- агрегация скорости (возможность быстрой записи)
или
- быстрый просмотр
взгляните на std:: list, std::vector.