3e9c7743ac0a14229063e278cff08053fe165933
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
, const 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
, const char *str
)
42 const 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
, bool head
)
103 if (!array
&& blobmsg_name(attr
)[0]) {
104 blobmsg_format_string(s
, blobmsg_name(attr
));
105 blobmsg_puts(s
, ":", 1);
108 data
= blob_data(attr
);
109 len
= blob_len(attr
);
111 data
= blobmsg_data(attr
);
112 len
= blobmsg_data_len(attr
);
115 switch(blob_id(attr
)) {
116 case BLOBMSG_TYPE_INT8
:
117 sprintf(buf
, "%d", *(uint8_t *)data
);
119 case BLOBMSG_TYPE_INT16
:
120 sprintf(buf
, "%d", *(uint16_t *)data
);
122 case BLOBMSG_TYPE_INT32
:
123 sprintf(buf
, "%d", *(uint32_t *)data
);
125 case BLOBMSG_TYPE_INT64
:
126 sprintf(buf
, "%lld", *(uint64_t *)data
);
128 case BLOBMSG_TYPE_STRING
:
129 blobmsg_puts(s
, data
, strlen(data
));
131 case BLOBMSG_TYPE_ARRAY
:
132 blobmsg_format_json_list(s
, data
, len
, true);
134 case BLOBMSG_TYPE_TABLE
:
135 blobmsg_format_json_list(s
, data
, len
, false);
138 blobmsg_puts(s
, buf
, strlen(buf
));
141 static void blobmsg_format_json_list(struct strbuf
*s
, struct blob_attr
*attr
, int len
, bool array
)
143 struct blob_attr
*pos
;
147 blobmsg_puts(s
, (array
? "[ " : "{ "), 2);
148 __blob_for_each_attr(pos
, attr
, rem
) {
150 blobmsg_puts(s
, ", ", 2);
152 blobmsg_format_element(s
, pos
, array
, false);
155 blobmsg_puts(s
, (array
? " ]" : " }"), 2);
158 char *blobmsg_format_json(struct blob_attr
*attr
, bool list
)
162 s
.len
= blob_len(attr
);
163 s
.buf
= malloc(s
.len
);
167 blobmsg_format_json_list(&s
, blob_data(attr
), blob_len(attr
), false);
169 blobmsg_format_element(&s
, attr
, false, false);
174 s
.buf
= realloc(s
.buf
, s
.pos
+ 1);
178 static const int blob_type
[__BLOBMSG_TYPE_LAST
] = {
179 [BLOBMSG_TYPE_INT8
] = BLOB_ATTR_INT8
,
180 [BLOBMSG_TYPE_INT16
] = BLOB_ATTR_INT16
,
181 [BLOBMSG_TYPE_INT32
] = BLOB_ATTR_INT32
,
182 [BLOBMSG_TYPE_INT64
] = BLOB_ATTR_INT64
,
183 [BLOBMSG_TYPE_STRING
] = BLOB_ATTR_STRING
,
186 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
188 const struct blobmsg_hdr
*hdr
;
192 if (blob_len(attr
) < sizeof(struct blobmsg_hdr
))
195 hdr
= (void *) attr
->data
;
196 if (!hdr
->namelen
&& name
)
199 if (hdr
->namelen
> blob_len(attr
) - sizeof(struct blobmsg_hdr
))
202 if (hdr
->name
[hdr
->namelen
] != 0)
206 len
= blobmsg_data_len(attr
);
207 data
= blobmsg_data(attr
);
209 if (!id
|| id
> BLOBMSG_TYPE_LAST
)
215 return blob_check_type(data
, len
, blob_type
[id
]);
218 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
219 struct blob_attr
**tb
, void *data
, int len
)
221 struct blobmsg_hdr
*hdr
;
222 struct blob_attr
*attr
;
226 memset(tb
, 0, policy_len
* sizeof(*tb
));
227 pslen
= alloca(policy_len
);
228 for (i
= 0; i
< policy_len
; i
++) {
232 pslen
[i
] = strlen(policy
[i
].name
);
235 __blob_for_each_attr(attr
, data
, len
) {
236 hdr
= blob_data(attr
);
237 for (i
= 0; i
< policy_len
; i
++) {
241 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
242 blob_id(attr
) != policy
[i
].type
)
245 if (hdr
->namelen
!= pslen
[i
])
248 if (!blobmsg_check_attr(attr
, true))
254 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
265 static struct blob_attr
*
266 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
268 struct blob_attr
*attr
;
269 struct blobmsg_hdr
*hdr
;
270 int attrlen
, namelen
;
275 namelen
= strlen(name
);
276 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
277 attr
= blob_new(buf
, type
, attrlen
);
281 hdr
= blob_data(attr
);
282 hdr
->namelen
= namelen
;
283 strcpy((char *) hdr
->name
, (const char *)name
);
284 *data
= blobmsg_data(attr
);
290 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
292 return (char *)attr
- (char *) buf
->buf
;
297 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
299 struct blob_attr
*head
= buf
->head
;
300 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
301 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
307 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
308 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
310 return (void *)offset
;
314 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
315 const void *data
, int len
)
317 struct blob_attr
*attr
;
320 if (type
== BLOBMSG_TYPE_ARRAY
||
321 type
== BLOBMSG_TYPE_TABLE
)
324 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
329 memcpy(data_dest
, data
, len
);