diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index 365bfda1b6f8..5955e03b87a0 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -1030,6 +1030,22 @@ struct qdf_ipv6_addr { */ QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr); +/** + * qdf_uint32_array_parse() - parse the given string as uint32 array + * @in_str: the input string to parse + * @out_array: the output uint32 array, populated on success + * @array_size: size of the array + * @out_size: size of the populated array + * + * This API is called to convert string (each value separated by + * a comma) into an uint32 array + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array, + qdf_size_t array_size, qdf_size_t *out_size); + /** * qdf_uint16_array_parse() - parse the given string as uint16 array * @in_str: the input string to parse diff --git a/qdf/src/qdf_types.c b/qdf/src/qdf_types.c index c259b297fb01..a56e69759c6e 100644 --- a/qdf/src/qdf_types.c +++ b/qdf/src/qdf_types.c @@ -616,6 +616,55 @@ QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr) } qdf_export_symbol(qdf_ipv6_parse); +QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array, + qdf_size_t array_size, qdf_size_t *out_size) +{ + QDF_STATUS status; + bool negate; + qdf_size_t size = 0; + uint64_t value; + + QDF_BUG(in_str); + if (!in_str) + return QDF_STATUS_E_INVAL; + + QDF_BUG(out_array); + if (!out_array) + return QDF_STATUS_E_INVAL; + + QDF_BUG(out_size); + if (!out_size) + return QDF_STATUS_E_INVAL; + + while (size < array_size) { + status = __qdf_int_parse_lazy(&in_str, &value, &negate); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + if ((uint32_t)value != value || negate) + return QDF_STATUS_E_RANGE; + + in_str = qdf_str_left_trim(in_str); + + switch (in_str[0]) { + case ',': + out_array[size++] = value; + in_str++; + break; + case '\0': + out_array[size++] = value; + *out_size = size; + return QDF_STATUS_SUCCESS; + default: + return QDF_STATUS_E_FAILURE; + } + } + + return QDF_STATUS_E_FAILURE; +} + +qdf_export_symbol(qdf_uint32_array_parse); + QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array, qdf_size_t array_size, qdf_size_t *out_size) { diff --git a/qdf/test/qdf_types_test.c b/qdf/test/qdf_types_test.c index fb12a1e42954..f26a4f7e39db 100644 --- a/qdf/test/qdf_types_test.c +++ b/qdf/test/qdf_types_test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -234,6 +234,80 @@ static uint32_t qdf_types_ut_uint16_array_parse(void) return errors; } +#define ut_uint32_array_pass(str, max_size, exp_arr, exp_arr_size) \ +__ut_uint32_array(str, QDF_STATUS_SUCCESS, max_size, exp_arr, exp_arr_size) + +#define ut_uint32_array_fail(str, max_size, exp_status, exp_arr, exp_arr_size)\ +__ut_uint32_array(str, exp_status, max_size, exp_arr, exp_arr_size) + +static uint32_t +__ut_uint32_array(const char *str, QDF_STATUS exp_status, + uint8_t max_array_size, uint32_t *exp_array, + uint8_t exp_array_size) +{ + uint32_t parsed_array[10]; + qdf_size_t parsed_array_size; + QDF_STATUS status; + uint8_t i; + + status = qdf_uint32_array_parse(str, parsed_array, max_array_size, + &parsed_array_size); + + if (status != exp_status) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> status %d; expected status %d", + str, status, exp_status); + return 1; + } + + if (QDF_IS_STATUS_ERROR(status)) + return 0; + + if (parsed_array_size != exp_array_size) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> parsed_array_size %zu; exp_array_size %d", + str, parsed_array_size, exp_array_size); + return 1; + } + + for (i = 0; i < exp_array_size; i++) + if (parsed_array[i] != exp_array[i]) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> parsed_array[%d] %d; exp_array[%d] %d", + str, i, parsed_array[i], i, + exp_array[i]); + return 1; + } + + return 0; +} + +static uint32_t qdf_types_ut_uint32_array_parse(void) +{ + uint32_t errors = 0; + uint32_t exp_array_value[10] = { 1, 100, 9997, 899965, 65536, 0, + 4294967295, 268435456, + 2164184149, 999999999}; + + errors += ut_uint32_array_pass( + "1, 100, 9997, 899965, 65536, 0, 4294967295, 268435456, 2164184149, 999999999", + 10, exp_array_value, 10); + errors += ut_uint32_array_pass( + "+1, +100, +9997, +899965, +65536, 0, +4294967295, +268435456, +2164184149, +999999999", + 10, exp_array_value, 10); + errors += ut_uint32_array_fail("1;", 10, QDF_STATUS_E_FAILURE, + exp_array_value, 0); + /* Out of range test where 4294967296 is out of range */ + errors += ut_uint32_array_fail( + "1, 100, 9997, 899965, 65536, 0, 4294967296, 268435456, 2164184149, 999999999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint32_array_fail( + "-1, -100, -9997, -899965, -65536, 0, -4294967295, -268435456, -2164184149, -999999999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint32_array_fail( + "1, 100, 9997, 899965, 65536, 日本, 0, 4294967295, 268435456, 999999999", + 10, QDF_STATUS_E_FAILURE, exp_array_value, 0); + + return errors; +} + #define ut_uint32_pass(str, exp) __ut_uint32(str, QDF_STATUS_SUCCESS, exp) #define ut_uint32_fail(str, exp_status) __ut_uint32(str, exp_status, 0) @@ -581,6 +655,7 @@ uint32_t qdf_types_unit_test(void) errors += qdf_types_ut_ipv4_parse(); errors += qdf_types_ut_ipv6_parse(); errors += qdf_types_ut_uint16_array_parse(); + errors += qdf_types_ut_uint32_array_parse(); return errors; }