2 * blob - library for generating/parsing tagged binary data
4 * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License version 2.1
8 * as published by the Free Software Foundation
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
19 blob_buffer_grow(struct blob_buf
*buf
, int minlen
)
21 buf
->buflen
+= ((minlen
/ 256) + 1) * 256;
22 buf
->buf
= realloc(buf
->buf
, buf
->buflen
);
27 blob_init(struct blob_attr
*attr
, int id
, unsigned int len
)
29 len
&= BLOB_ATTR_LEN_MASK
;
30 len
|= (id
<< BLOB_ATTR_ID_SHIFT
) & BLOB_ATTR_ID_MASK
;
31 attr
->id_len
= cpu_to_be32(len
);
34 static inline struct blob_attr
*
35 offset_to_attr(struct blob_buf
*buf
, int offset
)
37 void *ptr
= (char *)buf
->buf
+ offset
;
42 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
44 return (char *)attr
- (char *) buf
->buf
;
47 static struct blob_attr
*
48 blob_add(struct blob_buf
*buf
, struct blob_attr
*pos
, int id
, int payload
)
50 int offset
= attr_to_offset(buf
, pos
);
51 int required
= (offset
+ sizeof(struct blob_attr
) + payload
) - buf
->buflen
;
52 struct blob_attr
*attr
;
55 int offset_head
= attr_to_offset(buf
, buf
->head
);
57 if (!buf
->grow
|| !buf
->grow(buf
, required
))
60 buf
->head
= offset_to_attr(buf
, offset_head
);
61 attr
= offset_to_attr(buf
, offset
);
66 blob_init(attr
, id
, payload
+ sizeof(struct blob_attr
));
71 blob_buf_init(struct blob_buf
*buf
, int id
)
74 buf
->grow
= blob_buffer_grow
;
77 if (blob_add(buf
, buf
->buf
, id
, 0) == NULL
)
84 blob_new(struct blob_buf
*buf
, int id
, int payload
)
86 struct blob_attr
*attr
;
88 attr
= blob_add(buf
, blob_next(buf
->head
), id
, payload
);
92 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) + blob_pad_len(attr
));
97 blob_put(struct blob_buf
*buf
, int id
, const void *ptr
, int len
)
99 struct blob_attr
*attr
;
101 attr
= blob_new(buf
, id
, len
);
106 memcpy(blob_data(attr
), ptr
, len
);
111 blob_nest_start(struct blob_buf
*buf
, int id
)
113 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
114 buf
->head
= blob_new(buf
, id
, 0);
115 return (void *) offset
;
119 blob_nest_end(struct blob_buf
*buf
, void *cookie
)
121 struct blob_attr
*attr
= offset_to_attr(buf
, (unsigned long) cookie
);
122 blob_set_raw_len(attr
, blob_pad_len(attr
) + blob_len(buf
->head
));
126 static const int blob_type_minlen
[BLOB_ATTR_LAST
] = {
127 [BLOB_ATTR_STRING
] = 1,
128 [BLOB_ATTR_INT8
] = sizeof(uint8_t),
129 [BLOB_ATTR_INT16
] = sizeof(uint16_t),
130 [BLOB_ATTR_INT32
] = sizeof(uint32_t),
131 [BLOB_ATTR_INT64
] = sizeof(uint64_t),
135 blob_check_type(const void *ptr
, int len
, int type
)
137 const char *data
= ptr
;
139 if (type
>= BLOB_ATTR_LAST
)
142 if (type
>= BLOB_ATTR_INT8
&& type
<= BLOB_ATTR_INT64
) {
143 if (len
!= blob_type_minlen
[type
])
146 if (len
< blob_type_minlen
[type
])
150 if (type
== BLOB_ATTR_STRING
&& data
[len
- 1] != 0)
157 blob_parse(struct blob_attr
*attr
, struct blob_attr
**data
, const struct blob_attr_info
*info
, int max
)
159 struct blob_attr
*pos
;
163 memset(data
, 0, sizeof(struct blob_attr
*) * max
);
164 blob_for_each_attr(pos
, attr
, rem
) {
165 int id
= blob_id(pos
);
166 int len
= blob_len(pos
);
172 int type
= info
[id
].type
;
174 if (type
< BLOB_ATTR_LAST
) {
175 if (!blob_check_type(blob_data(pos
), len
, type
))
179 if (info
[id
].minlen
&& len
< info
[id
].minlen
)
182 if (info
[id
].maxlen
&& len
> info
[id
].maxlen
)
185 if (info
[id
].validate
&& !info
[id
].validate(&info
[id
], attr
))