2 * blob.c - uci <-> blobmsg conversion layer
3 * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
18 #include <libubox/blobmsg.h>
23 uci_attr_to_blob(struct blob_buf
*b
, const char *str
,
24 const char *name
, enum blobmsg_type type
)
31 case BLOBMSG_TYPE_STRING
:
32 blobmsg_add_string(b
, name
, str
);
34 case BLOBMSG_TYPE_BOOL
:
35 if (!strcmp(str
, "true") || !strcmp(str
, "1"))
37 else if (!strcmp(str
, "false") || !strcmp(str
, "0"))
42 blobmsg_add_u8(b
, name
, intval
);
44 case BLOBMSG_TYPE_INT32
:
45 intval
= strtol(str
, &err
, 0);
49 blobmsg_add_u32(b
, name
, intval
);
51 case BLOBMSG_TYPE_INT64
:
52 llval
= strtoll(str
, &err
, 0);
56 blobmsg_add_u64(b
, name
, llval
);
65 uci_array_to_blob(struct blob_buf
*b
, struct uci_option
*o
,
66 enum blobmsg_type type
)
68 struct uci_element
*e
;
69 char *str
, *next
, *word
;
71 if (o
->type
== UCI_TYPE_LIST
) {
72 uci_foreach_element(&o
->v
.list
, e
) {
73 uci_attr_to_blob(b
, e
->name
, NULL
, type
);
78 str
= strdup(o
->v
.string
);
81 while ((word
= strsep(&next
, " \t")) != NULL
) {
85 uci_attr_to_blob(b
, word
, NULL
, type
);
92 __uci_element_to_blob(struct blob_buf
*b
, struct uci_element
*e
,
93 const struct uci_blob_param_list
*p
)
95 const struct blobmsg_policy
*attr
= NULL
;
96 struct uci_option
*o
= uci_to_option(e
);
97 unsigned int types
= 0;
101 for (i
= 0; i
< p
->n_params
; i
++) {
102 attr
= &p
->params
[i
];
104 if (strcmp(attr
->name
, e
->name
) != 0)
107 if (attr
->type
> BLOBMSG_TYPE_LAST
)
110 if (types
& (1 << attr
->type
))
113 types
|= 1 << attr
->type
;
115 if (attr
->type
== BLOBMSG_TYPE_ARRAY
) {
116 int element_type
= 0;
119 element_type
= p
->info
[i
].type
;
122 element_type
= BLOBMSG_TYPE_STRING
;
124 array
= blobmsg_open_array(b
, attr
->name
);
125 uci_array_to_blob(b
, o
, element_type
);
126 blobmsg_close_array(b
, array
);
131 if (o
->type
== UCI_TYPE_LIST
)
134 ret
+= uci_attr_to_blob(b
, o
->v
.string
, attr
->name
, attr
->type
);
140 __uci_to_blob(struct blob_buf
*b
, struct uci_section
*s
,
141 const struct uci_blob_param_list
*p
)
143 struct uci_element
*e
;
146 uci_foreach_element(&s
->options
, e
)
147 ret
+= __uci_element_to_blob(b
, e
, p
);
153 uci_to_blob(struct blob_buf
*b
, struct uci_section
*s
,
154 const struct uci_blob_param_list
*p
)
159 ret
+= __uci_to_blob(b
, s
, p
);
160 for (i
= 0; i
< p
->n_next
; i
++)
161 ret
+= uci_to_blob(b
, s
, p
->next
[i
]);
167 uci_blob_diff(struct blob_attr
**tb1
, struct blob_attr
**tb2
,
168 const struct uci_blob_param_list
*config
, unsigned long *diff
)
173 for (i
= 0; i
< config
->n_params
; i
++) {
174 if (!tb1
[i
] && !tb2
[i
])
177 if (!!tb1
[i
] != !!tb2
[i
])
180 if (blob_len(tb1
[i
]) != blob_len(tb2
[i
]))
183 if (memcmp(tb1
[i
], tb2
[i
], blob_raw_len(tb1
[i
])) != 0)
191 uci_bitfield_set(diff
, i
);
201 __uci_blob_check_equal(struct blob_attr
*c1
, struct blob_attr
*c2
,
202 const struct uci_blob_param_list
*config
)
204 struct blob_attr
**tb1
, **tb2
;
212 tb1
= alloca(config
->n_params
* sizeof(struct blob_attr
*));
213 blobmsg_parse(config
->params
, config
->n_params
, tb1
,
214 blob_data(c1
), blob_len(c1
));
216 tb2
= alloca(config
->n_params
* sizeof(struct blob_attr
*));
217 blobmsg_parse(config
->params
, config
->n_params
, tb2
,
218 blob_data(c2
), blob_len(c2
));
220 return !uci_blob_diff(tb1
, tb2
, config
, NULL
);
224 uci_blob_check_equal(struct blob_attr
*c1
, struct blob_attr
*c2
,
225 const struct uci_blob_param_list
*config
)
229 if (!__uci_blob_check_equal(c1
, c2
, config
))
232 for (i
= 0; i
< config
->n_next
; i
++) {
233 if (!__uci_blob_check_equal(c1
, c2
, config
->next
[i
]))