# [C++] Bit-Operationen auf String



## Bgag (7. Februar 2011)

Hallo!

Ich beschäftige mich aktuell mit einem Algorithmus, der es erforderlich macht, an einen String ein einzelnes "1" Bit anzuhängen und dann den String durch anhängen von "0" Bits auf Länge Kongruent 448, modulo 512 zu bringen. Dies soll auch geschehen, falls der String schon eine Länge von 448 Bit (modulo 512) hat.

Anschließend soll die Länge des Strings als 64 Bit Zahl an den String angehängt werden, sodass die resultierende Länge des Strings nun ein vielfaches von 512 ist. Sollte die Länge größer als 64 Bit sein, sollen nur die 64 niederwertigen Bits angehängt werden.

Würde mich freuen, wenn mir jemand sagen könnte, wie ich eine solche Methode implementieren kann.

Liebe Grüße,

Andreas


----------



## CPoly (7. Februar 2011)

Erstmal hab ich Fragen zu deinem Problem:

1. C (char *) oder C++ (std:string) ?
Edit: Hab jetzt erst den Titel gesehen.

2. Du redest von "Bits anhängen", aber die kleinste Einheit ist ein Byte. Soll der String also eine Länge (Anzahl der Zeichen) haben, welche durch 512 einen Rest von 448 ergibt? Oder soll die Länge geteilt durch 64 einen Rest von 56 ergeben?
3. Wie zum Teufel soll die Länge eines Strings nicht mehr in einen 64 Bit unsigned integer passen? Das wären 128 Exabyte, sofern ich mich nicht verrechnet habe.

Ansonsten: Wo hängts denn? Ein string ist ein char-Array. Ein char hat 8 bit, ist also genau ein byte. In C kannst du mit char rechnen wie mit Zahlen, also sollte das doch alles kein Problem sein.


----------



## Bgag (7. Februar 2011)

Hallo.

Danke erstmal für deine schnelle Antwort. Habe nachfolgend mal versucht deine Fragen zu beantworten. 



CPoly hat gesagt.:


> C (char *) oder C++ (std:string) ?



Es ist eigentlich egal, da ich mit einem C++ std::string arbeite und so mit der Methode c_str() auf das Char Array zugreifen kann.



CPoly hat gesagt.:


> Du redest von "Bits anhängen", aber die kleinste Einheit ist ein Byte. Soll der String also eine Länge (Anzahl der Zeichen) haben, welche durch 512 einen Rest von 448 ergibt? Oder soll die Länge geteilt durch 64 einen Rest von 56 ergeben?



Genau das Problem hatte ich auch. Es sollen allerdings tatsächlich Bits angehängt werden. Nachfolgend ein kleiner Ausschnitt aus dem entsprechenden RFC.



> 3.1 Step 1. Append Padding Bits
> 
> 
> The message is "padded" (extended) so that its length (in bits) is
> ...





CPoly hat gesagt.:


> Wie zum Teufel soll die Länge eines Strings nicht mehr in einen 64 Bit unsigned integer passen? Das wären 128 Exabyte, sofern ich mich nicht verrechnet habe.



Ich weiß auch, dass das eigentlich nicht vorkommen sollte, aber der Algorithmus sieht es, wie du oben sehen konntest, so vor.

Liebe Grüße,

Andreas


----------



## deepthroat (7. Februar 2011)

Hi.

Warum sagst du denn nicht gleich, das es um den MD4 Algorithmus geht?

Und wie kommst du auf String? Die Rede ist von einer Nachricht, also einer Bitfolge. Die Verarbeitung erfolgt wortweise (16Bit).

Das was der Abschnitt aus dem RFC sagt, ist lediglich, dass du die Nachricht so ausrichten mußt, dass die Länge der Nachricht am Ende ein Vielfaches von 512 ist. Das muß man aber nicht wirklich so machen. Verarbeite einfach alle Daten und zum Schluss erzeuge die Padding Daten (so muß man die Nachricht nicht doppelt lesen falls die Größe nicht durch andere Funktionen ermittelt werden kann).

Man findet mit Sicherheit auch Implementierungen von MD4 im Netz...

Gruß


----------



## Bgag (7. Februar 2011)

deepthroat hat gesagt.:


> Warum sagst du denn nicht gleich, das es um den MD4 Algorithmus geht?



Fast richtig. Es geht um MD5.



deepthroat hat gesagt.:


> Und wie kommst du auf String? Die Rede ist von einer Nachricht, also einer Bitfolge. Die Verarbeitung erfolgt wortweise (16Bit).





