mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
uri_parser: provide function to split query
This commit is contained in:
parent
91fe57a4d1
commit
af03ba4aa8
@ -80,6 +80,16 @@ typedef struct {
|
||||
uint16_t query_len; /**< length of @ref query */
|
||||
} uri_parser_result_t;
|
||||
|
||||
/**
|
||||
* @brief Container to represent a query parameter
|
||||
*/
|
||||
typedef struct {
|
||||
char *name; /**< name of the query parameter */
|
||||
char *value; /**< value of the query parameter */
|
||||
uint16_t name_len; /**< length of @ref name */
|
||||
uint16_t value_len; /**< length of @ref value */
|
||||
} uri_parser_query_param_t;
|
||||
|
||||
/**
|
||||
* @brief Checks whether @p uri is in absolute form
|
||||
*
|
||||
@ -133,6 +143,36 @@ int uri_parser_process(uri_parser_result_t *result, const char *uri,
|
||||
*/
|
||||
int uri_parser_process_string(uri_parser_result_t *result, const char *uri);
|
||||
|
||||
/**
|
||||
* @brief Provides a list of URI query parameters from a given URI parser
|
||||
* result.
|
||||
*
|
||||
* @note The function **DOES NOT** check for duplicate query parameters.
|
||||
*
|
||||
* @pre `uri_parsed != NULL`
|
||||
* @pre `params != NULL` and all its elements are set to zero.
|
||||
*
|
||||
* @param[in] uri_parsed A parsed URI result. Must not be NULL.
|
||||
* @param[out] params An array of @ref uri_parser_query_param_t.
|
||||
* Must not be NULL and all zero-valued on call. Will be
|
||||
* filled with the name-value-pairs in
|
||||
* uri_parser_result_t::query of @p uri_parsed. If the
|
||||
* number of query parameters in @p uri_parsed exceeds
|
||||
* @p params_len, the list will be truncated and the
|
||||
* function returns -2.
|
||||
* @param[in] params_len The length of @p params
|
||||
*
|
||||
* @return number of filled entries in @p params on success. Might be 0 if
|
||||
* uri_parser_result_t::query is NULL.
|
||||
* @return -1 on parsing error.
|
||||
* @return -2 when the number of query parameters exceeds @p params_len.
|
||||
* In that case, the array is filled with the first @p params_len
|
||||
* name-value-pairs in uri_parser_result_t::query of @p uri_parsed.
|
||||
*/
|
||||
int uri_parser_split_query(const uri_parser_result_t *uri_parsed,
|
||||
uri_parser_query_param_t *params,
|
||||
size_t params_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -305,3 +305,75 @@ int uri_parser_process_string(uri_parser_result_t *result, const char *uri)
|
||||
{
|
||||
return uri_parser_process(result, uri, strlen(uri));
|
||||
}
|
||||
|
||||
int uri_parser_split_query(const uri_parser_result_t *uri,
|
||||
uri_parser_query_param_t *params,
|
||||
size_t params_len)
|
||||
{
|
||||
const char *query_end;
|
||||
unsigned idx = 0;
|
||||
|
||||
assert(uri);
|
||||
assert(params);
|
||||
|
||||
if ((uri->query == NULL) || (uri->query_len == 0) || (params_len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
assert(params[0].name == 0);
|
||||
assert(params[0].name_len == 0);
|
||||
assert(params[0].value == 0);
|
||||
assert(params[0].value_len == 0);
|
||||
query_end = uri->query + uri->query_len;
|
||||
params[0].name = uri->query;
|
||||
for (const char *c = uri->query; c < query_end; c++) {
|
||||
switch (*c) {
|
||||
case '#':
|
||||
case '&':
|
||||
if (params[idx].value == NULL) {
|
||||
/* we should have picked up a parameter value by now */
|
||||
return -1;
|
||||
}
|
||||
params[idx].value_len = c - params[idx].value;
|
||||
if (*c == '#') {
|
||||
/* we've reached the end of the query string, next comes an
|
||||
* anchor, enforce end of loop
|
||||
* XXX: can be removed when uri_parser has anchor support */
|
||||
c = query_end;
|
||||
}
|
||||
else if ((idx + 1) < params_len) {
|
||||
/* c is an ampersand (&), so mark the next char as the next
|
||||
* parameter's name name */
|
||||
params[++idx].name = (char *)c + 1U;
|
||||
assert(params[idx].name_len == 0);
|
||||
}
|
||||
else {
|
||||
/* c is an ampersand (&), but we exceeded param_len.
|
||||
* Return -2 as per doc */
|
||||
return -2;
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
/* params[idx].value != NULL picks up duplicate = in query
|
||||
* parameter */
|
||||
if ((params[idx].name == NULL) || params[idx].value != NULL) {
|
||||
/* we should have picked up a parameter name by now */
|
||||
return -1;
|
||||
}
|
||||
params[idx].name_len = c - params[idx].name;
|
||||
/* pick next char as start of value */
|
||||
params[idx].value = (char *)c + 1U;
|
||||
/* make sure the precondition on params is met */
|
||||
assert(params[idx].value_len == 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((uri->query != query_end) && (params[idx].value == NULL)) {
|
||||
/* we should have picked up a parameter value by now */
|
||||
return -1;
|
||||
}
|
||||
/* set final value_len */
|
||||
params[idx].value_len = query_end - params[idx].value;
|
||||
return idx + 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user