b16510bcc88cb89d116131f1f4e940bc6ac7ae39
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.
24 static bool blobmsg_puts(struct strbuf
*s
, char *c
, int len
)
29 if (s
->pos
+ len
>= s
->len
) {
31 s
->buf
= realloc(s
->buf
, s
->len
);
35 memcpy(s
->buf
+ s
->pos
, c
, len
);
40 static void blobmsg_format_string(struct strbuf
*s
, char *str
)
42 char *p
, *last
= str
, *end
= str
+ strlen(str
);
43 char buf
[8] = "\\u00";
45 blobmsg_puts(s
, "\"", 1);
46 for (p
= str
; *p
; p
++) {
78 blobmsg_puts(s
, last
, p
- last
);
83 sprintf(buf
+ 4, "%02x", (unsigned char) *p
);
88 blobmsg_puts(s
, buf
, len
);
91 blobmsg_puts(s
, last
, end
- last
);
92 blobmsg_puts(s
, "\"", 1);
95 static void blobmsg_format_json_list(struct strbuf
*s
, struct blob_attr
*attr
, int len
, bool array
);
97 static void blobmsg_format_element(struct strbuf
*s
, struct blob_attr
*attr
, bool array
)
104 data
= blob_data(attr
);
105 len
= blob_len(attr
);
107 blobmsg_format_string(s
, blobmsg_name(attr
));
108 blobmsg_puts(s
, ":", 1);
109 data
= blobmsg_data(attr
);
110 len
= blobmsg_data_len(attr
);
113 switch(blob_id(attr
)) {
114 case BLOBMSG_TYPE_INT8
:
115 sprintf(buf
, "%d", *(uint8_t *)data
);
117 case BLOBMSG_TYPE_INT16
:
118 sprintf(buf
, "%d", *(uint16_t *)data
);
120 case BLOBMSG_TYPE_INT32
:
121 sprintf(buf
, "%d", *(uint32_t *)data
);
123 case BLOBMSG_TYPE_INT64
:
124 sprintf(buf
, "%lld", *(uint64_t *)data
);
126 case BLOBMSG_TYPE_STRING
:
127 blobmsg_puts(s
, data
, strlen(data
));
129 case BLOBMSG_TYPE_ARRAY
:
130 blobmsg_format_json_list(s
, data
, len
, true);
132 case BLOBMSG_TYPE_TABLE
:
133 blobmsg_format_json_list(s
, data
, len
, false);
136 blobmsg_puts(s
, buf
, strlen(buf
));
139 static void blobmsg_format_json_list(struct strbuf
*s
, struct blob_attr
*attr
, int len
, bool array
)
141 struct blob_attr
*pos
;
145 blobmsg_puts(s
, (array
? "[ " : "{ "), 2);
146 __blob_for_each_attr(pos
, attr
, rem
) {
148 blobmsg_puts(s
, ", ", 2);
150 blobmsg_format_element(s
, pos
, array
);
153 blobmsg_puts(s
, (array
? " ]" : " }"), 2);
156 char *blobmsg_format_json(struct blob_attr
*attr
)
160 s
.len
= blob_len(attr
);
161 s
.buf
= malloc(s
.len
);
164 blobmsg_format_element(&s
, attr
, false);
169 s
.buf
= realloc(s
.buf
, s
.pos
+ 1);
173 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
175 const struct blobmsg_hdr
*hdr
;
177 if (blob_len(attr
) < sizeof(struct blobmsg_hdr
))
180 hdr
= (void *) attr
->data
;
181 if (!hdr
->namelen
&& name
)
184 if (hdr
->namelen
> blob_len(attr
) - sizeof(struct blobmsg_hdr
))
187 if (hdr
->name
[hdr
->namelen
] != 0)
193 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
194 struct blob_attr
**tb
, void *data
, int len
)
196 struct blobmsg_hdr
*hdr
;
197 struct blob_attr
*attr
;
201 memset(tb
, 0, policy_len
* sizeof(*tb
));
202 pslen
= alloca(policy_len
);
203 for (i
= 0; i
< policy_len
; i
++) {
207 pslen
[i
] = strlen(policy
[i
].name
);
210 __blob_for_each_attr(attr
, data
, len
) {
211 hdr
= blob_data(attr
);
212 for (i
= 0; i
< policy_len
; i
++) {
216 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
217 blob_id(attr
) != policy
[i
].type
)
220 if (hdr
->namelen
!= pslen
[i
])
223 if (!blobmsg_check_attr(attr
, true))
229 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
240 static struct blob_attr
*
241 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
243 struct blob_attr
*attr
;
244 struct blobmsg_hdr
*hdr
;
245 int attrlen
, namelen
;
247 if (blob_id(buf
->head
) == BLOBMSG_TYPE_ARRAY
&& !name
) {
248 attr
= blob_new(buf
, type
, payload_len
);
249 *data
= blob_data(attr
);
253 if (blob_id(buf
->head
) != BLOBMSG_TYPE_TABLE
|| !name
)
256 namelen
= strlen(name
);
257 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
258 attr
= blob_new(buf
, type
, attrlen
);
262 hdr
= blob_data(attr
);
263 hdr
->namelen
= namelen
;
264 strcpy((char *) hdr
->name
, (const char *)name
);
265 *data
= blobmsg_data(attr
);
271 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
273 return (char *)attr
- (char *) buf
->buf
;
278 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
280 struct blob_attr
*head
= buf
->head
;
281 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
282 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
285 if (blob_id(head
) == BLOBMSG_TYPE_ARRAY
&& !name
)
286 return blob_nest_start(buf
, type
);
288 if (blob_id(head
) == BLOBMSG_TYPE_TABLE
&& name
) {
289 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
290 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
292 return (void *)offset
;
299 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
300 const void *data
, int len
)
302 struct blob_attr
*attr
;
305 if (type
== BLOBMSG_TYPE_ARRAY
||
306 type
== BLOBMSG_TYPE_TABLE
)
309 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
314 memcpy(data_dest
, data
, len
);