summaryrefslogtreecommitdiff
path: root/pbstruct.h
blob: be6222dc76dce453cd55f63057810b794054b095 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
 * pbstream - a stream-oriented implementation of protocol buffers.
 *
 * Copyright (c) 2009 Joshua Haberman.  See LICENSE for details.
 *
 * pbstruct is an efficient, compact, self-describing format for storing
 * pb messages in-memory.  It can be used when parsing a protobuf into
 * a structure is desired, but both the parsing and emitting modules can
 * be used without ever using pbstruct.
 */

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

typedef enum pbstruct_type {
  PBSTRUCT_TYPE_DOUBLE = 1,
  PBSTRUCT_TYPE_FLOAT = 2,
  PBSTRUCT_TYPE_INT32 = 3,
  PBSTRUCT_TYPE_UINT32 = 4,
  PBSTRUCT_TYPE_INT64 = 5,
  PBSTRUCT_TYPE_UINT64 = 6,
  PBSTRUCT_TYPE_BOOL = 7,

  /* For these types, the main struct contains a pointer to the real data. */
  PBSTRUCT_TYPE_BYTES = 8,
  PBSTRUCT_TYPE_STRING = 9,
  PBSTRUCT_TYPE_SUBSTRUCT = 10,

  /* The array types are just like the primitive types, except the main struct
   * contains a pointer to an array of the primitive type. */
  PBSTRUCT_ARRAY = 16,  /* Not itself a real type. */
  PBSTRUCT_TYPE_DOUBLE_ARRAY    = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_DOUBLE,
  PBSTRUCT_TYPE_FLOAT_ARRAY     = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_FLOAT,
  PBSTRUCT_TYPE_INT32_ARRAY     = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_INT32,
  PBSTRUCT_TYPE_UINT32_ARRAY    = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_UINT32,
  PBSTRUCT_TYPE_INT64_ARRAY     = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_INT64,
  PBSTRUCT_TYPE_UINT64_ARRAY    = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_UINT64,
  PBSTRUCT_TYPE_BOOL_ARRAY      = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_BOOL,
  PBSTRUCT_TYPE_BYTES_ARRAY     = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_BYTES,
  PBSTRUCT_TYPE_STRING_ARRAY    = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_STRING,
  PBSTRUCT_TYPE_SUBSTRUCT_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_SUBSTRUCT,
} pbstruct_type_t;

struct pbstruct_field {
  char *name;
  pbstruct_type_t type;
  ptrdiff_t byte_offset;
  ptrdiff_t isset_byte_offset;
  uint8_t isset_byte_mask;
};

struct pbstruct_delimited {
  size_t len;
  char data[];
};

struct pbstruct_definition {
  char *name;
  size_t struct_size;
  int num_fields;
  int num_required_fields;
  struct pbstruct_field fields[];
};

struct pbstruct {
  struct pbstruct_definition *definition;
  uint8_t data[];
};

struct pbstruct* pbstruct_new(struct pbstruct_definition *definition);
/* Deletes any sub-structs also. */
struct pbstruct* pbstruct_delete(struct pbstruct_definition *definition);

inline bool pbstruct_is_set(struct pbstruct *s, struct pbstruct_field *f) {
  return s->data[f->isset_byte_offset] & f->isset_byte_mask;
}

/* These do no existence checks or type checks. */
#define DEFINE_GETTERS(ctype, name) \
  inline ctype pbstruct_get_ ## name(struct pbstruct *s, struct pbstruct_field *f) { \
    /* TODO: make sure the compiler knows this is an aligned access. */ \
    return *(ctype*)(s->data + f->byte_offset); \
  } \
  inline ctype *pbstruct_get_ ## name ## _array(struct pbstruct *s, \
                                         struct pbstruct_field *f) { \
    /* TODO: make sure the compiler knows this is an aligned access. */ \
    return *(ctype**)(s->data + f->byte_offset); \
  }

DEFINE_GETTERS(double,   double)
DEFINE_GETTERS(float,    float)
DEFINE_GETTERS(int32_t,  int32)
DEFINE_GETTERS(int64_t,  int64)
DEFINE_GETTERS(uint32_t, uint32)
DEFINE_GETTERS(uint64_t, uint64)
DEFINE_GETTERS(bool,     bool)
DEFINE_GETTERS(struct pbstruct_delimited*, bytes)
DEFINE_GETTERS(struct pbstruct_delimited*, string)
DEFINE_GETTERS(struct pbstruct*, substruct)

generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback