Skip to content

Commit

Permalink
aws_byte_cursor_starts_with(input, prefix) (#905)
Browse files Browse the repository at this point in the history
  • Loading branch information
graebm authored May 2, 2022
1 parent 9b2a8b7 commit ee859bf
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
14 changes: 14 additions & 0 deletions include/aws/common/byte_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,20 @@ bool aws_byte_cursor_eq_c_str(const struct aws_byte_cursor *const cursor, const
AWS_COMMON_API
bool aws_byte_cursor_eq_c_str_ignore_case(const struct aws_byte_cursor *const cursor, const char *const c_str);

/**
* Return true if the input starts with the prefix (exact byte comparison).
*/
AWS_COMMON_API
bool aws_byte_cursor_starts_with(const struct aws_byte_cursor *input, const struct aws_byte_cursor *prefix);

/**
* Return true if the input starts with the prefix (case-insensitive).
* The "C" locale is used for comparing upper and lowercase letters.
* Data is assumed to be ASCII text, UTF-8 will work fine too.
*/
AWS_COMMON_API
bool aws_byte_cursor_starts_with_ignore_case(const struct aws_byte_cursor *input, const struct aws_byte_cursor *prefix);

/**
* Case-insensitive hash function for array containing ASCII or UTF-8 text.
*/
Expand Down
36 changes: 36 additions & 0 deletions source/byte_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,42 @@ bool aws_byte_cursor_eq_c_str_ignore_case(const struct aws_byte_cursor *const cu
return rv;
}

bool aws_byte_cursor_starts_with(const struct aws_byte_cursor *input, const struct aws_byte_cursor *prefix) {

AWS_PRECONDITION(aws_byte_cursor_is_valid(input));
AWS_PRECONDITION(aws_byte_cursor_is_valid(prefix));

if (input->len < prefix->len) {
return false;
}

struct aws_byte_cursor start = {.ptr = input->ptr, .len = prefix->len};
bool rv = aws_byte_cursor_eq(&start, prefix);

AWS_POSTCONDITION(aws_byte_cursor_is_valid(input));
AWS_POSTCONDITION(aws_byte_cursor_is_valid(prefix));
return rv;
}

bool aws_byte_cursor_starts_with_ignore_case(
const struct aws_byte_cursor *input,
const struct aws_byte_cursor *prefix) {

AWS_PRECONDITION(aws_byte_cursor_is_valid(input));
AWS_PRECONDITION(aws_byte_cursor_is_valid(prefix));

if (input->len < prefix->len) {
return false;
}

struct aws_byte_cursor start = {.ptr = input->ptr, .len = prefix->len};
bool rv = aws_byte_cursor_eq_ignore_case(&start, prefix);

AWS_POSTCONDITION(aws_byte_cursor_is_valid(input));
AWS_POSTCONDITION(aws_byte_cursor_is_valid(prefix));
return rv;
}

int aws_byte_buf_append(struct aws_byte_buf *to, const struct aws_byte_cursor *from) {
AWS_PRECONDITION(aws_byte_buf_is_valid(to));
AWS_PRECONDITION(aws_byte_cursor_is_valid(from));
Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ add_test_case(test_byte_buf_reserve_relative)
add_test_case(test_byte_buf_reset)
add_test_case(test_byte_cursor_compare_lexical)
add_test_case(test_byte_cursor_compare_lookup)
add_test_case(test_byte_cursor_starts_with)
add_test_case(test_byte_cursor_starts_with_ignore_case)
add_test_case(test_isalnum)
add_test_case(test_isalpha)
add_test_case(test_isdigit)
Expand Down
69 changes: 69 additions & 0 deletions tests/byte_buf_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,75 @@ static int s_test_byte_buf_reserve_relative(struct aws_allocator *allocator, voi
}
AWS_TEST_CASE(test_byte_buf_reserve_relative, s_test_byte_buf_reserve_relative)

static int s_test_byte_cursor_starts_with(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
(void)allocator;

struct aws_byte_cursor a = aws_byte_cursor_from_c_str("a");
struct aws_byte_cursor abcd = aws_byte_cursor_from_c_str("abcd");
struct aws_byte_cursor ab = aws_byte_cursor_from_c_str("ab");
struct aws_byte_cursor abcde = aws_byte_cursor_from_c_str("abcde");
struct aws_byte_cursor ABCD = aws_byte_cursor_from_c_str("ABCD");
struct aws_byte_cursor AB = aws_byte_cursor_from_c_str("AB");
struct aws_byte_cursor empty_string = aws_byte_cursor_from_c_str("");
struct aws_byte_cursor null_char_string = aws_byte_cursor_from_array("\0", 1);

/* TRUE */
ASSERT_TRUE(aws_byte_cursor_starts_with(&a, &a));
ASSERT_TRUE(aws_byte_cursor_starts_with(&abcd, &ab));
ASSERT_TRUE(aws_byte_cursor_starts_with(&abcd, &abcd));
ASSERT_TRUE(aws_byte_cursor_starts_with(&abcd, &empty_string));
ASSERT_TRUE(aws_byte_cursor_starts_with(&empty_string, &empty_string));

/* FALSE */
ASSERT_FALSE(aws_byte_cursor_starts_with(&abcd, &abcde));
ASSERT_FALSE(aws_byte_cursor_starts_with(&abcd, &ABCD));
ASSERT_FALSE(aws_byte_cursor_starts_with(&abcd, &AB));
ASSERT_FALSE(aws_byte_cursor_starts_with(&empty_string, &a));
ASSERT_FALSE(aws_byte_cursor_starts_with(&empty_string, &null_char_string));
ASSERT_FALSE(aws_byte_cursor_starts_with(&abcd, &null_char_string));

return 0;
}
AWS_TEST_CASE(test_byte_cursor_starts_with, s_test_byte_cursor_starts_with)

static int s_test_byte_cursor_starts_with_ignore_case(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
(void)allocator;

struct aws_byte_cursor a = aws_byte_cursor_from_c_str("a");
struct aws_byte_cursor A = aws_byte_cursor_from_c_str("A");
struct aws_byte_cursor abcd = aws_byte_cursor_from_c_str("abcd");
struct aws_byte_cursor ABCD = aws_byte_cursor_from_c_str("ABCD");
struct aws_byte_cursor abcde = aws_byte_cursor_from_c_str("abcde");
struct aws_byte_cursor azcd = aws_byte_cursor_from_c_str("azcd");
struct aws_byte_cursor empty_string = aws_byte_cursor_from_c_str("");
struct aws_byte_cursor null_char_string = aws_byte_cursor_from_array("\0", 1);

/* TRUE */
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&abcd, &abcd));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&abcd, &ABCD));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&ABCD, &abcd));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&ABCD, &ABCD));

ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&abcd, &a));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&abcd, &A));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&ABCD, &a));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&ABCD, &A));

ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&abcd, &empty_string));
ASSERT_TRUE(aws_byte_cursor_starts_with_ignore_case(&empty_string, &empty_string));

/* FALSE */
ASSERT_FALSE(aws_byte_cursor_starts_with_ignore_case(&abcd, &abcde));
ASSERT_FALSE(aws_byte_cursor_starts_with_ignore_case(&abcd, &azcd));
ASSERT_FALSE(aws_byte_cursor_starts_with_ignore_case(&empty_string, &a));
ASSERT_FALSE(aws_byte_cursor_starts_with_ignore_case(&empty_string, &null_char_string));

return 0;
}
AWS_TEST_CASE(test_byte_cursor_starts_with_ignore_case, s_test_byte_cursor_starts_with_ignore_case)

static int s_test_byte_cursor_compare_lexical(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
(void)allocator;
Expand Down

0 comments on commit ee859bf

Please sign in to comment.