deepthroat hat gesagt.:


> Das was der Abschnitt aus dem RFC sagt, ist lediglich, dass du die Nachricht so ausrichten mußt, dass die Länge der Nachricht am Ende ein Vielfaches von 512 ist. Das muß man aber nicht wirklich so machen. Verarbeite einfach alle Daten und zum Schluss erzeuge die Padding Daten (so muß man die Nachricht nicht doppelt lesen falls die Größe nicht durch andere Funktionen ermittelt werden kann).



Das kann ich leider nicht ganz nachvollziehen. Die Padding Daten müssen doch zu Anfang erzeugt werden, sodass die nachfolgenden Transformationen überhaupt ausgeführt werden können.



deepthroat hat gesagt.:


> Man findet mit Sicherheit auch Implementierungen von MD4 im Netz...



Natürlich findet man im Netz auch Implementationen in C/C++, sogar Massenweise, darunter vorallem sehr umständliche, falsche und schlecht dokumentierte. Sogar das RFC 1312 selbst enthält eine Implementierung in C. Leider komme ich um eine eigene Implementation nicht rum. Sie ist Teil eines Fach-Praktikums.

Wenn ich es nun richtig verstanden habe, muss ich meinen String in ein Byte Array umwandeln.


```
unsigned char *buffer = input.c_str();
```

Danach kann ich nun das Anfügen und das Anpassen der Größe vornehmen. Aber wie mache ich das?

Später operiere ich dann ja auf einem Array von 64 Bytes, also 512 Bits.

Liebe Grüße,

Andreas


----------



## Matthias Reitinger (7. Februar 2011)

Avedo hat gesagt.:


> Das kann ich leider nicht ganz nachvollziehen. Die Padding Daten müssen doch zu Anfang erzeugt werden, sodass die nachfolgenden Transformationen überhaupt ausgeführt werden können.


Ich hab den MD5-Algorithmus jetzt nicht exakt im Kopf, aber soweit ich mich erinnere, muss man den String doch nur einmal durchlaufen, oder nicht? Dann reicht es doch, wenn du die Padding-Bits „on demand“ generierst, nämlich genau dann wenn du am Ende des Strings angekommen bist.



Avedo hat gesagt.:


