cmp 10

cmp 10

测试已测试
Lang语言 CC
许可证 MIT
发布最后发布2015 年 1 月

Nikolay Kasyanov 维护。



cmp 10

  • Charlie Gunyon

CMP 是 MessagePack 序列化格式的 C 实现。它目前实现了 MessagePack 规范的第 5 版。

CMP 的目标是轻量级和直观,不对程序员强制任何事情。

许可证

虽然我非常相信 GPL,但我将 CMP 许可证下放在 MIT 许可证下。

示例用法

以下示例使用文件作为后端,并基于 msgpack-c 项目中的示例模型。

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "cmp.h"

static bool read_bytes(void *data, size_t sz, FILE *fh) {
    return fread(data, sizeof(uint8_t), sz, fh) == (sz * sizeof(uint8_t));
}

static bool file_reader(cmp_ctx_t *ctx, void *data, size_t limit) {
    return read_bytes(data, limit, (FILE *)ctx->buf);
}

static size_t file_writer(cmp_ctx_t *ctx, const void *data, size_t count) {
    return fwrite(data, sizeof(uint8_t), count, (FILE *)ctx->buf);
}

void error_and_exit(const char *msg) {
    fprintf(stderr, "%s\n\n", msg);
    exit(EXIT_FAILURE);
}

int main(void) {
    FILE *fh = NULL;
    cmp_ctx_t cmp;
    uint32_t array_size = 0;
    uint32_t str_size = 0;
    char hello[6] = {0, 0, 0, 0, 0, 0};
    char message_pack[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

    fh = fopen("cmp_data.dat", "w+b");

    if (fh == NULL)
        error_and_exit("Error opening data.dat");

    cmp_init(&cmp, fh, file_reader, file_writer);

    if (!cmp_write_array(&cmp, 2))
        error_and_exit(cmp_strerror(&cmp));

    if (!cmp_write_str(&cmp, "Hello", 5))
        error_and_exit(cmp_strerror(&cmp));

    if (!cmp_write_str(&cmp, "MessagePack", 11))
        error_and_exit(cmp_strerror(&cmp));

    rewind(fh);

    if (!cmp_read_array(&cmp, &array_size))
        error_and_exit(cmp_strerror(&cmp));

    /* You can read the str byte size and then read str bytes... */

    if (!cmp_read_str_size(&cmp, &str_size))
        error_and_exit(cmp_strerror(&cmp));

    if (str_size > (sizeof(hello) - 1))
        error_and_exit("Packed 'hello' length too long\n");

    if (!read_bytes(hello, str_size, fh))
        error_and_exit(cmp_strerror(&cmp));

    /*
     * ...or you can set the maximum number of bytes to read and do it all in
     * one call
     */

    str_size = sizeof(message_pack);
    if (!cmp_read_str(&cmp, message_pack, &str_size))
        error_and_exit(cmp_strerror(&cmp));

    printf("Array Length: %zu.\n", array_size);
    printf("[\"%s\", \"%s\"]\n", hello, message_pack);

    fclose(fh);

    return EXIT_SUCCESS;
}

高级用法

请参阅 examples 文件夹。

快速、轻量级、灵活和健壮

CMP 不使用内部缓冲区;转换、编码和解码都是实时进行的。

CMP 的源文件和头文件总共有 < 2,500 行代码。

CMP 不进行堆分配。

CMP 使用标准类型而不是声明自己的,它只依赖于 bool.hstdint.hstring.h。它没有链接时依赖,甚至不依赖 C 标准库。

CMP 使用 C89 (ANSI C) 编写,当然,除了它使用了固定宽度的整数类型和 bool 之外。

另一方面,CMP 的测试套件依赖于 C 标准库,并需要 C99。

CMP 只要求程序员提供读取函数和写入函数。这样,程序员可以使用 CMP 在内存、文件、套接字等处使用 CMP。

CMP 是可移植的。它使用固定宽度的整数类型,并在运行时检查机器的字节序(MessagePack 是大端字节序)。

CMP 提供了一个类似于 errnostrerror 的相当全面的错误报告机制。

CMP 是线程安全的;虽然上下文不能在线程之间共享,但每个线程都可以自由使用自己的上下文。

CMP 使用 MessagePack 测试套件以及大量自定义测试用例进行测试。其小型测试程序使用 clang 编译,使用 -Wall -Werror -Wextra ... 以及其他几个标志,没有生成编译错误。

CMP 的源代码尽可能易于阅读,使用明确的、描述性的变量名称和一致、清晰的风格。

CMP 的源代码编写得尽可能安全。其测试套件检查无效值,并在数据进行验证之前始终将其视为可疑数据。

CMP的API旨在清晰、便捷且不令人惊讶。字符串以空字符结尾,二进制数据则不是,错误代码清晰可见,等等。

构建

CMP没有构建系统。程序员可以将cmp.ccmp.h放入它们的源树中并按需修改。无需特殊的编译器设置即可构建它,并且它在clang或gcc中都不会产生编译错误。