2009-09-23 16 views
16

Ich bin auf der Suche nach einem C++ "Äquivalent" von Java ByteBuffer.C++ entspricht Java ByteBuffer?

Ich vermisse wahrscheinlich das Offensichtliche oder brauche nur ein isoliertes Anwendungsbeispiel zur Klärung. Ich habe durch die Iostream-Familie & geschaut es sieht aus wie es eine Grundlage liefern kann. Insbesondere möchte ich in der Lage sein:

  • Erstellen Sie einen Puffer von einem Byte Array/Punkt und erhalten Grundelemente aus dem Puffer, z. getByte, getInt
  • bauen Sie einen Puffer mit Primitiven z. putByte, putInt und dann das Byte Array/Pointer.
+0

Es ist wichtig zu beachten, dass in 'bekommen (T)' und 'setzen (T)', 'T' ist * nicht *' byte'. Es sind * andere * primitive Typen wie 'int',' float' und 'short'. –

+0

Ja, es war eine unglückliche Wahl, mich zu benennen. Ich habe das klarer gemacht. – hplbsh

Antwort

14

Sie haben stringbuf, filebuf oder Sie vector<char> nutzen könnten.


Dies ist ein einfaches Beispiel mit 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 

Dank @Pete Kirkham für die Idee der allgemeinen Funktionen.

#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); 
} 
+1

Dies wäre ein besseres Beispiel, wenn das aus dem Puffer extrahierte Objekt kein anderes Array von Zeichen wäre. 'ByteBuffer' erlaubt das Extrahieren * anderer * primitiver Typen aus dem Byte-Puffer, nicht nur Bytes. http://java.sun.com/j2se/1.4.2/docs/api/java/nio/ByteBuffer.html –

+0

Meine Wahl von get (T) und Put (T) als Beispiele war eher schlecht; Ich möchte variable Größen aus dem Puffer extrahieren. std :: stringbuf fühlt sich an wie die richtige Richtung. Vielen Dank. – hplbsh

+0

Es basiert nicht auf Zeichen. Vielleicht ist std :: streambuf in diesem Fall eine bessere Wahl, obwohl beide funktionieren sollten. – hplbsh

3
std::vector<char> bytes; 

bytes.push_back(some_val); // put 

char x = bytes[N];   // get 

const char* ptr = &bytes[0]; // pointer to array 
8

stringstream bietet grundlegende unformatierte get und write Operationen zum Schreiben von Blöcken von Zeichen. Zur Spezialisierung auf T entweder Unterklasse oder Umbruch, oder bieten freistehende Template-Funktionen zur Verwendung der Get/Write Speicher entsprechend der Größe.

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

Sie könnten solche Vorlagen schreiben, was auch immer für andere Stream oder Vektor Sie wollen - im Fall des Vektor, würde es braucht Einsatz zu verwenden, anstatt zu schreiben.

+0

Schöne Lösung :) Ich denke Streams sind mehr ein Werkzeug zum Lesen und Schreiben * formatierte Daten *. Warum sollte ich einen Stream wie einen Puffer verwenden, in dem sich ein Puffer befindet. Dennoch denke ich, dass Ihre generischen Funktionen eine ausgezeichnete Idee sind. – AraK

+0

Ich bevorzuge Streams, wie ich den Zwang, bool und das Idiom der Rückkehr der Stream für die Verkettung, lieber als die Puffer die Anzahl der Bytes geschrieben und um diese Probe herumspielen versuchen. –

1

Vielen Dank für die Eingabe, hat es auf diese ziemlich einfache Lösung führen:


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

Zur Verwendung zB:


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); 
} 
+1

-1: Ich mag die Idee, dass Sie ein std :: stringbuf unterklassifizieren. Verwenden Sie stattdessen die Komposition. Die meisten Typen in diesem Namespace sind nicht dafür ausgelegt. Warum verwenden Sie auch size_t? – Arafangion

4

ich diese eine Weile zurück schrieb genau das zu tun, was Sie fragen zum. Geben Sie ihm einen Schuss:

https://code.google.com/p/bytebuffer-cpp/

+0

Dies scheint nicht mit Byte-Reihenfolge Unterschiede für ganzzahlige Typen umzugehen, wenn der Schreiber und Leser auf verschiedenen Architekturen ausgeführt werden. Ich denke Java's ByteBuffer ist standardmäßig Big Endian, bietet aber die Möglichkeit, die Byte-Reihenfolge zu ändern. Irgendwelche Alternativen? – Hoobajoob