64-bit Endianess Conversion

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

64-bit Endianess Conversion

Beitrag von Glocke » Fr Feb 07, 2014 5:20 pm

Hi,

ich habe für meine Netzwerk-Library [1] eine BinaryStream-Klasse, die Daten beim Einfügen in BigEndian konvertiert. Dabei verwende ich htons etc. Allerdings habe ich für 64-Bit-Typen (long long oder double) nichts derartiges gefunden - zumindest nicht in C++11 Standard. Notwendig sollte dies eigentlich schon sein (siehe Aufteilung von Mantisse und Exponenten bei double). Gibt es da schlicht und ergreifend einfach (noch) nichts im aktuellen Standard? Wie kann ich die Konvertierung am schnellsten durchführen?

LG Glocke

[1] https://github.com/cgloeckner/netLib

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: 64-bit Endianess Conversion

Beitrag von Xin » Fr Feb 07, 2014 5:49 pm

Grundsätzlich müsstest Du lediglich aus dem long long int zwei 32 Bit ints machen, z.B. durch ein Union.

Du hast ein vorderes und ein hinteres Int. Die beiden musst du zum einen vertauschen und dann auf beide hoch htons anwenden.
So sollte es gehen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 64-bit Endianess Conversion

Beitrag von Glocke » Fr Feb 07, 2014 5:55 pm

Also ich habe folgende Methode zum schreiben (lesen analog):

Code: Alles auswählen

template <typename T>
void BinaryStream::write(T const data) {
    std::size_t bytes = sizeof(T);
    T converted;
    // convert from host byte order to big endian
    switch (bytes) {
        case 1: // 8 bit, nothing to do
            converted = data;
            break;
    case 2: // 16 bit
        converted = htons(data);
        break;
    case 4: // 32 bit
        converted = htonl(data);
        break;
    //case 8: // 64 bit, nothing known to me
        //	break;
    default:
        return;
    }
    // append to buffer
    this->append(&converted, bytes);
}
Dabei unterscheide ich anhand sizeof(T) nach der Anzahl der Bytes für den jeweiligen Typ (Zeiger fange ich hier nicht ab - die gehören hier nicht rein). Prinzipiell will ich nur Primitivdaten einfügen, d.h. keine structs o.Ä. - Vermutlich müsste ich dazu für jeden einzelnen Typ die Methode überladen (so wie es bei SFML gemacht wurde). Das wollte ich vermeiden ^^

Joa also bräuchte ich eine Unterscheidung ob es ein long-long oder ein double ist, da ich beide ja anders konvertiere. D.h. mein Ansatz ist nicht geeignet, oder?

LG Glocke

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: 64-bit Endianess Conversion

Beitrag von Xin » Fr Feb 07, 2014 6:02 pm

Glocke hat geschrieben:Also ich habe folgende Methode zum schreiben (lesen analog):
...
Dabei unterscheide ich anhand sizeof(T) nach der Anzahl der Bytes für den jeweiligen Typ (Zeiger fange ich hier nicht ab - die gehören hier nicht rein). Prinzipiell will ich nur Primitivdaten einfügen, d.h. keine structs o.Ä. - Vermutlich müsste ich dazu für jeden einzelnen Typ die Methode überladen (so wie es bei SFML gemacht wurde). Das wollte ich vermeiden ^^

Joa also bräuchte ich eine Unterscheidung ob es ein long-long oder ein double ist, da ich beide ja anders konvertiere. D.h. mein Ansatz ist nicht geeignet, oder?
Nein, ich halte auch nix davon.

Code: Alles auswählen

void BinaryStream::write(char const * data, unsigned int size )
{ /* ... Daten schreiben ... */ }

template <typename T>
void BinaryStream::write(T const data);

template <>
inline void BinaryStream::write(long long int const data)
{ 
  char array[8]; 
  ...
  write( data, 8 ); // die eigentliche Funktion
}

template <>
inline void BinaryStream::write(float const data)
{ 
  ...
  write( static_cast< char * >( &data), 4 ); // die eigentliche Funktion
}

...
Fließkommazahlen werden nicht durch Endianess verändert.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: 64-bit Endianess Conversion

Beitrag von Glocke » Fr Feb 07, 2014 6:09 pm

Xin hat geschrieben:Fließkommazahlen werden nicht durch Endianess verändert.
Okay, das war mir nicht bewusst :D Dann werde ich das Template für long long überladen (wie ich es auch bei std::string gemacht habe ^^)

Danke :)

LG Glocke

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: 64-bit Endianess Conversion

Beitrag von mfro » Fr Feb 07, 2014 6:34 pm

Xin hat geschrieben: Fließkommazahlen werden nicht durch Endianess verändert.
Stimmt meiner Kenntnis nach nicht.

Zumindest die "großen" Plattformen, die ich als Big-Endian kenne (Sparc und Power) speichern Fließkommazahlen ebenso als Big-Endian ab.
Fließkommazahlen müssen also, wenn sie auf einem Little-Endian System eingelesen werden, genauso wie ints "rumgedreht" werden. Gerüchteweise soll es ARM-Prozessoren geben, die Integer Little-Endian und Fließkommazahlen Big-Endian ablegen.

Was es allerdings meiner Kenntnis nach nicht gibt, ist die Definition einer "Network Byte Order" (also ein standardisiertes Übertragungsformat). Im Gegensatz zu den Integer-Formaten definiert die IEEE nicht, was "richtig" ist.
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Antworten