MPACK é uma implementação C de um codificador e decodificador para o formato de serialização do MessagePack. Isso é:
O núcleo do MPACK contém um leitor e escritor tamponado e um analisador de estilo de árvore que se decodifica em uma árvore de nós dinamicamente tipados. As funções auxiliares podem ser ativadas a ler valores do tipo esperado, para trabalhar com arquivos, cultivar buffers ou alocar strings automaticamente, verificar a codificação UTF-8 e muito mais.
O código MPACK é pequeno o suficiente para ser incorporado diretamente na sua base de código. Basta baixar o pacote de amalgamação e adicionar mpack.h e mpack.c ao seu projeto.
O MPACK suporta todos os compiladores modernos, todos os oses de desktop e smartphone, WebAssembly, dentro do kernel Linux e até microcontroladores de 8 bits, como o Arduino. O MPACK Recursoset pode ser personalizado em tempo de compilação para definir quais recursos, componentes e verificações de depuração são compilados e quais dependências estão disponíveis.
A API do Node analisa um pedaço de dados do MessagePack em uma árvore imutável de nós dinamicamente do tipo dinâmico. Uma série de funções auxiliares pode ser usada para extrair dados de tipos específicos de cada nó.
// 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 ;
}Observe que nenhum manuseio de erros adicional é necessário no código acima. Se o arquivo estiver ausente ou corrompido, se as chaves do mapa estiverem ausentes ou se os nós não estiverem nos tipos esperados, os nós especiais "nil" e os valores falsos/zero serão retornados e a árvore será colocada em um estado de erro. Uma verificação de erro é necessária apenas antes de usar os dados.
O exemplo acima aloca nós automaticamente. Um pool de nós fixo pode ser fornecido ao analisador em ambientes com restrição de memória. Para desempenho máximo e uso mínimo de memória, a API espera ser usada para analisar dados de um esquema predefinido.
A API de gravação codifica dados estruturados para 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 );No exemplo acima, codificamos a um buffer de memória cultivável. O escritor pode escrever em um buffer pré-alocado ou alocado em pilha (com tamanhos iniciais para tipos de compostos), evitando a necessidade de alocação de memória. O escritor também pode receber uma função de descarga (como um arquivo ou função de gravação de soquete) para chamar quando o buffer estiver cheio ou quando a gravação é concluída.
Se ocorrer algum erro, o escritor será colocado em um estado de erro. O escritor sinalizará um erro se muitos dados forem gravados, se o número errado de elementos forem gravados, se ocorrer uma falha de alocação, se os dados não puderam ser lavados, etc. Nenhum tratamento de erro adicional for necessário no código acima; Quaisquer gravações subsequentes são ignoradas quando o escritor está em um estado de erro, para que você não precise verificar todos os erros de gravação.
O exemplo acima usa mpack_build_map() para determinar automaticamente o número de pares de valores-chave contidos. Se você conhece o número de elementos necessários, poderá passá-lo para mpack_start_map() . Nesse caso, o mpack_finish_map() correspondente será afirmado no modo de depuração que o número esperado de elementos foram realmente escritos, o que é algo que outras bibliotecas de MessagePack C/C ++ podem não fazer.
O MPACK é rico em recursos, mantendo um desempenho muito alto e uma pequena pegada de código. Aqui está uma pequena tabela de recursos comparando -a com outros analisadores C:
| Mpack (v1.1) | MSGPACK-C (v3.3.0) | Cmp (v19) | Cwpack (v1.3.1) | |
|---|---|---|---|---|
| Nenhum requisito da LIBC | ✓ | ✓ | ✓ | |
| Escritor de memória cultivável | ✓ | ✓ | ✓* | |
| Arquivo de E/S do arquivo | ✓ | ✓ | ✓* | |
| Manipulação de erros com estado | ✓ | ✓ | ||
| Analisador incremental | ✓ | ✓ | ✓ | |
| Analisador de fluxo de árvores | ✓ | ✓ | ||
| Rastreamento de tamanho composto | ✓ | |||
| Tamanho do composto automático | ✓ |
Uma tabela de comparação de recursos maiores está disponível aqui, que inclui descrições das várias entradas da tabela.
Este conjunto de benchmarking compara o desempenho do MPACK com outras implementações dos formatos de serialização esquemalesa. O MPACK supera todas as bibliotecas JSON e MessagePack (exceto CWPACK) e, em alguns testes, o MPACK é várias vezes mais rápido que o Rapidjson para obter dados equivalentes.
Conceitualmente, o MessagePack armazena dados de maneira semelhante ao JSON: ambos são compostos de valores simples, como números e strings, armazenados hierarquicamente em mapas e matrizes. Então, por que não usar apenas o JSON? A principal razão é que o JSON foi projetado para ser legível pelo homem, por isso não é tão eficiente quanto um formato de serialização binária:
Tipos de compostos, como strings, mapas e matrizes, são delimitados, portanto, o armazenamento apropriado não pode ser alocado antecipadamente. Todo o objeto deve ser analisado para determinar seu tamanho.
As cordas não são armazenadas em sua codificação nativa. Personagens especiais, como citações e barras de barriga, devem ser escapados quando escritos e convertidos de volta quando lidos.
Os números são particularmente ineficientes (especialmente ao analisar flutuantes), tornando o JSON inapropriado como formato básico para dados estruturados que contêm muitos números.
Os dados binários não são suportados pelo JSON. Pequenas bolhas binárias, como ícones e miniaturas, precisam ser baseadas em Base64 codificadas ou passadas fora da banda.
As questões acima aumentam bastante a complexidade do decodificador. Os decodificadores JSON completos são bastante grandes, e os decodificadores mínimos tendem a deixar de fora os recursos como string que não estimam e flutuam, deixando-os para o usuário ou a plataforma. Isso pode levar a bugs difíceis e específicos de plataforma de plataforma, além de um maior potencial de vulnerabilitos de segurança. Isso também diminui significativamente o desempenho, tornando o JSON pouco atraente para uso em aplicativos como jogos para celular.
Embora as ineficiências do espaço do JSON possam ser parcialmente mitigadas através da minificação e da compressão, as ineficiências de desempenho não podem. Mais importante, se você está minificando e comprimindo os dados, por que usar um formato legível por humanos em primeiro lugar?
O processo de construção do MPACK não transforma o MPACK em uma biblioteca; É usado para construir e executar os testes de unidade. Você não precisa criar o MPACK ou o conjunto de testes de unidade para usar o MPACK.
Consulte o teste/readme.md para obter informações sobre como testar o MPACK.