MPACK est une implémentation C d'un encodeur et d'un décodeur pour le format de sérialisation MessagePack. C'est:
Le noyau de MPACK contient un lecteur et un écrivain tamponné, et un analyseur de style arbre qui décode en un arbre de nœuds dynamiquement typés. Les fonctions d'assistance peuvent être autorisées à lire les valeurs du type attendu, à fonctionner avec des fichiers, à augmenter automatiquement les tampons ou à allouer les chaînes, pour vérifier le codage UTF-8, et plus encore.
Le code MPACK est suffisamment petit pour être intégré directement dans votre base de code. Téléchargez simplement le package de fusion et ajoutez mpack.h et mpack.c à votre projet.
MPACK prend en charge tous les compilateurs modernes, tous les Os de bureau et de smartphone, WebAssembly, à l'intérieur du noyau Linux et même des microcontrôleurs 8 bits tels que Arduino. Le MPACK FeatureSet peut être personnalisé au moment de la compilation pour définir les fonctionnalités, les composants et les vérifications de débogage sont compilés et quelles dépendances sont disponibles.
L'API du nœud analyse un morceau de données MessagePack dans un arbre immuable de nœuds de type dynamique. Une série de fonctions d'assistance peut être utilisée pour extraire des données de types spécifiques à partir de chaque nœud.
// 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 ;
}Notez qu'aucune gestion d'erreur supplémentaire n'est nécessaire dans le code ci-dessus. Si le fichier est manquant ou corrompu, si les touches de carte sont manquantes ou si les nœuds ne sont pas dans les types attendus, les nœuds "nil" spéciaux et les valeurs fausses / zéro sont renvoyés et l'arborescence est placée dans un état d'erreur. Une vérification d'erreur n'est nécessaire qu'avant d'utiliser les données.
L'exemple ci-dessus alloue automatiquement les nœuds. Un pool de nœuds fixes peut être fourni à l'analyseur à la place dans des environnements liés à la mémoire. Pour des performances maximales et une utilisation minimale de la mémoire, l'API attend peut être utilisée pour analyser les données d'un schéma prédéfini.
L'API d'écriture code sur des données structurées sur 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 );Dans l'exemple ci-dessus, nous codant pour un tampon de mémoire grandissant. L'écrivain peut à la place écrire dans un tampon pré-alloué ou alloué à la pile (avec des tailles initiales pour les types de composés), en évitant le besoin d'allocation de mémoire. L'écrivain peut également être fourni avec une fonction Flush (comme une fonction d'écriture de fichiers ou de socket) pour appeler lorsque le tampon est plein ou lorsque l'écriture est terminée.
Si une erreur se produit, l'écrivain est placé dans un état d'erreur. L'écrivain signalera une erreur si trop de données sont écrites, si le mauvais nombre d'éléments est écrit, si une défaillance d'allocation se produit, si les données ne pouvaient pas être rincées, etc. Aucune gestion d'erreur supplémentaire n'est nécessaire dans le code ci-dessus; Toutes les écritures ultérieures sont ignorées lorsque l'écrivain est dans un état d'erreur, vous n'avez donc pas besoin de vérifier chaque écriture pour les erreurs.
L'exemple ci-dessus utilise mpack_build_map() pour déterminer automatiquement le nombre de paires de valeurs clés contenues. Si vous connaissez à l'avance le nombre d'éléments nécessaires, vous pouvez le transmettre à mpack_start_map() . Dans ce cas, le mpack_finish_map() correspondant affirmera en mode de débogage que le nombre attendu d'éléments a été réellement écrit, ce que les autres bibliothèques MessagePack C / C ++ peuvent ne pas faire.
MPACK est riche en fonctionnalités tout en maintenant des performances très élevées et une petite empreinte de code. Voici une courte table de fonctionnalité la comparant à d'autres analyseurs C:
| Mpack (v1.1) | msgpack-c (v3.3.0) | Cmp (v19) | Cwpack (v1.3.1) | |
|---|---|---|---|---|
| Aucune exigence LIBC | ✓ | ✓ | ✓ | |
| Écrivain de mémoire grandissable | ✓ | ✓ | ✓ * | |
| Dossier d'E / S | ✓ | ✓ | ✓ * | |
| Gestion des erreurs avec état | ✓ | ✓ | ||
| Analyseur progressif | ✓ | ✓ | ✓ | |
| Analyseur de flux d'arbres | ✓ | ✓ | ||
| Suivi de la taille des composés | ✓ | |||
| Taille du composé automatique | ✓ |
Un tableau de comparaison de fonctionnalités est disponible ici qui comprend des descriptions des différentes entrées du tableau.
Cette suite d'analyse comparative compare les performances de MPACK à d'autres implémentations de formats de sérialisation des schémas. MPACK surpasse toutes les bibliothèques JSON et MessagePack (sauf CWPACK), et dans certains tests, MPACK est plusieurs fois plus rapide que RapidJson pour des données équivalentes.
Conceptuellement, MessagePack stocke les données de manière similaire à JSON: elles sont toutes deux composées de valeurs simples telles que les nombres et les chaînes, stockées hiérarchiquement dans des cartes et des tableaux. Alors pourquoi ne pas simplement utiliser JSON à la place? La raison principale est que JSON est conçu pour être lisible par l'homme, il n'est donc pas aussi efficace qu'un format de sérialisation binaire:
Les types de composés tels que les chaînes, les cartes et les tableaux sont délimités, de sorte que le stockage approprié ne peut pas être alloué à l'avance. L'objet entier doit être analysé pour déterminer sa taille.
Les cordes ne sont pas stockées dans leur codage indigène. Des caractères spéciaux tels que des citations et des barreaux de barreaux doivent être échappés lorsqu'ils sont écrits et convertis lorsqu'ils sont lus.
Les nombres sont particulièrement inefficaces (en particulier lorsque l'analyse des flotteurs de dos), ce qui rend JSON inapproprié comme format de base pour des données structurées qui contient beaucoup de nombres.
Les données binaires ne sont pas du tout prises en charge par JSON. De petits blobs binaires tels que des icônes et des miniatures doivent être encodés de la base64 ou transmis hors bande.
Les problèmes ci-dessus augmentent considérablement la complexité du décodeur. Les décodeurs JSON complets sont assez importants et les décodeurs minimaux ont tendance à laisser de côté des fonctionnalités telles que la chaîne sans crystage et l'analyse flottante, ce qui les laisse à l'utilisateur ou à la plate-forme. Cela peut conduire à des bogues difficiles à trouver spécifiques à la plate-forme et aux paramètres régionaux, ainsi qu'à un plus grand potentiel de vulnérabilité de sécurité. Cela diminue également considérablement les performances, ce qui rend JSON peu attrayant pour une utilisation dans des applications telles que les jeux mobiles.
Bien que les inefficacités de l'espace de JSON puissent être partiellement atténuées par une minification et une compression, les inefficacités de performance ne le peuvent pas. Plus important encore, si vous minimisez et compressez les données, alors pourquoi utiliser un format lisible par l'homme en premier lieu?
Le processus de construction MPACK ne construit pas MPACK dans une bibliothèque; Il est utilisé pour construire et exécuter les tests unitaires. Vous n'avez pas besoin de construire MPACK ou la suite de tests unitaires pour utiliser MPACK.
Voir test / readme.md pour plus d'informations sur la façon de tester MPACK.