> Wenn ich es nun richtig verstanden habe, muss ich meinen String in ein Byte Array umwandeln.
> 
> 
> ```
> ...


Musst du nicht unbedingt. Du kannst über string::append Zeichen an den String anhängen (zuerst '\x80' und dann so oft '\0' bis du bei einem Vielfachen von 56 Zeichen in der Gesamtlänge angekommen bist).

Grüße,
Matthias


----------



## Bgag (7. Februar 2011)

Guten Abend!

Habe nochmal versucht das Programm zum Laufen zu bringen. Dabei bin ich ein ganzes Stück weiter gekommen und ich glaube nun auch einiges verstanden zu haben.

Leider geht zur Zeit irgendwo, aus mir nicht ganz erklärlichen Gründen, noch etwas in die Hose. Ich befürchte, dass noch etwas bei der Umrechnung von uint64 in einen Binär-String fehlschlägt. Der betreffende Abschnitt findet sich, zusammen mit der Anpassung der Länge des Strings, in der Methode preprocess().

Wäre super, wenn jemand mal einen Blick auf die Klasse werfen könnte. Habe das komplette Programm als *.zip-Archiv in den Anhang gepackt. Ein Minimal-Beispiel und ein Makefile zur einfacheren Kompilierung liegt ebenfalls bei.

Liebe Grüße,

Andreas

*PS:* Das Resultat der Ausführung des Beispiels sollte "9e107d9d372bb6826bd81d3542a419d6" sein.


----------



## Bgag (8. Februar 2011)

Guten Morgen!

Habe gestern und heute noch etwas an meinem Programm gearbeitet und noch ein paar Fehler behoben. Leider wird immer noch nicht der richtige Hash-Code erzeugt. Woran das liegt, weiß ich leider nicht. Ich bin den Algorithmus eigentlich noch einmal Schritt für Schritt durchgegangen.

Wäre super, wenn jemand von euch noch einmal drauf schaun könnte. Die neue Version habe ich am Ende angehängt.

Liebe Grüße,

Andreas


----------



## Matthias Reitinger (8. Februar 2011)

Hallo,

ich sehe da einige potenzielle Probleme mit deiner Implementierung. Zuerst mal deine typedefs — auf einem 64-Bit-System könntest du damit Probleme kriegen. Dein uint32 hat bei mir beispielsweise 64 Bits, womit die ganze Modulo-2^32-Arithmetik den Bach runter geht. Du könntest stattdessen die Typen aus cstdint verwenden, falls vorhanden. Bei der Intialisierung von state hast du denke ich die Bytesortierung falsch rum.

Verwende am besten eine Beispielimplementierung, die die Zwischenzustände mit ausgibt, um die Fehler einzugrenzen.

Grüße,
Matthias


----------



## Bgag (9. Februar 2011)

Guten Morgen!

Danke für deine Hilfe. Bin ein ganzes Stück weiter gekommen. Habe nun jedoch ein Problem. Lustiger Weise wird der Hash-Code von "The quick brown fox jumps over the lazy dog" korrekt erzeugt. Gebe ich jedoch eine zu verwendende Datei an oder übergebe zum Beispiel "Hallo Welt", so wird ein falscher Hash erzeugt.

Durch das Einfügen einiger Ausgaben und deren Abgleich mit der Ausgabe des von dir oben erwähnten Tools, konnte ich herausfinden, dass der Fehler bereits in der Initialisierung auftritt. Weder die Umwandlung des String ansich noch das Anhängen des einzelnen Bits, das Auffüllen mit Nullen und das Anhängen der String Länge, scheint zu funktionieren.

Es muss also im folgenden Abschnitt etwas Schief laufen.


```
// Get the size of the unpadded message.
	uint64 inputLength = input.size() * 8;

	// Append a single '1' bit, ...
	input.append(1, '\x80');

	// ... and then the '0' bit until the string length is congruent to 56 modulo 64.
	input.append(56 - (input.size() % 64), '\0');

	// Finally append the length of unpadded message as 64-bit little-endian integer to message.
	char chLen[8];
	chLen[7] = (unsigned char) ((inputLength >> 56) & 0xff);
	chLen[6] = (unsigned char) ((inputLength >> 48) & 0xff);
	chLen[5] = (unsigned char) ((inputLength >> 40) & 0xff);
	chLen[4] = (unsigned char) ((inputLength >> 32) & 0xff);
	chLen[3] = (unsigned char) ((inputLength >> 24) & 0xff);
	chLen[2] = (unsigned char) ((inputLength >> 16) & 0xff);
	chLen[1] = (unsigned char) ((inputLength >> 8) & 0xff);
	chLen[0] = (unsigned char) (inputLength & 0xff);
	input.append(chLen, 8);

	return input;
```

Im Anhang habe ich auch nochmal die komplette überarbeitete Version angehängt.

Würde mich sehr freun, wenn jemand von euch noch einen Blick darauf werfen könnte.

Liebe Grüße,

Andreas


----------



## deepthroat (9. Februar 2011)

Hi.





Avedo hat gesagt.:


> ```
> // ... and then the '0' bit until the string length is congruent to 56 modulo 64.
> input.append(56 - (input.size() % 64), '\0');
> ```


Irgendwas kann hier nicht stimmen. Das Ergebnis von modulo 64 kann 0 bis 63 sein. 56 - 63 = -7.

Zufällig hat "The quick brown fox jumps over the lazy dog" genau die richtige Größe, so das es dann passt.

Wie schon gesagt, ist diese Vorverarbeitung unnötig. Du kopierst die Daten 3fach umher ohne wirklich etwas mit ihnen anzustellen.

Gruß


----------



## Bgag (9. Februar 2011)

Hallo!

Danke für deine Antwort.



deepthroat hat gesagt.:


> Irgendwas kann hier nicht stimmen. Das Ergebnis von modulo 64 kann 0 bis 63 sein. 56 - 63 = -7.



Das stimmt allerdings. Habe den entsprechenden Part mal wie folgt abgeändert. Das funktioniert auch ganz gut.


```
// Get the size of the unpadded message.
	uint64 inputLength = input.size() * 8;

	// Append a single '1' bit, ...
	input.append(1, '\x80');

	// ... calculate the index ...
	size_t index = input.size() % 64;

	// ... and the padding length ...
	size_t padLen = (index < 56) ? (56 - index) : (120 - index);

	// ... and then the '0' bit until the string length is congruent to 56 modulo 64.
	input.append(padLen, '\0');

	// Finally append the length of unpadded message as 64-bit little-endian integer to message.
	char chLen[8];
	chLen[0] = (unsigned char) (inputLength & 0xff);
	chLen[1] = (unsigned char) ((inputLength >> 8) & 0xff);
	chLen[2] = (unsigned char) ((inputLength >> 16) & 0xff);
	chLen[3] = (unsigned char) ((inputLength >> 24) & 0xff);
	chLen[4] = (unsigned char) ((inputLength >> 32) & 0xff);
	chLen[5] = (unsigned char) ((inputLength >> 40) & 0xff);
	chLen[6] = (unsigned char) ((inputLength >> 48) & 0xff);
	chLen[7] = (unsigned char) ((inputLength >> 56) & 0xff);
	input.append(chLen, 8);

	return input;
