[C++] Bit-Operationen auf String

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:
C++:
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ß
 
Zuletzt bearbeitet:
Hallo!

... 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.

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.

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.

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?

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.

... 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.
 

Anhänge

  • md5sub.zip
    121,6 KB · Aufrufe: 15
Zuletzt bearbeitet von einem Moderator:
Hi.
Wie kann ich das ändern? Das \0 Zeichen maskiert doch das Ende eines Strings.
Du kannst doch die Länge direkt dem Konstruktor übergeben:
C++:
ustring input(reinterpret_cast<const unsigend char*>(in.data()), in.size());
Wäre allerdings auch hinfällig...
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).
C++:
while (... = fread(...)) {
}
if (!ferror(f)) {
  assert(feof(f));
  blockStr = append(blockStr, counter);
  transform(blockStr);
} else {
  // error / exception
}
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ß
 
Zurück