Simple interface for Mbed Cloud Client

Dependents:  

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  * Create a CBOR map.
00326  *
00327  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00328  * @param[out]  errp         Error, if NULL is returned
00329  * @return                   The created map, or NULL on error
00330  */
00331 cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
00332 
00333 /**
00334  * Create a CBOR byte string.  The data in the byte string is *not* owned
00335  * by the CBOR object, so it is not freed automatically.
00336  *
00337  * @param[in]   data         The data
00338  * @param[in]   len          The number of bytes of data
00339  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00340  * @param[out]  errp         Error, if NULL is returned
00341  * @return                   The created object, or NULL on error
00342  */
00343 cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
00344                              CBOR_CONTEXT,
00345                              cn_cbor_errback *errp);
00346 
00347 /**
00348  * Create a CBOR UTF-8 string.  The data is not checked for UTF-8 correctness.
00349  * The data being stored in the string is *not* owned the CBOR object, so it is
00350  * not freed automatically.
00351  *
00352  * @note: Do NOT use this function with untrusted data.  It calls strlen, and
00353  * relies on proper NULL-termination.
00354  *
00355  * @param[in]   data         NULL-terminated UTF-8 string
00356  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00357  * @param[out]  errp         Error, if NULL is returned
00358  * @return                   The created object, or NULL on error
00359  */
00360 cn_cbor* cn_cbor_string_create(const char* data
00361                                CBOR_CONTEXT,
00362                                cn_cbor_errback *errp);
00363 
00364 /**
00365  * Create a CBOR integer (either positive or negative).
00366  *
00367  * @param[in]   value    the value of the integer
00368  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00369  * @param[out]  errp         Error, if NULL is returned
00370  * @return                   The created object, or NULL on error
00371  */
00372 cn_cbor* cn_cbor_int_create(int64_t value
00373                             CBOR_CONTEXT,
00374                             cn_cbor_errback *errp);
00375 
00376 
00377 /**
00378 * Create a CBOR unsigned integer ( positive ).
00379 *
00380 * @param[in]   value    the value of the  unsigned integer
00381 * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00382 * @param[out]  errp         Error, if NULL is returned
00383 * @return                   The created object, or NULL on error
00384 */
00385 cn_cbor* cn_cbor_uint_create(uint64_t value
00386     CBOR_CONTEXT,
00387     cn_cbor_errback *errp);
00388 
00389 /**
00390  * Put a CBOR object into a map with a CBOR object key.  Duplicate checks are NOT
00391  * currently performed.
00392  *
00393  * @param[in]   cb_map       The map to insert into
00394  * @param[in]   key          The key
00395  * @param[in]   cb_value     The value
00396  * @param[out]  errp         Error
00397  * @return                   True on success
00398  */
00399 bool cn_cbor_map_put(cn_cbor* cb_map,
00400                      cn_cbor *cb_key, cn_cbor *cb_value,
00401                      cn_cbor_errback *errp);
00402 
00403 /**
00404  * Put a CBOR object into a map with an integer key.  Duplicate checks are NOT
00405  * currently performed.
00406  *
00407  * @param[in]   cb_map       The map to insert into
00408  * @param[in]   key          The integer key
00409  * @param[in]   cb_value     The value
00410  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00411  * @param[out]  errp         Error
00412  * @return                   True on success
00413  */
00414 bool cn_cbor_mapput_int(cn_cbor* cb_map,
00415                         int64_t key, cn_cbor* cb_value
00416                         CBOR_CONTEXT,
00417                         cn_cbor_errback *errp);
00418 
00419 /**
00420  * Put a CBOR object into a map with a string key.  Duplicate checks are NOT
00421  * currently performed.
00422  *
00423  * @note: do not call this routine with untrusted string data.  It calls
00424  * strlen, and requires a properly NULL-terminated key.
00425  *
00426  * @param[in]   cb_map       The map to insert into
00427  * @param[in]   key          The string key
00428  * @param[in]   cb_value     The value
00429  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00430  * @param[out]  errp         Error
00431  * @return                   True on success
00432  */
00433 bool cn_cbor_mapput_string(cn_cbor* cb_map,
00434                            const char* key, cn_cbor* cb_value
00435                            CBOR_CONTEXT,
00436                            cn_cbor_errback *errp);
00437 
00438 /**
00439  * Create a CBOR array
00440  *
00441  * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
00442  * @param[out]  errp         Error, if NULL is returned
00443  * @return                   The created object, or NULL on error
00444  */
00445 cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
00446 
00447 /**
00448  * Append an item to the end of a CBOR array.
00449  *
00450  * @param[in]   cb_array  The array into which to insert
00451  * @param[in]   cb_value  The value to insert
00452  * @param[out]  errp      Error
00453  * @return                True on success
00454  */
00455 bool cn_cbor_array_append(cn_cbor* cb_array,
00456                           cn_cbor* cb_value,
00457                           cn_cbor_errback *errp);
00458 
00459 #ifdef USE_CBOR_CONTEXT
00460 
00461 // The maximum number of CBOR objects in an allocated pool.
00462 #define MAX_SIZE_POOL_IN_CBORS 64
00463 
00464 /**
00465 * Init a new cn_cbor_context.
00466 * This will dynamically allocate a pool of cn_cbor objects and must be freed by calling cn_cbor_free_context.
00467 * FIXME: The created context is currently stored as a global in cn-cbor.c for easy access and convenience.
00468 *        This means only one CBOR context can be used at a time and is prone to errors if we are not careful.
00469 *        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.
00470 *        This will also allow us to use several contexts at a time and run multi-threaded.
00471 *
00472 * @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)
00473 *
00474 * @return      A pointer to the created context, or NULL in case of error
00475 */
00476 cn_cbor_context *cn_cbor_init_context(size_t num_of_cbors_in_pool);
00477 
00478 /**
00479 * Release the resources of a cn_cbor_context.
00480 * Releases the dynamically allocated pool. if either ctx is NULL or the pool is NULL,
00481 * then the function will do nothing. This should never happen, unless user committed an error.
00482 * The function does not return anything to conform with standard freeing practices.
00483 *
00484 * @param[in]    ctx Pointer to the cn_cbor_context object which points to the memory pool we wish to free
00485 *
00486 */
00487 void cn_cbor_free_context(cn_cbor_context *ctx);
00488 
00489 #ifdef USE_CBOR_CONTEXT_STATS
00490 
00491 /**
00492 * Print stats of the memory allocations of the CBOR library.
00493 */
00494 void cn_cbor_context_print_stats(void);
00495 
00496 /**
00497 * Resets the stats of the memory allocations of the CBOR library.
00498 */
00499 void cn_cbor_context_reset_stats(void);
00500 
00501 #else
00502 #define cn_cbor_context_print_stats()
00503 #define cn_cbor_context_reset_stats()
00504 #endif // USE_CBOR_CONTEXT_STATS
00505 
00506 #endif // USE_CBOR_CONTEXT
00507 
00508 
00509 #ifdef  __cplusplus
00510 }
00511 #endif
00512 
00513 #endif  /* CN_CBOR_H */