Amxb_Ubus  3.3.1
Ambiorix Ubus API
amxb_ubus_blob.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #include <stdlib.h>
56 
57 #include "amxb_ubus.h"
58 
59 typedef union _ubus_double {
60  double d;
61  uint64_t u64;
63 
64 static void amxb_ubus_set_var(amxc_var_t* var,
65  struct blob_attr* attr,
66  void* data,
67  int len) {
68  switch(blob_id(attr)) {
69  case BLOBMSG_TYPE_INT8:
70  amxc_var_set(int8_t, var, *(int8_t*) data);
71  break;
72 
73  case BLOBMSG_TYPE_INT16:
74  amxc_var_set(int16_t, var, (int16_t) be16_to_cpu(*(uint16_t*) data));
75  break;
76 
77  case BLOBMSG_TYPE_INT32:
78  amxc_var_set(int32_t, var, (int32_t) be32_to_cpu(*(uint32_t*) data));
79  break;
80 
81  case BLOBMSG_TYPE_INT64:
82  amxc_var_set(int64_t, var, (int64_t) be64_to_cpu(*(uint64_t*) data));
83  break;
84 
85  case BLOBMSG_TYPE_DOUBLE: {
86  ubus_double_t v;
87  v.u64 = be64_to_cpu(*(uint64_t*) data);
88  amxc_var_set(double, var, v.d);
89  }
90  break;
91 
92  case BLOBMSG_TYPE_STRING:
93  amxc_var_set(cstring_t, var, (const char*) data);
94  break;
95 
96  case BLOBMSG_TYPE_ARRAY:
97  amxc_var_set_type(var, AMXC_VAR_ID_LIST);
98  amxb_ubus_parse_blob_array(var, (struct blob_attr*) data, len);
99  break;
100 
101  case BLOBMSG_TYPE_TABLE:
102  amxc_var_set_type(var, AMXC_VAR_ID_HTABLE);
103  amxb_ubus_parse_blob_table(var, (struct blob_attr*) data, len);
104  break;
105 
106  default:
107  break;
108  }
109 }
110 
111 int PRIVATE amxb_ubus_parse_blob(amxc_var_t* var,
112  struct blob_attr* attr,
113  bool table) {
114  int len;
115  int off = 0;
116  void* data;
117 
118  if(!blobmsg_check_attr(attr, false)) {
119  return 0;
120  }
121 
122  if(table) {
123  if(blobmsg_name(attr)[0] != 0) {
124  var = amxc_var_add_new_key(var, blobmsg_name(attr));
125  off++;
126  } else {
127  return 0;
128  }
129  }
130 
131  data = blobmsg_data(attr);
132  len = blobmsg_data_len(attr);
133  amxb_ubus_set_var(var, attr, data, len);
134 
135  return off + 1;
136 }
137 
138 int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t* var,
139  struct blob_attr* attr,
140  int len) {
141  int rem = len;
142  struct blob_attr* pos;
143 
144  __blob_for_each_attr(pos, attr, rem) {
145  amxb_ubus_parse_blob(var, pos, true);
146  }
147 
148  return 1;
149 }
150 
151 
152 int PRIVATE amxb_ubus_parse_blob_array(amxc_var_t* var,
153  struct blob_attr* attr,
154  int len) {
155  int rem = len;
156  struct blob_attr* pos;
157 
158  __blob_for_each_attr(pos, attr, rem) {
159  amxc_var_t* item = amxc_var_add_new(var);
160  amxb_ubus_parse_blob(item, pos, false);
161  }
162 
163  return 1;
164 }
165 
166 int PRIVATE amxb_ubus_format_blob(amxc_var_t* data,
167  const char* key,
168  struct blob_buf* b) {
169  void* c;
170 
171  switch(amxc_var_type_of(data)) {
172  case AMXC_VAR_ID_BOOL: {
173  blobmsg_add_u8(b, key, (uint8_t) amxc_var_constcast(bool, data));
174  }
175  break;
176 
177  case AMXC_VAR_ID_INT8: {
178  blobmsg_add_u8(b, key, (uint8_t) amxc_var_constcast(int8_t, data));
179  }
180  break;
181  case AMXC_VAR_ID_UINT8: {
182  if(amxc_var_constcast(uint8_t, data) > INT8_MAX) {
183  blobmsg_add_u16(b, key, (uint16_t) amxc_var_constcast(uint8_t, data));
184  } else {
185  blobmsg_add_u8(b, key, (uint8_t) amxc_var_constcast(uint8_t, data));
186  }
187  }
188  break;
189  case AMXC_VAR_ID_INT16: {
190  blobmsg_add_u16(b, key, (uint16_t) amxc_var_constcast(int16_t, data));
191  }
192  break;
193  case AMXC_VAR_ID_UINT16: {
194  if(amxc_var_constcast(uint16_t, data) > INT16_MAX) {
195  blobmsg_add_u32(b, key, (uint32_t) amxc_var_constcast(uint16_t, data));
196  } else {
197  blobmsg_add_u16(b, key, (uint16_t) amxc_var_constcast(uint16_t, data));
198  }
199  }
200  break;
201  case AMXC_VAR_ID_INT32: {
202  blobmsg_add_u32(b, key, (uint32_t) amxc_var_constcast(int32_t, data));
203  }
204  break;
205  case AMXC_VAR_ID_UINT32: {
206  if(amxc_var_constcast(uint32_t, data) > INT32_MAX) {
207  blobmsg_add_u64(b, key, (uint64_t) amxc_var_constcast(uint32_t, data));
208  } else {
209  blobmsg_add_u32(b, key, (uint32_t) amxc_var_constcast(uint32_t, data));
210  }
211  }
212  break;
213  case AMXC_VAR_ID_INT64: {
214  blobmsg_add_u64(b, key, (uint64_t) amxc_var_constcast(int64_t, data));
215  }
216  break;
217  case AMXC_VAR_ID_UINT64: {
218  blobmsg_add_u64(b, key, (uint64_t) amxc_var_constcast(uint64_t, data));
219  }
220  break;
221 
222  case AMXC_VAR_ID_HTABLE: {
223  const amxc_htable_t* table = amxc_var_constcast(amxc_htable_t, data);
224  c = blobmsg_open_table(b, key);
225  amxb_ubus_format_blob_table(table, b);
226  blobmsg_close_table(b, c);
227  }
228  break;
229 
230  case AMXC_VAR_ID_LIST: {
231  const amxc_llist_t* list = amxc_var_constcast(amxc_llist_t, data);
232  c = blobmsg_open_array(b, key);
234  blobmsg_close_array(b, c);
235  }
236  break;
237 
238  default: {
239  char* string = amxc_var_dyncast(cstring_t, data);
240  blobmsg_add_string(b, key, string == NULL ? "" : string);
241  free(string);
242  }
243  break;
244  }
245 
246  return 0;
247 }
248 
249 int PRIVATE amxb_ubus_format_blob_table(const amxc_htable_t* table,
250  struct blob_buf* b) {
251  int retval = -1;
252 
253  amxc_htable_for_each(it, table) {
254  const char* key = amxc_htable_it_get_key(it);
255  amxc_var_t* data = amxc_var_from_htable_it(it);
256  when_failed(amxb_ubus_format_blob(data, key, b), exit);
257  }
258 
259  retval = 0;
260 
261 exit:
262  return retval;
263 }
264 
265 int PRIVATE amxb_ubus_format_blob_array(const amxc_llist_t* list,
266  struct blob_buf* b) {
267  int retval = -1;
268 
269  amxc_llist_for_each(it, list) {
270  amxc_var_t* data = amxc_var_from_llist_it(it);
271  when_failed(amxb_ubus_format_blob(data, NULL, b), exit);
272  }
273 
274  retval = 0;
275 
276 exit:
277  return retval;
278 }
static void amxb_ubus_set_var(amxc_var_t *var, struct blob_attr *attr, void *data, int len)
int PRIVATE amxb_ubus_format_blob_array(const amxc_llist_t *list, struct blob_buf *b)
int PRIVATE amxb_ubus_parse_blob(amxc_var_t *var, struct blob_attr *attr, bool table)
int PRIVATE amxb_ubus_format_blob_table(const amxc_htable_t *table, struct blob_buf *b)
union _ubus_double ubus_double_t
int PRIVATE amxb_ubus_format_blob(amxc_var_t *data, const char *key, struct blob_buf *b)
int PRIVATE amxb_ubus_parse_blob_array(amxc_var_t *var, struct blob_attr *attr, int len)
int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t *var, struct blob_attr *attr, int len)
uint64_t u64