```

Leider bleibt noch ein letztes Problem. Irgendwie geht etwas beim setzen von '\x80' schief. Er trägt mir an dieser Stelle den falschen Wert ein. Hat dazu vielleicht noch jemand eine Idee.



deepthroat hat gesagt.:


> Wie schon gesagt, ist diese Vorverarbeitung unnötig. Du kopierst die Daten 3fach umher ohne wirklich etwas mit ihnen anzustellen.



Das mag sein, aber ich habe leider keinen blassen Schimmer, wie ich es aktuell anders lösen sollte. Zu einem Beispiel sage ich natürlich nicht nein. 

Liebe Grüße,

Andreas


----------



## Matthias Reitinger (9. Februar 2011)

Avedo hat gesagt.:


> Das mag sein, aber ich habe leider keinen blassen Schimmer, wie ich es aktuell anders lösen sollte. Zu einem Beispiel sage ich natürlich nicht nein.


Durchlaufe den Original-String (ohne das Padding) in ganzen 64-Byte-Blöcken. Am Ende bleibt im Allgemeinen noch ein Stück <64 Byte am Ende des Strings übrig. Schreibe dieses an den Anfang von block und fülle den Rest mit dem Padding auf. Führe mit diesem Block jetzt noch eine letzte Runde durch. Du musst aber noch ein paar Fälle unterscheiden, z.B. wenn das Padding nicht mehr in den Block passt (du müsstest dann noch einen weiteren Block generieren).

\edit: 





Avedo hat gesagt.:


> Leider bleibt noch ein letztes Problem. Irgendwie geht etwas beim setzen von '\x80' schief. Er trägt mir an dieser Stelle den falschen Wert ein. Hat dazu vielleicht noch jemand eine Idee.


Wie hast du das verifiziert?

Grüße,
Matthias


----------



## Bgag (9. Februar 2011)

Matthias Reitinger hat gesagt.:


> Durchlaufe den Original-String (ohne das Padding) in ganzen 64-Byte-Blöcken. Am Ende bleibt im Allgemeinen noch ein Stück <64 Byte am Ende des Strings übrig. Schreibe dieses an den Anfang von block und fülle den Rest mit dem Padding auf. Führe mit diesem Block jetzt noch eine letzte Runde durch. Du musst aber noch ein paar Fälle unterscheiden, z.B. wenn das Padding nicht mehr in den Block passt (du müsstest dann noch einen weiteren Block generieren).



Vielen Dank für diese Erläuterungen. Werde nun erstmal versuchen meine aktuelle Version zum Laufen zu bekommen. In einer späteren Version versuche ich dann diesen Punkt zu verbessern.



Matthias Reitinger hat gesagt.:


> Wie hast du das verifiziert?



Ich habe mir einfach mal alle Blöcke ausgeben lassen. Alle werden richtig erzeugt. Allerdings tritt genau an der Stelle, an der das einzelne Bit eingefügt wird ein Fehler auf. 

*Ein Beispiel:* Möchte ich die Nachricht "_Hallo du kleine Welt. Es ist ein schoener Tag_" verarbeiten, erhalte ich die folgenden Blöcke.



> block[0] = 6c6c6148
> block[1] = 7564206f
> block[2] = 656c6b20
> block[3] = 20656e69
> ...



Aussehen sollte es aber wie folgt.



> block[0] = 6c6c6148
> block[1] = 7564206f
> block[2] = 656c6b20
> block[3] = 20656e69
> ...



Der Unterschied findet sich in Block 11, an dessen Stelle die Nachricht zu Ende ist und das Bit eingefügt wird. Dort steht bei mir _ffff8067_ anstatt _00008067_, wie es der von dir vorgstellte MD5-Generator tut, der auch den richtigen Hash erzeugt.

Ich habe leider keine Ahnung, woran das liegen kann. Hat jemand von euch dazu eine Idee?

Liebe Grüße

Andreas

*EDIT:* Habe gerade noch ein paar Tests durchgeführt und es scheint generell noch ein Problem mit dem Padding zu geben. Der Rest ist in Ordnung.


----------



## deepthroat (10. Februar 2011)

Hi.





Avedo hat gesagt.:


> Der Unterschied findet sich in Block 11, an dessen Stelle die Nachricht zu Ende ist und das Bit eingefügt wird. Dort steht bei mir _ffff8067_ anstatt _00008067_, wie es der von dir vorgstellte MD5-Generator tut, der auch den richtigen Hash erzeugt.
> 
> Ich habe leider keine Ahnung, woran das liegen kann. Hat jemand von euch dazu eine Idee?


signed / unsigned Problem.

Verwende std::basic_string<unsigned char> und füge 0x80 statt '\x80' hinzu.

Gruß


----------



## Bgag (10. Februar 2011)

Hallo!

Vielen Dank für deine Hilfe, euer aller Hilfe. Habe leider nur begrenzt Daumen.

Das Programm läuft nun, auch wenn ich mich gerade noch etwas verrückt gemacht habe, da ich einen anderen Hash aus einer Datei generiert habe, als der oben gepostete MD5-Generator. Allerdings habe ich dann meinen Hash mit der Ausgabe des unter XUbuntu automatisch verfügbaren Programms _md5sum_ verglichen und das hat das gleiche Resultat geliefert.

Das Programm unterstützt nun die Verarbeitung von Dateien unter angabe des Dateipfades, von Strings, die mit -s, Testfällen und Zeit-Tests, die mit -x und -t angegeben werden können. Die Befehle können natürlich auch wild hintereinander geschrieben werden.

*Beispiele:*

```
./md5 -x
./md5 ~/Videos/myvideo.avi
./md5 -t ~/Videos/myvideo.avi
./md5 -s "The quick brown fox jumps over the lazy dog"
./md5 -t -s "Bli Bla Blubb" ~/Videos/vid1.avi -t ~/Videos/vid2.avi -x
```

Das komplette Programm findet man nochmal im Anhang.

Liebe Grüße

Andreas

*PS:* Das Programm konnte den Hash einer 704MB großen *.avi Datei in nur 3.64 Sekunden bilden.

*PSS:* Komischer Weise gab es im übrigen Probleme, wenn ich Dateien mit dem C++ ifstream anstatt des C FILE-Handles gelesen habe. Welchen Grund könnte das haben?

*EDIT:* Er frisst zwar vieles, jedoch hat er bei großen Dateien Probleme. Woran kann das liegen.


----------



## sheel (10. Februar 2011)

Was sind große Dateien? >2GB?


----------



## Bgag (11. Februar 2011)

Nein leider nicht. Nach der Umstellung auf C-FILE Handles kann ich schon Dateien von 700 mb nicht mehr verarbeiten.


----------



## Matthias Reitinger (11. Februar 2011)

Kein Wunder, du liest die Dateien schließlich ohne guten Grund komplett in den Speicher ein. Du solltest eine Methode anbieten, die es erlaubt, eine Zeichenkette Stück für Stück an deine Klasse zu übergeben. Diese sollte den den Hashwert dann inkrementell berechnen.

Grüße,
Matthias


----------



## Bgag (11. Februar 2011)

Ich habe nun das Programm so abgeändert, dass Strings und Dateien unterschiedlich behandelt werden. Es kommt nun auch zu einer Blockweisen Verarbeitung, an deren Ende erst das Padding vorgenommen wird.

Dank dieser Änderungen funktioniert nun auch die Verarbeitung beliebig großer Dateien ohne Probleme.

Vielen Dank an alle Helfer. Die neueste Version habe ich angehängt.

Liebe Grüße

Andreas


----------



## deepthroat (11. Februar 2011)

Hi.

Einige Probleme / Verbesserungen:

- verwende konstante Referenzen als Argumente (du kopiert unnötig Daten beim jedem Aufruf)
- Fehler falls \0 Zeichen im String enthalten sind bei hashString(std::string)
- duplizierter Code - hashString(std::string) und hashString(std::basic_string<unsigned char> unterscheiden sich fast gar nicht voneinander
- feof ist evtl. erst gesetzt wenn versucht wurde hinter das Ende der Datei zu lesen, falls die Dateigröße ein Vielfaches von 1024 ist, wird der Check innerhalb der while Schleife in hashFile nie aufgerufen
- verarbeite Strings doch ebenfalls wie bei Dateien (im Grunde brauchst du nur eine allgemeine Funktion die auf Daten arbeitet -- da pumpst du Daten rein und finalisierst dann irgendwann mal)
Bsp:

```
md5 hash; // ruft init() auf. bzw. initialsiert im Konstruktor
hash.update(std::string("alblual"));
hash.update("asdfa");
char x[] = ...;
hash.update(x);
hash.digest(); // finalisiert und gibt digest zurück
hash.hex_digest(); // gibt einen hex digest zurück
md5 file_hash;
file_hash.update(ifstream("bla.blub"));
// usw.
```
- warum sind init(), append() und transform() public?

Gruß


----------



## Bgag (12. Februar 2011)

Hallo!



deepthroat hat gesagt.:


> ... verwende konstante Referenzen als Argumente (du kopiert unnötig Daten beim jedem Aufruf) ...



Guter Hinweis. Werde ich ändern. Wäre es denn nicht auch sinnvoll roundRot und radians als static const direkt in der Header Datei zu initialisieren. Die ändern sich doch eigentlich nie.



deepthroat hat gesagt.:


> Fehler falls \0 Zeichen im String enthalten sind bei hashString(std::string)



Wie kann ich das ändern? Das \0 Zeichen maskiert doch das Ende eines Strings.



deepthroat hat gesagt.:


> duplizierter Code - hashString(std::string) und hashString(std::basic_string<unsigned char> unterscheiden sich fast gar nicht voneinander



Wird ja so oder so nach den unten vorgeschlagenen Änderungen hinfällig.



deepthroat hat gesagt.:


> feof ist evtl. erst gesetzt wenn versucht wurde hinter das Ende der Datei zu lesen, falls die Dateigröße ein Vielfaches von 1024 ist, wird der Check innerhalb der while Schleife in hashFile nie aufgerufen



Wie kann ich das denn ändern? Wäre es anders, wenn ich alles in einer do...while Schleife verarbeite?



deepthroat hat gesagt.:


> verarbeite Strings doch ebenfalls wie bei Dateien (im Grunde brauchst du nur eine allgemeine Funktion die auf Daten arbeitet -- da pumpst du Daten rein und finalisierst dann irgendwann mal)



Die Daten, die nicht sofort verarbeitet werden können, da ihre Länge nicht ein Vielfaches von 512 müssten dann gepuffert werden.



deepthroat hat gesagt.:


> ... warum sind init(), append() und transform() public?



Oh man. Da fragst du den falschen. Weiß ich selbst nicht. Schon geändert.

Danke für deine vielen Hinweise, habe wohl jetzt noch einiges zu tun.

Liebe Grüße

Andreas

*Edit:* Habe mal die wichtigsten Dinge geändert. Die Methoden append() und transform() sind nun private, init() wurde vollkommen entfernt, transform(), hashString() und append() erhalten nun Referenzen als Parameter und sowohl roundRot[], als auch radians[] werden schon in der Klasse initialisiert. Diese wenigen Änderungen haben einen Performance-Gewinn von ungefähr 30% gebracht.


----------



## deepthroat (12. Februar 2011)

Hi.





Avedo hat gesagt.:


> Wie kann ich das ändern? Das \0 Zeichen maskiert doch das Ende eines Strings.


Du kannst doch die Länge direkt dem Konstruktor übergeben:

```
ustring input(reinterpret_cast<const unsigend char*>(in.data()), in.size());
```
Wäre allerdings auch hinfällig...


Avedo hat gesagt.:


> Wie kann ich das denn ändern? Wäre es anders, wenn ich alles in einer do...while Schleife verarbeite?


Nein. Es ist sowieso relativ unsinnig ständig in der Schleife abzufragen ob EOF erreicht ist. EOF ist genau dann erreicht wenn die Schleife vollständig durchgelaufen ist (und nicht ferror gesetzt ist).

```
while (... = fread(...)) {
}
if (!ferror(f)) {
  assert(feof(f));
  blockStr = append(blockStr, counter);
  transform(blockStr);
} else {
  // error / exception
}
```



Avedo hat gesagt.:


> Die Daten, die nicht sofort verarbeitet werden können, da ihre Länge nicht ein Vielfaches von 512 müssten dann gepuffert werden.


Ja, das sind ja nur 63 Bytes. Da wäre es evtl. eine gute Idee den aktuellen Block einfach als Attribut der Klasse zu definieren. Und die transform Methode nicht mehr auf ustring sondern einfach auf (const unsigned char*, size_t) zu definieren. So mußt du nicht mehr ständig die Daten in den String rein und aus dem String in das Array kopieren.

Gruß


----------

