2 * blobmsg - library for generating/parsing structured blob messages
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.
23 blobmsg_json_format_t custom_format
;
27 static bool blobmsg_puts(struct strbuf
*s
, const char *c
, int len
)
32 if (s
->pos
+ len
>= s
->len
) {
34 s
->buf
= realloc(s
->buf
, s
->len
);
38 memcpy(s
->buf
+ s
->pos
, c
, len
);
43 static void blobmsg_format_string(struct strbuf
*s
, const char *str
)
45 const char *p
, *last
= str
, *end
= str
+ strlen(str
);
46 char buf
[8] = "\\u00";
48 blobmsg_puts(s
, "\"", 1);
49 for (p
= str
; *p
; p
++) {
81 blobmsg_puts(s
, last
, p
- last
);
86 sprintf(buf
+ 4, "%02x", (unsigned char) *p
);
91 blobmsg_puts(s
, buf
, len
);
94 blobmsg_puts(s
, last
, end
- last
);
95 blobmsg_puts(s
, "\"", 1);
98 static void blobmsg_format_json_list(struct strbuf
*s
, struct blob_attr
*attr
, int len
, bool array
);
100 static void blobmsg_format_element(struct strbuf
*s
, struct blob_attr
*attr
, bool array
, bool head
)
102 const char *data_str
;
107 if (!array
&& blobmsg_name(attr
)[0]) {
108 blobmsg_format_string(s
, blobmsg_name(attr
));
109 blobmsg_puts(s
, ":", 1);
112 data
= blob_data(attr
);
113 len
= blob_len(attr
);
115 data
= blobmsg_data(attr
);
116 len
= blobmsg_data_len(attr
);
118 if (s
->custom_format
) {
119 data_str
= s
->custom_format(s
->priv
, attr
);
126 switch(blob_id(attr
)) {
127 case BLOBMSG_TYPE_INT8
:
128 sprintf(buf
, "%d", *(uint8_t *)data
);
130 case BLOBMSG_TYPE_INT16
:
131 sprintf(buf
, "%d", *(uint16_t *)data
);
133 case BLOBMSG_TYPE_INT32
:
134 sprintf(buf
, "%d", *(uint32_t *)data
);
136 case BLOBMSG_TYPE_INT64
:
137 sprintf(buf
, "%lld", *(uint64_t *)data
);
139 case BLOBMSG_TYPE_STRING
:
140 blobmsg_format_string(s
, data
);
142 case BLOBMSG_TYPE_ARRAY
:
143 blobmsg_format_json_list(s
, data
, len
, true);
145 case BLOBMSG_TYPE_TABLE
:
146 blobmsg_format_json_list(s
, data
, len
, false);
151 blobmsg_puts(s
, data_str
, strlen(data_str
));
154 static void blobmsg_format_json_list(struct strbuf
*s
, struct blob_attr
*attr
, int len
, bool array
)
156 struct blob_attr
*pos
;
160 blobmsg_puts(s
, (array
? "[ " : "{ "), 2);
161 __blob_for_each_attr(pos
, attr
, rem
) {
163 blobmsg_puts(s
, ", ", 2);
165 blobmsg_format_element(s
, pos
, array
, false);
168 blobmsg_puts(s
, (array
? " ]" : " }"), 2);
171 char *blobmsg_format_json_with_cb(struct blob_attr
*attr
, bool list
, blobmsg_json_format_t cb
, void *priv
)
175 s
.len
= blob_len(attr
);
176 s
.buf
= malloc(s
.len
);
178 s
.custom_format
= cb
;
182 blobmsg_format_json_list(&s
, blob_data(attr
), blob_len(attr
), false);
184 blobmsg_format_element(&s
, attr
, false, false);
189 s
.buf
= realloc(s
.buf
, s
.pos
+ 1);
193 static const int blob_type
[__BLOBMSG_TYPE_LAST
] = {
194 [BLOBMSG_TYPE_INT8
] = BLOB_ATTR_INT8
,
195 [BLOBMSG_TYPE_INT16
] = BLOB_ATTR_INT16
,
196 [BLOBMSG_TYPE_INT32
] = BLOB_ATTR_INT32
,
197 [BLOBMSG_TYPE_INT64
] = BLOB_ATTR_INT64
,
198 [BLOBMSG_TYPE_STRING
] = BLOB_ATTR_STRING
,
201 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
203 const struct blobmsg_hdr
*hdr
;
207 if (blob_len(attr
) < sizeof(struct blobmsg_hdr
))
210 hdr
= (void *) attr
->data
;
211 if (!hdr
->namelen
&& name
)
214 if (hdr
->namelen
> blob_len(attr
) - sizeof(struct blobmsg_hdr
))
217 if (hdr
->name
[hdr
->namelen
] != 0)
221 len
= blobmsg_data_len(attr
);
222 data
= blobmsg_data(attr
);
224 if (!id
|| id
> BLOBMSG_TYPE_LAST
)
230 return blob_check_type(data
, len
, blob_type
[id
]);
233 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
234 struct blob_attr
**tb
, void *data
, int len
)
236 struct blobmsg_hdr
*hdr
;
237 struct blob_attr
*attr
;
241 memset(tb
, 0, policy_len
* sizeof(*tb
));
242 pslen
= alloca(policy_len
);
243 for (i
= 0; i
< policy_len
; i
++) {
247 pslen
[i
] = strlen(policy
[i
].name
);
250 __blob_for_each_attr(attr
, data
, len
) {
251 hdr
= blob_data(attr
);
252 for (i
= 0; i
< policy_len
; i
++) {
256 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
257 blob_id(attr
) != policy
[i
].type
)
260 if (hdr
->namelen
!= pslen
[i
])
263 if (!blobmsg_check_attr(attr
, true))
269 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
280 static struct blob_attr
*
281 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
283 struct blob_attr
*attr
;
284 struct blobmsg_hdr
*hdr
;
285 int attrlen
, namelen
;
290 namelen
= strlen(name
);
291 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
292 attr
= blob_new(buf
, type
, attrlen
);
296 hdr
= blob_data(attr
);
297 hdr
->namelen
= namelen
;
298 strcpy((char *) hdr
->name
, (const char *)name
);
299 *data
= blobmsg_data(attr
);
305 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
307 return (char *)attr
- (char *) buf
->buf
;
312 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
314 struct blob_attr
*head
= buf
->head
;
315 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
316 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
322 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
323 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
325 return (void *)offset
;
329 blobmsg_alloc_string_buffer(struct blob_buf
*buf
, const char *name
, int maxlen
)
331 struct blob_attr
*attr
;
334 attr
= blobmsg_new(buf
, BLOBMSG_TYPE_STRING
, name
, maxlen
, &data_dest
);
338 data_dest
= blobmsg_data(attr
);
339 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blob_pad_len(attr
));
340 blob_set_raw_len(attr
, blob_raw_len(attr
) - maxlen
);
346 blobmsg_add_string_buffer(struct blob_buf
*buf
)
348 struct blob_attr
*attr
;
351 attr
= blob_next(buf
->head
);
352 len
= strlen(blobmsg_data(attr
)) + 1;
354 attrlen
= blob_raw_len(attr
) + len
;
355 blob_set_raw_len(attr
, attrlen
);
356 blob_set_raw_len(buf
->head
, blob_raw_len(buf
->head
) + blob_pad_len(attr
));
360 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
361 const void *data
, int len
)
363 struct blob_attr
*attr
;
366 if (type
== BLOBMSG_TYPE_ARRAY
||
367 type
== BLOBMSG_TYPE_TABLE
)
370 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
375 memcpy(data_dest
, data
, len
);