MPACK ist eine C -Implementierung eines Encoders und Decoders für das MessagePack -Serialisierungsformat. Es ist:
Der Kern von Mpack enthält einen gepufferten Leser und Schriftsteller und einen Parser im Baumstil, der zu einem Baum dynamisch typisierter Knoten decodiert. Helferfunktionen können aktiviert werden, um Werte des erwarteten Typs zu lesen, mit Dateien zu arbeiten, Puffer auszubauen oder Zeichenfolgen automatisch zuzuweisen, die UTF-8-Codierung und mehr zu überprüfen.
Der MPACK -Code ist klein genug, um direkt in Ihre Codebasis eingebettet zu werden. Laden Sie einfach das Zusammenschlusspaket herunter und fügen Sie mpack.h und mpack.c zu Ihrem Projekt hinzu.
MPACK unterstützt alle modernen Compiler, alle Desktop- und Smartphone-Osen, WebAssembly, im Linux-Kernel und sogar 8-Bit-Mikrocontroller wie Arduino. Der MPACK-Featureset kann bei Compile-Time angepasst werden, um festzulegen, welche Funktionen, Komponenten und Debug-Überprüfungen zusammengestellt werden und welche Abhängigkeiten verfügbar sind.
Die Knoten-API analysiert einen Stück MessagePack-Daten in einen unveränderlichen Baum von dynamisch typischen Knoten. Eine Reihe von Helferfunktionen kann verwendet werden, um Daten von bestimmten Typen aus jedem Knoten zu extrahieren.
// parse a file into a node tree
mpack_tree_t tree ;
mpack_tree_init_filename ( & tree , "homepage-example.mp" , 0 );
mpack_tree_parse ( & tree );
mpack_node_t root = mpack_tree_root ( & tree );
// extract the example data on the msgpack homepage
bool compact = mpack_node_bool ( mpack_node_map_cstr ( root , "compact" ));
int schema = mpack_node_i32 ( mpack_node_map_cstr ( root , "schema" ));
// clean up and check for errors
if ( mpack_tree_destroy ( & tree ) != mpack_ok ) {
fprintf ( stderr , "An error occurred decoding the data!n" );
return ;
}Beachten Sie, dass im obigen Code kein zusätzlicher Fehler behandelt wird. Wenn die Datei fehlt oder beschädigt ist, wenn Kartenschlüssel fehlen oder wenn Knoten nicht in den erwarteten Typen enthalten sind, werden spezielle "NIL" -Knoten und falsche/Nullwerte zurückgegeben und der Baum in einen Fehlerzustand platziert. Vor der Verwendung der Daten wird nur eine Fehlerprüfung benötigt.
Das obige Beispiel zuordnet Knoten automatisch zu. Der Parser kann stattdessen in maßgeschneiderten Umgebungen ein fester Knotenpool zur Verfügung gestellt werden. Für maximale Leistung und minimale Speicherverwendung kann die API -Erwartung verwendet werden, um Daten eines vordefinierten Schemas zu analysieren.
Die Schreib -API codiert strukturierte Daten für MessagePack.
// encode to memory buffer
char * data ;
size_t size ;
mpack_writer_t writer ;
mpack_writer_init_growable ( & writer , & data , & size );
// write the example on the msgpack homepage
mpack_build_map ( & writer );
mpack_write_cstr ( & writer , "compact" );
mpack_write_bool ( & writer , true);
mpack_write_cstr ( & writer , "schema" );
mpack_write_uint ( & writer , 0 );
mpack_complete_map ( & writer );
// finish writing
if ( mpack_writer_destroy ( & writer ) != mpack_ok ) {
fprintf ( stderr , "An error occurred encoding the data!n" );
return ;
}
// use the data
do_something_with_data ( data , size );
free ( data );Im obigen Beispiel codieren wir zu einem wachsbaren Speicherpuffer. Der Schriftsteller kann stattdessen in einen vorab allozierten oder stapelabhängigen Puffer schreiben (mit Vorabgrößen für zusammengesetzte Typen), wodurch die Notwendigkeit einer Speicherzuweisung vermieden wird. Dem Verfasser kann auch eine Flush -Funktion (z. B. eine Datei oder eine Socket -Schreibfunktion) erhalten, um aufzurufen, wenn der Puffer voll ist oder wenn das Schreiben ausgeführt wird.
Wenn ein Fehler auftritt, wird der Schriftsteller in einen Fehlerzustand gestellt. Der Verfasser markiert einen Fehler, wenn zu viel Daten geschrieben werden, wenn die falsche Anzahl von Elementen geschrieben wird, wenn ein Zuordnungsfehler auftritt, wenn die Daten nicht gespült werden konnten usw. In dem obigen Code sind keine zusätzlichen Fehlerbehandlung erforderlich. Nachfolgende Schreibvorgänge werden ignoriert, wenn sich der Schriftsteller in einem Fehlerzustand befindet, sodass Sie nicht jedes Schreiben auf Fehler überprüfen müssen.
Das obige Beispiel verwendet mpack_build_map() um die Anzahl der enthaltenen Schlüsselwertpaare automatisch zu bestimmen. Wenn Sie die Anzahl der benötigten Elemente im Voraus kennen, können Sie sie stattdessen an mpack_start_map() weitergeben. In diesem Fall wird der entsprechende mpack_finish_map() im Debug -Modus behaupten, dass die erwartete Anzahl von Elementen tatsächlich geschrieben wurde, was andere MessagePack -C/C ++ -Bibliotheken möglicherweise nicht tun.
MPACK ist reich an Funktionen, während sie eine sehr hohe Leistung und einen kleinen Code -Fußabdruck aufrechterhalten. Hier ist eine kurze Feature -Tabelle, in der sie mit anderen C -Parser verglichen werden:
| Mpack (v1.1) | MSGPACK-C (v3.3.0) | CMP (v19) | Cwpack (v1.3.1) | |
|---|---|---|---|---|
| Keine LIBC -Anforderung | ✓ | ✓ | ✓ | |
| Wachsbarer Gedächtnisautor | ✓ | ✓ | ✓* | |
| Datei -E/A -Helfer | ✓ | ✓ | ✓* | |
| Stateful Fehlerbehandlung | ✓ | ✓ | ||
| Inkrementeller Parser | ✓ | ✓ | ✓ | |
| Baumstream -Parser | ✓ | ✓ | ||
| Verfolgung der zusammengesetzten Größe | ✓ | |||
| Automatische Verbindungsgröße | ✓ |
Hier finden Sie eine größere Funktionsvergleichstabelle, die Beschreibungen der verschiedenen Einträge in der Tabelle enthält.
Diese Benchmarking -Suite vergleicht die Leistung von MPACK mit anderen Implementierungen von Schemaless -Serialisierungsformaten. Mpack übertrifft alle JSON- und MessagePack -Bibliotheken (außer CWPack), und in einigen Tests ist MPACK für äquivalente Daten um ein Vielfaches schneller als Rapidjson.
Konzeptionell speichert MessagePack Daten ähnlich wie JSON: Sie bestehen beide aus einfachen Werten wie Zahlen und Zeichenfolgen, die hierarchisch in Karten und Arrays gespeichert sind. Warum also nicht einfach JSON verwenden? Der Hauptgrund ist, dass JSON so konzipiert ist, dass es menschlich lesbar ist, so dass es nicht so effizient ist wie ein binäres Serialisierungsformat:
Verbundtypen wie Zeichenfolgen, Karten und Arrays sind abgenommen, sodass eine angemessene Speicherung nicht im Voraus zugewiesen werden kann. Das gesamte Objekt muss analysiert werden, um seine Größe zu bestimmen.
Saiten werden in ihrer einheimischen Codierung nicht gespeichert. Sonderzeichen wie Zitate und Backslashes müssen beim Schreiben entkommen und beim Lesen wieder konvertiert werden.
Die Zahlen sind besonders ineffizient (insbesondere beim Analysieren von Schwimmern), was JSON als Basisformat für strukturierte Daten, die viele Zahlen enthalten, unangemessen machen.
Binärdaten werden von JSON überhaupt nicht unterstützt. Kleine binäre Blobs wie Ikonen und Miniaturansichten müssen baS 64 codiert oder aus dem Band übergeben werden.
Die obigen Probleme erhöhen die Komplexität des Decoders erheblich. JSON-Decoder mit vollem Funktionsumfang sind ziemlich groß, und minimale Decoder neigen dazu, solche Funktionen wie String Unscaping und Float-Parsen herauszulassen, und überlassen dies stattdessen dem Benutzer oder der Plattform. Dies kann zu schwer zu findenden, plattformspezifischen und lokalspezifischen Fehler sowie zu einem größeren Potenzial für Sicherheitslücke. Dies verringert auch die Leistung erheblich und macht JSON unattraktiv für die Verwendung in Anwendungen wie mobilen Spielen.
Während die Raumeffizienzen von JSON durch Minifikation und Komprimierung teilweise gemindert werden können, können die Leistungseffizienz nicht können. Noch wichtiger ist, wenn Sie die Daten minimieren und komprimieren, warum dann überhaupt ein menschliches lesbares Format verwenden?
Der MPACK -Build -Prozess baut Mpack nicht in eine Bibliothek auf. Es wird verwendet, um die Unit -Tests zu erstellen und auszuführen. Sie müssen MPACK oder die Unit -Testsuite nicht für die Verwendung von MPACK erstellen.
Informationen zum Testen von MPACK finden Sie unter test/readme.md.