742a93bf62cc0993a8064143addc30ab504a9fe4
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
, 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 bool blobmsg_check_attr(const struct blob_attr
*attr
, bool name
)
180 const struct blobmsg_hdr
*hdr
;
182 if (blob_len(attr
) < sizeof(struct blobmsg_hdr
))
185 hdr
= (void *) attr
->data
;
186 if (!hdr
->namelen
&& name
)
189 if (hdr
->namelen
> blob_len(attr
) - sizeof(struct blobmsg_hdr
))
192 if (hdr
->name
[hdr
->namelen
] != 0)
198 int blobmsg_parse(const struct blobmsg_policy
*policy
, int policy_len
,
199 struct blob_attr
**tb
, void *data
, int len
)
201 struct blobmsg_hdr
*hdr
;
202 struct blob_attr
*attr
;
206 memset(tb
, 0, policy_len
* sizeof(*tb
));
207 pslen
= alloca(policy_len
);
208 for (i
= 0; i
< policy_len
; i
++) {
212 pslen
[i
] = strlen(policy
[i
].name
);
215 __blob_for_each_attr(attr
, data
, len
) {
216 hdr
= blob_data(attr
);
217 for (i
= 0; i
< policy_len
; i
++) {
221 if (policy
[i
].type
!= BLOBMSG_TYPE_UNSPEC
&&
222 blob_id(attr
) != policy
[i
].type
)
225 if (hdr
->namelen
!= pslen
[i
])
228 if (!blobmsg_check_attr(attr
, true))
234 if (strcmp(policy
[i
].name
, (char *) hdr
->name
) != 0)
245 static struct blob_attr
*
246 blobmsg_new(struct blob_buf
*buf
, int type
, const char *name
, int payload_len
, void **data
)
248 struct blob_attr
*attr
;
249 struct blobmsg_hdr
*hdr
;
250 int attrlen
, namelen
;
255 namelen
= strlen(name
);
256 attrlen
= blobmsg_hdrlen(namelen
) + payload_len
;
257 attr
= blob_new(buf
, type
, attrlen
);
261 hdr
= blob_data(attr
);
262 hdr
->namelen
= namelen
;
263 strcpy((char *) hdr
->name
, (const char *)name
);
264 *data
= blobmsg_data(attr
);
270 attr_to_offset(struct blob_buf
*buf
, struct blob_attr
*attr
)
272 return (char *)attr
- (char *) buf
->buf
;
277 blobmsg_open_nested(struct blob_buf
*buf
, const char *name
, bool array
)
279 struct blob_attr
*head
= buf
->head
;
280 int type
= array
? BLOBMSG_TYPE_ARRAY
: BLOBMSG_TYPE_TABLE
;
281 unsigned long offset
= attr_to_offset(buf
, buf
->head
);
287 head
= blobmsg_new(buf
, type
, name
, 0, &data
);
288 blob_set_raw_len(buf
->head
, blob_pad_len(buf
->head
) - blobmsg_hdrlen(strlen(name
)));
290 return (void *)offset
;
294 blobmsg_add_field(struct blob_buf
*buf
, int type
, const char *name
,
295 const void *data
, int len
)
297 struct blob_attr
*attr
;
300 if (type
== BLOBMSG_TYPE_ARRAY
||
301 type
== BLOBMSG_TYPE_TABLE
)
304 attr
= blobmsg_new(buf
, type
, name
, len
, &data_dest
);
309 memcpy(data_dest
, data
, len
);