Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cn-cbor.h Source File

cn-cbor.h

Go to the documentation of this file.
00001 /**
00002  * \file
00003  * \brief
00004  * CBOR parsing
00005  */
00006 
00007 #ifndef CN_CBOR_H
00008 #define CN_CBOR_H
00009 
00010 #ifdef  __cplusplus
00011 extern "C" {
00012 #endif
00013 
00014 //typedef int ssize_t;
00015 
00016 #ifdef EMACS_INDENTATION_HELPER
00017 } /* Duh. */
00018 #endif
00019 
00020 #include <stdbool.h>
00021 #include <stdint.h>
00022 #include <stdio.h>
00023 
00024 //typedef ssize_t int;
00025 //#include <unistd.h>
00026 
00027 /**
00028  * All of the different kinds of CBOR values.
00029  */
00030 typedef enum cn_cbor_type {
00031   /** false */
00032   CN_CBOR_FALSE,
00033   /** true */
00034   CN_CBOR_TRUE,
00035   /** null */
00036   CN_CBOR_NULL,
00037   /** undefined */
00038   CN_CBOR_UNDEF,
00039   /** Positive integers */
00040   CN_CBOR_UINT,
00041   /** Negative integers */
00042   CN_CBOR_INT,
00043   /** Byte string */
00044   CN_CBOR_BYTES,
00045   /** UTF-8 string */
00046   CN_CBOR_TEXT,
00047   /** Byte string, in chunks.  Each chunk is a child. */
00048   CN_CBOR_BYTES_CHUNKED,
00049   /** UTF-8 string, in chunks.  Each chunk is a child */
00050   CN_CBOR_TEXT_CHUNKED,
00051   /** Array of CBOR values.  Each array element is a child, in order */
00052   CN_CBOR_ARRAY,
00053   /** Map of key/value pairs.  Each key and value is a child, alternating. */
00054   CN_CBOR_MAP,
00055   /** Tag describing the next value.  The next value is the single child. */
00056   CN_CBOR_TAG,
00057   /** Simple value, other than the defined ones */
00058   CN_CBOR_SIMPLE,
00059   /** Doubles, floats, and half-floats */
00060   CN_CBOR_DOUBLE,
00061   /** An error has occurred */
00062   CN_CBOR_INVALID
00063 } cn_cbor_type;
00064 
00065 /**
00066  * Flags used during parsing.  Not useful for consumers of the
00067  * `cn_cbor` structure.
00068  */
00069 typedef enum cn_cbor_flags {
00070   /** The count field will be used for parsing */
00071   CN_CBOR_FL_COUNT = 1,
00072   /** An indefinite number of children */
00073   CN_CBOR_FL_INDEF = 2,
00074   /** Not used yet; the structure must free the v.str pointer when the
00075      structure is freed */
00076   CN_CBOR_FL_OWNER = 0x80,            /* of str */
00077 } cn_cbor_flags;
00078 
00079 // FIXME: These could be used in the future instead of type and flags in struct cn_cbor (will make the sizeof(cn_cbor) 8 bytes less)
00080 //#define CN_CBOR_TYPE(pCbor) (pCbor->enums & 0x0f)
00081 //#define CN_CBOR_FLAGS(pCbor) (pCbor->enums & 0xf0)
00082 
00083 /**
00084  * A CBOR value
00085  */
00086 
00087 typedef struct cn_cbor {
00088   /** The type of value */
00089   cn_cbor_type type;
00090   /** Flags used at parse time */
00091   cn_cbor_flags flags;
00092   /** Data associated with the value; different branches of the union are
00093       used depending on the `type` field. */
00094   union {
00095     /** CN_CBOR_BYTES */
00096     const uint8_t* bytes;
00097     /** CN_CBOR_TEXT */
00098     const char* str;
00099     /** CN_CBOR_INT */
00100     int64_t sint;
00101     /** CN_CBOR_UINT */
00102     uint64_t uint;
00103     /** CN_CBOR_DOUBLE */
00104     double dbl;
00105     /** for use during parsing */
00106     unsigned long count;
00107   } v;                          /* TBD: optimize immediate */
00108   /** Number of children.
00109     * @note: for maps, this is 2x the number of entries */
00110   int length;
00111 
00112   // FIXME: This could be used in the future instead of type and flags in struct cn_cbor (will make the sizeof(cn_cbor) 8 bytes less)
00113   //uint8_t enums;
00114 
00115   /** The first child value */
00116   struct cn_cbor* first_child;
00117   /** The last child value */
00118   struct cn_cbor* last_child;
00119   /** The sibling after this one, or NULL if this is the last */
00120   struct cn_cbor* next;
00121   /** The parent of this value, or NULL if this is the root */
00122   struct cn_cbor* parent;
00123 } cn_cbor;
00124 
00125 /**
00126  * All of the different kinds of errors
00127  */
00128 typedef enum cn_cbor_error {
00129   /** No error has occurred */
00130   CN_CBOR_NO_ERROR,
00131   /** More data was expected while parsing */
00132   CN_CBOR_ERR_OUT_OF_DATA,
00133   /** Some extra data was left over at the end of parsing */
00134   CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED,
00135   /** A map should be alternating keys and values.  A break was found
00136       when a value was expected */
00137   CN_CBOR_ERR_ODD_SIZE_INDEF_MAP,
00138   /** A break was found where it wasn't expected */
00139   CN_CBOR_ERR_BREAK_OUTSIDE_INDEF,
00140   /** Indefinite encoding works for bstrs, strings, arrays, and maps.
00141       A different major type tried to use it. */
00142   CN_CBOR_ERR_MT_UNDEF_FOR_INDEF,
00143   /** Additional Information values 28-30 are reserved */
00144   CN_CBOR_ERR_RESERVED_AI,
00145   /** A chunked encoding was used for a string or bstr, and one of the elements
00146       wasn't the expected (string/bstr) type */
00147   CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING,
00148   /** An invalid parameter was passed to a function */
00149   CN_CBOR_ERR_INVALID_PARAMETER,
00150   /** Allocation failed */
00151   CN_CBOR_ERR_OUT_OF_MEMORY,
00152   /** A float was encountered during parse but the library was built without
00153       support for float types. */
00154   CN_CBOR_ERR_FLOAT_NOT_SUPPORTED,
00155   /** Encoder was unable to encode the cn_cbor object that was provided */
00156   CN_CBOR_ERR_ENCODER
00157 } cn_cbor_error;
00158 
00159 /**
00160  * Strings matching the `cn_cbor_error` conditions.
00161  *
00162  * @todo: turn into a function to make the type safety more clear?
00163  */
00164 extern const char *cn_cbor_error_str[];
00165 
00166 /**
00167  * Errors
00168  */
00169 typedef struct cn_cbor_errback {
00170   /** The position in the input where the erorr happened */
00171   int pos;
00172   /** The error, or CN_CBOR_NO_ERROR if none */
00173   cn_cbor_error err;
00174 } cn_cbor_errback;
00175 
00176 #ifdef USE_CBOR_CONTEXT
00177 
00178 
00179 /**
00180  * Allocate and zero out memory.  `count` elements of `size` are required,
00181  * as for `calloc(3)`.  The `context` is the `cn_cbor_context` passed in
00182  * earlier to the CBOR routine.
00183  *
00184  * @param[in] count   The number of items to allocate
00185  * @param[in] size    The size of each item
00186  * @param[in] context The allocation context
00187  */
00188 typedef void* (*cn_calloc_func)(size_t count, size_t size, void *context);
00189 
00190 /**
00191  * Free memory previously allocated with a context.  If using a pool allocator,
00192  * this function will often be a no-op, but it must be supplied in order to
00193  * prevent the CBOR library from calling `free(3)`.
00194  *
00195  * @note: it may be that this is never needed; if so, it will be removed for
00196  * clarity and speed.
00197  *
00198  * @param  context [description]
00199  * @return         [description]
00200  */
00201 typedef void (*cn_free_func)(void *ptr, void *context);
00202 
00203 /**
00204  * The allocation context.
00205  */
00206 typedef struct cn_cbor_context {
00207     /** The pool `calloc` routine.  Must allocate and zero. */
00208     cn_calloc_func calloc_func;
00209     /** The pool `free` routine.  Often a no-op, but required. */
00210     cn_free_func  free_func;
00211     /** Typically, the pool object, to be used when calling `calloc_func`
00212       * and `free_func` */
00213     void *context;
00214 } cn_cbor_context;
00215 
00216 extern cn_cbor_context *cbor_context;
00217 
00218 /** When USE_CBOR_CONTEXT is defined, many functions take an extra `context`
00219   * parameter */
00220 #define CBOR_CONTEXT , cn_cbor_context *cbor_context
00221 /** When USE_CBOR_CONTEXT is defined, some functions take an extra `context`
00222   * parameter at the beginning */
00223 #define CBOR_CONTEXT_COMMA cn_cbor_context *cbor_context,
00224 /** When USE_CBOR_CONTEXT is defined, some functions take a `context`
00225   * parameter, as the only argument */
00226 #define CBOR_CONTEXT_NO_COMMA cn_cbor_context *cbor_context
00227 
00228 /** The following two defines are used by caller as arguments for the  
00229   * function that is being called - to use context*/
00230 #define CBOR_CONTEXT_PARAM , cbor_context
00231 #define CBOR_CONTEXT_PARAM_COMMA cbor_context, 
00232 
00233 /** The following two defines are used by caller as arguments for the
00234   * function that is being called - to force use of LIBC allocation instead of pool*/
00235 #define CBOR_CONTEXT_NULL , NULL
00236 #define CBOR_CONTEXT_NULL_COMMA NULL,
00237 
00238 
00239 #else
00240 
00241 #define CBOR_CONTEXT
00242 #define CBOR_CONTEXT_COMMA
00243 #define CBOR_CONTEXT_NO_COMMA void
00244 #define CBOR_CONTEXT_PARAM
00245 #define CBOR_CONTEXT_PARAM_COMMA
00246 #define CBOR_CONTEXT_NULL
00247 #define CBOR_CONTEXT_NULL_COMMA
00248 
00249 #endif
00250 
00251 /**
00252  * Decode an array of CBOR bytes into structures.
00253  *
00254  * @param[in]  buf          The array of bytes to parse
00255  * @param[in]  len          The number of bytes in the array
00256  * @param[in]  CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00257  * @param[out] errp         Error, if NULL is returned
00258  * @return                  The parsed CBOR structure, or NULL on error
00259  */
00260 cn_cbor* cn_cbor_decode(const uint8_t *buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp);
00261 
00262 /**
00263  * Get a value from a CBOR map that has the given string as a key.
00264  *
00265  * @param[in]  cb           The CBOR map
00266  * @param[in]  key          The string to look up in the map
00267  * @return                  The matching value, or NULL if the key is not found
00268  */
00269 cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key);
00270 
00271 /**
00272  * Get a value from a CBOR map that has the given integer as a key.
00273  *
00274  * @param[in]  cb           The CBOR map
00275  * @param[in]  key          The int to look up in the map
00276  * @return                  The matching value, or NULL if the key is not found
00277  */
00278 cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key);
00279 
00280 /**
00281  * Get the item with the given index from a CBOR array.
00282  *
00283  * @param[in]  cb           The CBOR map
00284  * @param[in]  idx          The array index
00285  * @return                  The matching value, or NULL if the index is invalid
00286  */
00287 cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx);
00288 
00289 /**
00290  * Free the given CBOR structure.
00291  * You MUST NOT try to free a cn_cbor structure with a parent (i.e., one
00292  * that is not a root in the tree).
00293  *
00294  * @param[in]  cb           The CBOR value to free.  May be NULL, or a root object.
00295  * @param[in]  CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00296  */
00297 void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT);
00298 
00299 /**
00300 * Get the size of the buffer that must be provided to cn_cbor_encoder_write().
00301 * This is the size of the CBOR that will be encoded.
00302 *
00303 * @param[in]  cb         Pointer to a cn_cbor structure, which the user wishes to encode.
00304 * @param[out] err    Error, if -1 is returned.
00305 * @return                -1 on fail, or number size of the allocated buffer containing the encoded data.
00306 */
00307 
00308 int cn_cbor_get_encoded_size(const cn_cbor *cb, cn_cbor_errback *err);
00309 
00310 /**
00311  * Write a CBOR value and all of the child values.
00312  * Allocates a buffer of the correct size and fills it with the encoded CBOR. 
00313  * User must free the buffer.
00314  *
00315  * @param[in]  cb         Pointer to a cn_cbor structure, which the user wishes to encode.
00316  * @param[out] bufOut     Pointer a buffer which will be filled with the encoded data.
00317  * @param[in]  bufSize    Size of the provided buffer in bytes.
00318  * @param[out] err    Error, if -1 is returned.
00319  * @return                -1 on fail, or number encoded bytes written to the provided buffer.
00320  */
00321 
00322 int cn_cbor_encoder_write(const cn_cbor *cb, uint8_t *bufOut, int bufSize, cn_cbor_errback *err);
00323 
00324 /**
00325 * Get the size in bytes of the encoding of only cn_cbor container (map or array) discarding its parents and siblings.
00326 *
00327 * @param[in]  cb_container         Pointer to a cn_cbor structure of either type CN_CBOR_MAP or CN_CBOR_ARRAY. Mey be part of a bigger cn_cbor structure.
00328 * @return                          -1 on fail, or number encoded bytes the container will be .
00329 */
00330 int cn_cbor_get_encoded_container_size(const cn_cbor *cb_container);
00331 
00332 /**
00333  * Create a CBOR map.
00334  *
00335  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00336  * @param[out]  errp         Error, if NULL is returned
00337  * @return                   The created map, or NULL on error
00338  */
00339 cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
00340 
00341 /**
00342  * Create a CBOR byte string.  The data in the byte string is *not* owned
00343  * by the CBOR object, so it is not freed automatically.
00344  *
00345  * @param[in]   data         The data
00346  * @param[in]   len          The number of bytes of data
00347  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00348  * @param[out]  errp         Error, if NULL is returned
00349  * @return                   The created object, or NULL on error
00350  */
00351 cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
00352                              CBOR_CONTEXT,
00353                              cn_cbor_errback *errp);
00354 
00355 /**
00356  * Create a CBOR UTF-8 string from a buffer. The data is not checked for UTF-8 correctness.
00357  * The data being stored in the string is *not* owned the CBOR object, so it is
00358  * not freed automatically.
00359  *
00360  * @param[in]   data         UTF-8 string (does not have to be NULL terminated)
00361  * @param[in]   len          The number of bytes of data
00362  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00363  * @param[out]  errp         Error, if NULL is returned
00364  * @return                   The created object, or NULL on error
00365  */
00366 cn_cbor* cn_cbor_text_create(const uint8_t* data, int len
00367                              CBOR_CONTEXT,
00368                              cn_cbor_errback *errp);
00369 
00370 /**
00371  * Create a CBOR UTF-8 string.  The data is not checked for UTF-8 correctness.
00372  * The data being stored in the string is *not* owned the CBOR object, so it is
00373  * not freed automatically.
00374  *
00375  * @note: Do NOT use this function with untrusted data.  It calls strlen, and
00376  * relies on proper NULL-termination.
00377  *
00378  * @param[in]   data         NULL-terminated UTF-8 string
00379  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00380  * @param[out]  errp         Error, if NULL is returned
00381  * @return                   The created object, or NULL on error
00382  */
00383 cn_cbor* cn_cbor_string_create(const char* data
00384                                CBOR_CONTEXT,
00385                                cn_cbor_errback *errp);
00386 
00387 /**
00388  * Create a CBOR integer (either positive or negative).
00389  *
00390  * @param[in]   value    the value of the integer
00391  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00392  * @param[out]  errp         Error, if NULL is returned
00393  * @return                   The created object, or NULL on error
00394  */
00395 cn_cbor* cn_cbor_int_create(int64_t value
00396                             CBOR_CONTEXT,
00397                             cn_cbor_errback *errp);
00398 
00399 
00400 /**
00401 * Create a CBOR unsigned integer ( positive ).
00402 *
00403 * @param[in]   value    the value of the  unsigned integer
00404 * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00405 * @param[out]  errp         Error, if NULL is returned
00406 * @return                   The created object, or NULL on error
00407 */
00408 cn_cbor* cn_cbor_uint_create(uint64_t value
00409     CBOR_CONTEXT,
00410     cn_cbor_errback *errp);
00411 
00412 /**
00413  * Put a CBOR object into a map with a CBOR object key.  Duplicate checks are NOT
00414  * currently performed.
00415  *
00416  * @param[in]   cb_map       The map to insert into
00417  * @param[in]   key          The key
00418  * @param[in]   cb_value     The value
00419  * @param[out]  errp         Error
00420  * @return                   True on success
00421  */
00422 bool cn_cbor_map_put(cn_cbor* cb_map,
00423                      cn_cbor *cb_key, cn_cbor *cb_value,
00424                      cn_cbor_errback *errp);
00425 
00426 /**
00427  * Put a CBOR object into a map with an integer key.  Duplicate checks are NOT
00428  * currently performed.
00429  *
00430  * @param[in]   cb_map       The map to insert into
00431  * @param[in]   key          The integer key
00432  * @param[in]   cb_value     The value
00433  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00434  * @param[out]  errp         Error
00435  * @return                   True on success
00436  */
00437 bool cn_cbor_mapput_int(cn_cbor* cb_map,
00438                         int64_t key, cn_cbor* cb_value
00439                         CBOR_CONTEXT,
00440                         cn_cbor_errback *errp);
00441 
00442 /**
00443  * Put a CBOR object into a map with a string key.  Duplicate checks are NOT
00444  * currently performed.
00445  *
00446  * @note: do not call this routine with untrusted string data.  It calls
00447  * strlen, and requires a properly NULL-terminated key.
00448  *
00449  * @param[in]   cb_map       The map to insert into
00450  * @param[in]   key          The string key
00451  * @param[in]   cb_value     The value
00452  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00453  * @param[out]  errp         Error
00454  * @return                   True on success
00455  */
00456 bool cn_cbor_mapput_string(cn_cbor* cb_map,
00457                            const char* key, cn_cbor* cb_value
00458                            CBOR_CONTEXT,
00459                            cn_cbor_errback *errp);
00460 
00461 /**
00462  * Create a CBOR array
00463  *
00464  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00465  * @param[out]  errp         Error, if NULL is returned
00466  * @return                   The created object, or NULL on error
00467  */
00468 cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
00469 
00470 /**
00471  * Append an item to the end of a CBOR array.
00472  *
00473  * @param[in]   cb_array  The array into which to insert
00474  * @param[in]   cb_value  The value to insert
00475  * @param[out]  errp      Error
00476  * @return                True on success
00477  */
00478 bool cn_cbor_array_append(cn_cbor* cb_array,
00479                           cn_cbor* cb_value,
00480                           cn_cbor_errback *errp);
00481 
00482 #ifdef USE_CBOR_CONTEXT
00483 
00484 // The maximum number of CBOR objects in an allocated pool.
00485 #define MAX_SIZE_POOL_IN_CBORS 64
00486 
00487 /**
00488 * Init a new cn_cbor_context.
00489 * This will dynamically allocate a pool of cn_cbor objects and must be freed by calling cn_cbor_free_context.
00490 * FIXME: The created context is currently stored as a global in cn-cbor.c for easy access and convenience.
00491 *        This means only one CBOR context can be used at a time and is prone to errors if we are not careful.
00492 *        In the future we will probably want to init a context and and pass it on all the way to the cn_cbor functions that need access to it, Instead of using a global.
00493 *        This will also allow us to use several contexts at a time and run multi-threaded.
00494 *
00495 * @param[in]   num_of_cbors_in_pool The number of cn_cbor object in the pool. The size of the dynamically allocated pool will be num_of_cbors_in_pool * sizeof(cn_cbor)
00496 *
00497 * @return      A pointer to the created context, or NULL in case of error
00498 */
00499 cn_cbor_context *cn_cbor_init_context(size_t num_of_cbors_in_pool);
00500 
00501 /**
00502 * Release the resources of a cn_cbor_context.
00503 * Releases the dynamically allocated pool. if either ctx is NULL or the pool is NULL,
00504 * then the function will do nothing. This should never happen, unless user committed an error.
00505 * The function does not return anything to conform with standard freeing practices.
00506 *
00507 * @param[in]    ctx Pointer to the cn_cbor_context object which points to the memory pool we wish to free
00508 *
00509 */
00510 void cn_cbor_free_context(cn_cbor_context *ctx);
00511 
00512 #ifdef USE_CBOR_CONTEXT_STATS
00513 
00514 /**
00515 * Print stats of the memory allocations of the CBOR library.
00516 */
00517 void cn_cbor_context_print_stats(void);
00518 
00519 /**
00520 * Resets the stats of the memory allocations of the CBOR library.
00521 */
00522 void cn_cbor_context_reset_stats(void);
00523 
00524 #else
00525 #define cn_cbor_context_print_stats()
00526 #define cn_cbor_context_reset_stats()
00527 #endif // USE_CBOR_CONTEXT_STATS
00528 
00529 #endif // USE_CBOR_CONTEXT
00530 
00531 
00532 #ifdef  __cplusplus
00533 }
00534 #endif
00535 
00536 #endif  /* CN_CBOR_H */