diff --git a/include/aws/common/uri.h b/include/aws/common/uri.h index 0ac1fd9b3..edc3fb2bd 100644 --- a/include/aws/common/uri.h +++ b/include/aws/common/uri.h @@ -114,6 +114,28 @@ AWS_COMMON_API uint16_t aws_uri_port(const struct aws_uri *uri); */ AWS_COMMON_API const struct aws_byte_cursor *aws_uri_path_and_query(const struct aws_uri *uri); +/** + * For iterating over the params in the query string. + * `param` is an in/out argument used to track progress, it MUST be zeroed out to start. + * If true is returned, `param` contains the value of the next param. + * If false is returned, there are no further params. + * + * Edge cases: + * 1) Entries without '=' sign are treated as having a key and no value. + * Example: First param in query string "a&b=c" has key="a" value="" + * + * 2) Blank entries are skipped. + * Example: The only param in query string "&&a=b" is key="a" value="b" + */ +AWS_COMMON_API bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param); + +/** + * Parses query string and stores the parameters in 'out_params'. Returns AWS_OP_SUCCESS on success and + * AWS_OP_ERR on failure. The user is responsible for initializing out_params with item size of struct aws_query_param. + * The user is also responsible for cleaning up out_params when finished. + */ +AWS_COMMON_API int aws_query_string_params(struct aws_byte_cursor query_string, struct aws_array_list *out_params); + /** * For iterating over the params in the uri query string. * `param` is an in/out argument used to track progress, it MUST be zeroed out to start. diff --git a/source/uri.c b/source/uri.c index cefe57e87..9e6920488 100644 --- a/source/uri.c +++ b/source/uri.c @@ -212,7 +212,7 @@ uint16_t aws_uri_port(const struct aws_uri *uri) { return uri->port; } -bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { +bool aws_query_string_next_param(struct aws_byte_cursor query_string, struct aws_uri_param *param) { /* If param is zeroed, then this is the first run. */ bool first_run = param->value.ptr == NULL; @@ -230,7 +230,7 @@ bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_p /* The do-while is to skip over any empty substrings */ do { - if (!aws_byte_cursor_next_split(&uri->query_string, '&', &substr)) { + if (!aws_byte_cursor_next_split(&query_string, '&', &substr)) { /* no more splits, done iterating */ return false; } @@ -252,10 +252,10 @@ bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_p return true; } -int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params) { +int aws_query_string_params(struct aws_byte_cursor query_string_cursor, struct aws_array_list *out_params) { struct aws_uri_param param; AWS_ZERO_STRUCT(param); - while (aws_uri_query_string_next_param(uri, ¶m)) { + while (aws_query_string_next_param(query_string_cursor, ¶m)) { if (aws_array_list_push_back(out_params, ¶m)) { return AWS_OP_ERR; } @@ -264,6 +264,14 @@ int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list return AWS_OP_SUCCESS; } +bool aws_uri_query_string_next_param(const struct aws_uri *uri, struct aws_uri_param *param) { + return aws_query_string_next_param(uri->query_string, param); +} + +int aws_uri_query_string_params(const struct aws_uri *uri, struct aws_array_list *out_params) { + return aws_query_string_params(uri->query_string, out_params); +} + static void s_parse_scheme(struct uri_parser *parser, struct aws_byte_cursor *str) { const uint8_t *location_of_colon = memchr(str->ptr, ':', str->len);