1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 
21 #ifndef CBORATTR_H
22 #define CBORATTR_H
23 
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include "tinycbor/cbor.h"
30 
31 #ifdef MYNEWT
32 #include <os/os_mbuf.h>
33 #endif
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /* This library wraps the tinycbor decoder with a attribute based decoder
40  * suitable for decoding a binary version of json.  Specifically, the
41  * contents of the cbor contains pairs of attributes.  where the attribute
42  * is a key/value pair.  keys are always text strings, but values can be
43  * many different things (enumerated below) */
44 
45 typedef enum CborAttrType {
46     CborAttrIntegerType = 1,
47     CborAttrUnsignedIntegerType,
48     CborAttrByteStringType,
49     CborAttrTextStringType,
50     CborAttrBooleanType,
51     CborAttrHalfFloatType,
52     CborAttrFloatType,
53     CborAttrDoubleType,
54     CborAttrArrayType,
55     CborAttrObjectType,
56     CborAttrStructObjectType,
57     CborAttrNullType,
58 } CborAttrType;
59 
60 struct cbor_attr_t;
61 
62 struct cbor_enum_t {
63     char *name;
64     long long int value;
65 };
66 
67 struct cbor_array_t {
68     CborAttrType element_type;
69     union {
70         struct {
71             const struct cbor_attr_t *subtype;
72             char *base;
73             size_t stride;
74         } objects;
75         struct {
76             char **ptrs;
77             char *store;
78             int storelen;
79         } strings;
80         struct {
81             long long int *store;
82         } integers;
83         struct {
84             long long unsigned int *store;
85         } uintegers;
86         struct {
87             double *store;
88         } reals;
89         struct{
90             uint16_t *store;
91         } halffloats;
92         struct {
93             bool *store;
94         } booleans;
95     } arr;
96     int *count;
97     int maxlen;
98 };
99 
100 struct cbor_attr_t {
101     char *attribute;
102     CborAttrType type;
103     union {
104         long long int *integer;
105         long long unsigned int *uinteger;
106         uint16_t *halffloat;
107         double *real;
108         float *fval;
109         char *string;
110         bool *boolean;
111         struct byte_string {
112             uint8_t *data;
113             size_t *len;
114         } bytestring;
115         struct cbor_array_t array;
116         size_t offset;
117         struct cbor_attr_t *obj;
118     } addr;
119     union {
120         long long int integer;
121         double real;
122         bool boolean;
123         float fval;
124         uint16_t halffloat;
125     } dflt;
126     size_t len;
127     bool nodefault;
128 };
129 
130 #ifndef __ZEPHYR__
131 /** An array value to be encoded as CBOR. */
132 struct cbor_out_arr_val_t {
133     struct cbor_out_val_t *elems;
134     size_t len;
135 };
136 
137 /** A single value to be encoded as CBOR. */
138 struct cbor_out_val_t {
139     /** The type of data. */
140     CborAttrType type;
141 
142     /** The data value. */
143     union {
144         long long int integer;
145         long long unsigned int uinteger;
146         double real;
147         float fval;
148         uint16_t halffloat;
149         const char *string;
150         bool boolean;
151         struct {
152             const uint8_t *data;
153             size_t len;
154         } bytestring;
155         struct cbor_out_arr_val_t array;
156         struct cbor_out_attr_t *obj; /* Terminated with a type=0 entry. */
157     };
158 };
159 
160 /** An object key-value pair to be encoded as CBOR. */
161 struct cbor_out_attr_t {
162     const char *attribute;      /** The attribute name (key). */
163     struct cbor_out_val_t val;  /** The attribute value. */
164     bool omit;                  /** Attribute ignored if true. */
165 };
166 #endif
167 
168 /*
169  * Use the following macros to declare template initializers for
170  * CborAttrStructObjectType arrays. Writing the equivalents out by hand is
171  * error-prone.
172  *
173  * CBOR_STRUCT_OBJECT takes a structure name s, and a fieldname f in s.
174  *
175  * CBOR_STRUCT_ARRAY takes the name of a structure array, a pointer to a an
176  * initializer defining the subobject type, and the address of an integer to
177  * store the length in.
178  */
179 #define CBORATTR_STRUCT_OBJECT(s, f)        .addr.offset = offsetof(s, f)
180 #define CBORATTR_STRUCT_ARRAY(a, e, n)                                  \
181     .addr.array.element_type = CborAttrStructObjectType,                \
182     .addr.array.arr.objects.subtype = e,                                \
183     .addr.array.arr.objects.base = (char*)a,                            \
184     .addr.array.arr.objects.stride = sizeof(a[0]),                      \
185     .addr.array.count = n,                                              \
186     .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0]))
187 
188 #define CBORATTR_ATTR_UNNAMED (char *)(-1)
189 
190 int cbor_read_object(struct CborValue *, const struct cbor_attr_t *);
191 int cbor_read_array(struct CborValue *, const struct cbor_array_t *);
192 
193 int cbor_read_flat_attrs(const uint8_t *data, int len,
194                          const struct cbor_attr_t *attrs);
195 #ifdef MYNEWT
196 int cbor_read_mbuf_attrs(struct os_mbuf *m, uint16_t off, uint16_t len,
197                          const struct cbor_attr_t *attrs);
198 
199 /**
200  * @brief Encodes a CBOR representation of the specified key-value map.
201  *
202  * @param enc                   The CBOR encoder to write to.
203  * @param attrs                 The key-value map to encode.
204  *
205  * @return                      0 on success; SYS_E[...] error on failure.
206  */
207 int cbor_write_object(struct CborEncoder *enc,
208                       const struct cbor_out_attr_t *attrs);
209 
210 /**
211  * @brief Encodes a CBOR representation of the specified key-value map into an
212  * msys mbuf chain.
213  *
214  * @param attrs                 The key-value map to encode.
215  * @param out_om                On success, points to the populate mbuf chain.
216  *
217  * @return                      0 on success; SYS_E[...] error on failure.
218  */
219 int cbor_write_object_msys(const struct cbor_out_attr_t *attrs,
220                            struct os_mbuf **out_om);
221 #endif
222 #ifdef __cplusplus
223 }
224 #endif
225 
226 #endif /* CBORATTR_H */
227 
228