views:

1050

answers:

5

I'm looking for a C++ "equivalent" of Java ByteBuffer.

I'm probably missing the obvious or just need an isolated usage example to clarify. I've looked through the iostream family & it looks like it may provide a basis. Specifically, I want to be able to:

  • build a buffer from a byte array/point and get primitives from the buffer, e.g. getByte, getInt
  • build a buffer using primitives e.g. putByte, putInt and then get the byte array/pointer.
+4  A: 

You have stringbuf, filebuf or you could use vector<char>.


This is a simple example using 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


Thanks @Pete Kirkham for the idea of generic functions.

#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);
}
AraK
This would be a better example if the thing being extracted from the buffer weren't another array of char. `ByteBuffer` allows extracting *other* primitive types from the byte buffer, not just bytes. http://java.sun.com/j2se/1.4.2/docs/api/java/nio/ByteBuffer.html
Rob Kennedy
My choice of get(T) and put(T) as examples was rather poor; I would like to extract variable sizes from the buffer.std::stringbuf feels like the right direction. Thanks.
Stuart
Its non-character based. Perhaps std::streambuf is a better choice in this case though they both ought to be workable.
Stuart
Aha. streambuf is an abstract class, stringbuf is just called stringbuf but that doesn't mean it is character based. It is just a buffer of bytes. but the type of elements is char which is why called (string)buf.
AraK
+1  A: 
std::vector<char> bytes;

bytes.push_back( some_val ); // put

char x = bytes[N];           // get

const char* ptr = &bytes[0]; // pointer to array
Kirill V. Lyadvinsky
A: 

for std::vector more efficient is method

push_back(T)

You can find more here:

http://www.cppreference.com/wiki/stl/vector/start

and general about cpp stl libs

http://www.cppreference.com/wiki/stl/start

There are many containers, depends what do You need it for,

  • speed aggregation (fast writing capabilities) or
  • fast read

take a look at std::list, std::vector.

bua
+6  A: 

stringstream provides basic unformatted get and write operations to write blocks of chars. To specialise on T either subclass or wrap it, or provide free standing template functions to use the get/write appropriately sized memory.

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;
}

You could write such templates for whatever other stream or vector you want - in the vector's case, it would need to use insert rather than write.

Pete Kirkham
Nice solution :) I think streams are more a tool to read and write *formatted data*. Why would I use a stream like a buffer, where inside the stream there is a buffer. Still, I think your generic functions are excellent idea.
AraK
I tend to prefer streams as I like the coercion to bool and the idiom of returning the stream for chaining, rather than the buffer's returning of the number of bytes written and having to fiddle around testing that.
Pete Kirkham
+2  A: 
Stuart