137a7bc39SJason Zhu /*
237a7bc39SJason Zhu * Copyright (C) 2016 The Android Open Source Project
337a7bc39SJason Zhu *
437a7bc39SJason Zhu * Permission is hereby granted, free of charge, to any person
537a7bc39SJason Zhu * obtaining a copy of this software and associated documentation
637a7bc39SJason Zhu * files (the "Software"), to deal in the Software without
737a7bc39SJason Zhu * restriction, including without limitation the rights to use, copy,
837a7bc39SJason Zhu * modify, merge, publish, distribute, sublicense, and/or sell copies
937a7bc39SJason Zhu * of the Software, and to permit persons to whom the Software is
1037a7bc39SJason Zhu * furnished to do so, subject to the following conditions:
1137a7bc39SJason Zhu *
1237a7bc39SJason Zhu * The above copyright notice and this permission notice shall be
1337a7bc39SJason Zhu * included in all copies or substantial portions of the Software.
1437a7bc39SJason Zhu *
1537a7bc39SJason Zhu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1637a7bc39SJason Zhu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1737a7bc39SJason Zhu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1837a7bc39SJason Zhu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1937a7bc39SJason Zhu * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2037a7bc39SJason Zhu * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2137a7bc39SJason Zhu * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2237a7bc39SJason Zhu * SOFTWARE.
2337a7bc39SJason Zhu */
2437a7bc39SJason Zhu
2537a7bc39SJason Zhu #include <android_avb/avb_util.h>
2637a7bc39SJason Zhu
2737a7bc39SJason Zhu #include <stdarg.h>
2837a7bc39SJason Zhu
avb_be32toh(uint32_t in)2937a7bc39SJason Zhu uint32_t avb_be32toh(uint32_t in) {
3037a7bc39SJason Zhu uint8_t* d = (uint8_t*)∈
3137a7bc39SJason Zhu uint32_t ret;
3237a7bc39SJason Zhu ret = ((uint32_t)d[0]) << 24;
3337a7bc39SJason Zhu ret |= ((uint32_t)d[1]) << 16;
3437a7bc39SJason Zhu ret |= ((uint32_t)d[2]) << 8;
3537a7bc39SJason Zhu ret |= ((uint32_t)d[3]);
3637a7bc39SJason Zhu return ret;
3737a7bc39SJason Zhu }
3837a7bc39SJason Zhu
avb_be64toh(uint64_t in)3937a7bc39SJason Zhu uint64_t avb_be64toh(uint64_t in) {
4037a7bc39SJason Zhu uint8_t* d = (uint8_t*)∈
4137a7bc39SJason Zhu uint64_t ret;
4237a7bc39SJason Zhu ret = ((uint64_t)d[0]) << 56;
4337a7bc39SJason Zhu ret |= ((uint64_t)d[1]) << 48;
4437a7bc39SJason Zhu ret |= ((uint64_t)d[2]) << 40;
4537a7bc39SJason Zhu ret |= ((uint64_t)d[3]) << 32;
4637a7bc39SJason Zhu ret |= ((uint64_t)d[4]) << 24;
4737a7bc39SJason Zhu ret |= ((uint64_t)d[5]) << 16;
4837a7bc39SJason Zhu ret |= ((uint64_t)d[6]) << 8;
4937a7bc39SJason Zhu ret |= ((uint64_t)d[7]);
5037a7bc39SJason Zhu return ret;
5137a7bc39SJason Zhu }
5237a7bc39SJason Zhu
5337a7bc39SJason Zhu /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
avb_htobe32(uint32_t in)5437a7bc39SJason Zhu uint32_t avb_htobe32(uint32_t in) {
5537a7bc39SJason Zhu union {
5637a7bc39SJason Zhu uint32_t word;
5737a7bc39SJason Zhu uint8_t bytes[4];
5837a7bc39SJason Zhu } ret;
5937a7bc39SJason Zhu ret.bytes[0] = (in >> 24) & 0xff;
6037a7bc39SJason Zhu ret.bytes[1] = (in >> 16) & 0xff;
6137a7bc39SJason Zhu ret.bytes[2] = (in >> 8) & 0xff;
6237a7bc39SJason Zhu ret.bytes[3] = in & 0xff;
6337a7bc39SJason Zhu return ret.word;
6437a7bc39SJason Zhu }
6537a7bc39SJason Zhu
6637a7bc39SJason Zhu /* Converts a 64-bit unsigned integer from host to big-endian byte order. */
avb_htobe64(uint64_t in)6737a7bc39SJason Zhu uint64_t avb_htobe64(uint64_t in) {
6837a7bc39SJason Zhu union {
6937a7bc39SJason Zhu uint64_t word;
7037a7bc39SJason Zhu uint8_t bytes[8];
7137a7bc39SJason Zhu } ret;
7237a7bc39SJason Zhu ret.bytes[0] = (in >> 56) & 0xff;
7337a7bc39SJason Zhu ret.bytes[1] = (in >> 48) & 0xff;
7437a7bc39SJason Zhu ret.bytes[2] = (in >> 40) & 0xff;
7537a7bc39SJason Zhu ret.bytes[3] = (in >> 32) & 0xff;
7637a7bc39SJason Zhu ret.bytes[4] = (in >> 24) & 0xff;
7737a7bc39SJason Zhu ret.bytes[5] = (in >> 16) & 0xff;
7837a7bc39SJason Zhu ret.bytes[6] = (in >> 8) & 0xff;
7937a7bc39SJason Zhu ret.bytes[7] = in & 0xff;
8037a7bc39SJason Zhu return ret.word;
8137a7bc39SJason Zhu }
8237a7bc39SJason Zhu
avb_safe_memcmp(const void * s1,const void * s2,size_t n)8337a7bc39SJason Zhu int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
8437a7bc39SJason Zhu const unsigned char* us1 = s1;
8537a7bc39SJason Zhu const unsigned char* us2 = s2;
8637a7bc39SJason Zhu int result = 0;
8737a7bc39SJason Zhu
8837a7bc39SJason Zhu if (0 == n) {
8937a7bc39SJason Zhu return 0;
9037a7bc39SJason Zhu }
9137a7bc39SJason Zhu
9237a7bc39SJason Zhu /*
9337a7bc39SJason Zhu * Code snippet without data-dependent branch due to Nate Lawson
9437a7bc39SJason Zhu * (nate@root.org) of Root Labs.
9537a7bc39SJason Zhu */
9637a7bc39SJason Zhu while (n--) {
9737a7bc39SJason Zhu result |= *us1++ ^ *us2++;
9837a7bc39SJason Zhu }
9937a7bc39SJason Zhu
10037a7bc39SJason Zhu return result != 0;
10137a7bc39SJason Zhu }
10237a7bc39SJason Zhu
avb_safe_add_to(uint64_t * value,uint64_t value_to_add)10337a7bc39SJason Zhu bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
10437a7bc39SJason Zhu uint64_t original_value;
10537a7bc39SJason Zhu
10637a7bc39SJason Zhu avb_assert(value != NULL);
10737a7bc39SJason Zhu
10837a7bc39SJason Zhu original_value = *value;
10937a7bc39SJason Zhu
11037a7bc39SJason Zhu *value += value_to_add;
11137a7bc39SJason Zhu if (*value < original_value) {
11237a7bc39SJason Zhu avb_error("Overflow when adding values.\n");
11337a7bc39SJason Zhu return false;
11437a7bc39SJason Zhu }
11537a7bc39SJason Zhu
11637a7bc39SJason Zhu return true;
11737a7bc39SJason Zhu }
11837a7bc39SJason Zhu
avb_safe_add(uint64_t * out_result,uint64_t a,uint64_t b)11937a7bc39SJason Zhu bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
12037a7bc39SJason Zhu uint64_t dummy;
12137a7bc39SJason Zhu if (out_result == NULL) {
12237a7bc39SJason Zhu out_result = &dummy;
12337a7bc39SJason Zhu }
12437a7bc39SJason Zhu *out_result = a;
12537a7bc39SJason Zhu return avb_safe_add_to(out_result, b);
12637a7bc39SJason Zhu }
12737a7bc39SJason Zhu
avb_validate_utf8(const uint8_t * data,size_t num_bytes)12837a7bc39SJason Zhu bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
12937a7bc39SJason Zhu size_t n;
13037a7bc39SJason Zhu unsigned int num_cc;
13137a7bc39SJason Zhu
13237a7bc39SJason Zhu for (n = 0, num_cc = 0; n < num_bytes; n++) {
13337a7bc39SJason Zhu uint8_t c = data[n];
13437a7bc39SJason Zhu
13537a7bc39SJason Zhu if (num_cc > 0) {
13637a7bc39SJason Zhu if ((c & (0x80 | 0x40)) == 0x80) {
13737a7bc39SJason Zhu /* 10xx xxxx */
13837a7bc39SJason Zhu } else {
13937a7bc39SJason Zhu goto fail;
14037a7bc39SJason Zhu }
14137a7bc39SJason Zhu num_cc--;
14237a7bc39SJason Zhu } else {
14337a7bc39SJason Zhu if (c < 0x80) {
14437a7bc39SJason Zhu num_cc = 0;
14537a7bc39SJason Zhu } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
14637a7bc39SJason Zhu /* 110x xxxx */
14737a7bc39SJason Zhu num_cc = 1;
14837a7bc39SJason Zhu } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
14937a7bc39SJason Zhu /* 1110 xxxx */
15037a7bc39SJason Zhu num_cc = 2;
15137a7bc39SJason Zhu } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
15237a7bc39SJason Zhu (0x80 | 0x40 | 0x20 | 0x10)) {
15337a7bc39SJason Zhu /* 1111 0xxx */
15437a7bc39SJason Zhu num_cc = 3;
15537a7bc39SJason Zhu } else {
15637a7bc39SJason Zhu goto fail;
15737a7bc39SJason Zhu }
15837a7bc39SJason Zhu }
15937a7bc39SJason Zhu }
16037a7bc39SJason Zhu
16137a7bc39SJason Zhu if (num_cc != 0) {
16237a7bc39SJason Zhu goto fail;
16337a7bc39SJason Zhu }
16437a7bc39SJason Zhu
16537a7bc39SJason Zhu return true;
16637a7bc39SJason Zhu
16737a7bc39SJason Zhu fail:
16837a7bc39SJason Zhu return false;
16937a7bc39SJason Zhu }
17037a7bc39SJason Zhu
avb_str_concat(char * buf,size_t buf_size,const char * str1,size_t str1_len,const char * str2,size_t str2_len)17137a7bc39SJason Zhu bool avb_str_concat(char* buf,
17237a7bc39SJason Zhu size_t buf_size,
17337a7bc39SJason Zhu const char* str1,
17437a7bc39SJason Zhu size_t str1_len,
17537a7bc39SJason Zhu const char* str2,
17637a7bc39SJason Zhu size_t str2_len) {
17737a7bc39SJason Zhu uint64_t combined_len;
17837a7bc39SJason Zhu
17937a7bc39SJason Zhu if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
18037a7bc39SJason Zhu avb_error("Overflow when adding string sizes.\n");
18137a7bc39SJason Zhu return false;
18237a7bc39SJason Zhu }
18337a7bc39SJason Zhu
18437a7bc39SJason Zhu if (combined_len > buf_size - 1) {
18537a7bc39SJason Zhu avb_error("Insufficient buffer space.\n");
18637a7bc39SJason Zhu return false;
18737a7bc39SJason Zhu }
18837a7bc39SJason Zhu
18937a7bc39SJason Zhu avb_memcpy(buf, str1, str1_len);
19037a7bc39SJason Zhu avb_memcpy(buf + str1_len, str2, str2_len);
19137a7bc39SJason Zhu buf[combined_len] = '\0';
19237a7bc39SJason Zhu
19337a7bc39SJason Zhu return true;
19437a7bc39SJason Zhu }
19537a7bc39SJason Zhu
avb_malloc(size_t size)19637a7bc39SJason Zhu void* avb_malloc(size_t size) {
19737a7bc39SJason Zhu void* ret = avb_malloc_(size);
19837a7bc39SJason Zhu if (ret == NULL) {
19937a7bc39SJason Zhu avb_error("Failed to allocate memory.\n");
20037a7bc39SJason Zhu return NULL;
20137a7bc39SJason Zhu }
20237a7bc39SJason Zhu return ret;
20337a7bc39SJason Zhu }
20437a7bc39SJason Zhu
avb_calloc(size_t size)20537a7bc39SJason Zhu void* avb_calloc(size_t size) {
20637a7bc39SJason Zhu void* ret = avb_malloc(size);
20737a7bc39SJason Zhu if (ret == NULL) {
20837a7bc39SJason Zhu return NULL;
20937a7bc39SJason Zhu }
21037a7bc39SJason Zhu
21137a7bc39SJason Zhu avb_memset(ret, '\0', size);
21237a7bc39SJason Zhu return ret;
21337a7bc39SJason Zhu }
21437a7bc39SJason Zhu
avb_strdup(const char * str)21537a7bc39SJason Zhu char* avb_strdup(const char* str) {
21637a7bc39SJason Zhu size_t len = avb_strlen(str);
21737a7bc39SJason Zhu char* ret = avb_malloc(len + 1);
21837a7bc39SJason Zhu if (ret == NULL) {
21937a7bc39SJason Zhu return NULL;
22037a7bc39SJason Zhu }
22137a7bc39SJason Zhu
22237a7bc39SJason Zhu avb_memcpy(ret, str, len);
22337a7bc39SJason Zhu ret[len] = '\0';
22437a7bc39SJason Zhu
22537a7bc39SJason Zhu return ret;
22637a7bc39SJason Zhu }
22737a7bc39SJason Zhu
avb_strstr(const char * haystack,const char * needle)22837a7bc39SJason Zhu const char* avb_strstr(const char* haystack, const char* needle) {
22937a7bc39SJason Zhu size_t n, m;
23037a7bc39SJason Zhu
23137a7bc39SJason Zhu /* Look through |haystack| and check if the first character of
23237a7bc39SJason Zhu * |needle| matches. If so, check the rest of |needle|.
23337a7bc39SJason Zhu */
23437a7bc39SJason Zhu for (n = 0; haystack[n] != '\0'; n++) {
23537a7bc39SJason Zhu if (haystack[n] != needle[0]) {
23637a7bc39SJason Zhu continue;
23737a7bc39SJason Zhu }
23837a7bc39SJason Zhu
23937a7bc39SJason Zhu for (m = 1;; m++) {
24037a7bc39SJason Zhu if (needle[m] == '\0') {
24137a7bc39SJason Zhu return haystack + n;
24237a7bc39SJason Zhu }
24337a7bc39SJason Zhu
24437a7bc39SJason Zhu if (haystack[n + m] != needle[m]) {
24537a7bc39SJason Zhu break;
24637a7bc39SJason Zhu }
24737a7bc39SJason Zhu }
24837a7bc39SJason Zhu }
24937a7bc39SJason Zhu
25037a7bc39SJason Zhu return NULL;
25137a7bc39SJason Zhu }
25237a7bc39SJason Zhu
avb_strv_find_str(const char * const * strings,const char * str,size_t str_size)25337a7bc39SJason Zhu const char* avb_strv_find_str(const char* const* strings,
25437a7bc39SJason Zhu const char* str,
25537a7bc39SJason Zhu size_t str_size) {
25637a7bc39SJason Zhu size_t n;
25737a7bc39SJason Zhu for (n = 0; strings[n] != NULL; n++) {
25837a7bc39SJason Zhu if (avb_strlen(strings[n]) == str_size &&
25937a7bc39SJason Zhu avb_memcmp(strings[n], str, str_size) == 0) {
26037a7bc39SJason Zhu return strings[n];
26137a7bc39SJason Zhu }
26237a7bc39SJason Zhu }
26337a7bc39SJason Zhu return NULL;
26437a7bc39SJason Zhu }
26537a7bc39SJason Zhu
avb_replace(const char * str,const char * search,const char * replace)26637a7bc39SJason Zhu char* avb_replace(const char* str, const char* search, const char* replace) {
26737a7bc39SJason Zhu char* ret = NULL;
26837a7bc39SJason Zhu size_t ret_len = 0;
26937a7bc39SJason Zhu size_t search_len, replace_len;
27037a7bc39SJason Zhu const char* str_after_last_replace;
27137a7bc39SJason Zhu
27237a7bc39SJason Zhu search_len = avb_strlen(search);
27337a7bc39SJason Zhu replace_len = avb_strlen(replace);
27437a7bc39SJason Zhu
27537a7bc39SJason Zhu str_after_last_replace = str;
27637a7bc39SJason Zhu while (*str != '\0') {
27737a7bc39SJason Zhu const char* s;
27837a7bc39SJason Zhu size_t num_before;
27937a7bc39SJason Zhu size_t num_new;
28037a7bc39SJason Zhu
28137a7bc39SJason Zhu s = avb_strstr(str, search);
28237a7bc39SJason Zhu if (s == NULL) {
28337a7bc39SJason Zhu break;
28437a7bc39SJason Zhu }
28537a7bc39SJason Zhu
28637a7bc39SJason Zhu num_before = s - str;
28737a7bc39SJason Zhu
28837a7bc39SJason Zhu if (ret == NULL) {
28937a7bc39SJason Zhu num_new = num_before + replace_len + 1;
29037a7bc39SJason Zhu ret = avb_malloc(num_new);
29137a7bc39SJason Zhu if (ret == NULL) {
29237a7bc39SJason Zhu goto out;
29337a7bc39SJason Zhu }
29437a7bc39SJason Zhu avb_memcpy(ret, str, num_before);
29537a7bc39SJason Zhu avb_memcpy(ret + num_before, replace, replace_len);
29637a7bc39SJason Zhu ret[num_new - 1] = '\0';
29737a7bc39SJason Zhu ret_len = num_new - 1;
29837a7bc39SJason Zhu } else {
29937a7bc39SJason Zhu char* new_str;
30037a7bc39SJason Zhu num_new = ret_len + num_before + replace_len + 1;
30137a7bc39SJason Zhu new_str = avb_malloc(num_new);
30237a7bc39SJason Zhu if (new_str == NULL) {
30337a7bc39SJason Zhu goto out;
30437a7bc39SJason Zhu }
30537a7bc39SJason Zhu avb_memcpy(new_str, ret, ret_len);
30637a7bc39SJason Zhu avb_memcpy(new_str + ret_len, str, num_before);
30737a7bc39SJason Zhu avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
30837a7bc39SJason Zhu new_str[num_new - 1] = '\0';
30937a7bc39SJason Zhu avb_free(ret);
31037a7bc39SJason Zhu ret = new_str;
31137a7bc39SJason Zhu ret_len = num_new - 1;
31237a7bc39SJason Zhu }
31337a7bc39SJason Zhu
31437a7bc39SJason Zhu str = s + search_len;
31537a7bc39SJason Zhu str_after_last_replace = str;
31637a7bc39SJason Zhu }
31737a7bc39SJason Zhu
31837a7bc39SJason Zhu if (ret == NULL) {
31937a7bc39SJason Zhu ret = avb_strdup(str_after_last_replace);
32037a7bc39SJason Zhu if (ret == NULL) {
32137a7bc39SJason Zhu goto out;
32237a7bc39SJason Zhu }
32337a7bc39SJason Zhu } else {
32437a7bc39SJason Zhu size_t num_remaining = avb_strlen(str_after_last_replace);
32537a7bc39SJason Zhu size_t num_new = ret_len + num_remaining + 1;
32637a7bc39SJason Zhu char* new_str = avb_malloc(num_new);
32737a7bc39SJason Zhu if (new_str == NULL) {
32837a7bc39SJason Zhu goto out;
32937a7bc39SJason Zhu }
33037a7bc39SJason Zhu avb_memcpy(new_str, ret, ret_len);
33137a7bc39SJason Zhu avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
33237a7bc39SJason Zhu new_str[num_new - 1] = '\0';
33337a7bc39SJason Zhu avb_free(ret);
33437a7bc39SJason Zhu ret = new_str;
33537a7bc39SJason Zhu ret_len = num_new - 1;
33637a7bc39SJason Zhu }
33737a7bc39SJason Zhu
33837a7bc39SJason Zhu out:
33937a7bc39SJason Zhu return ret;
34037a7bc39SJason Zhu }
34137a7bc39SJason Zhu
34237a7bc39SJason Zhu /* We only support a limited amount of strings in avb_strdupv(). */
34337a7bc39SJason Zhu #define AVB_STRDUPV_MAX_NUM_STRINGS 32
34437a7bc39SJason Zhu
avb_strdupv(const char * str,...)34537a7bc39SJason Zhu char* avb_strdupv(const char* str, ...) {
34637a7bc39SJason Zhu va_list ap;
34737a7bc39SJason Zhu const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
34837a7bc39SJason Zhu size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
34937a7bc39SJason Zhu size_t num_strings, n;
35037a7bc39SJason Zhu uint64_t total_length;
35137a7bc39SJason Zhu char *ret = NULL, *dest;
35237a7bc39SJason Zhu
35337a7bc39SJason Zhu num_strings = 0;
35437a7bc39SJason Zhu total_length = 0;
35537a7bc39SJason Zhu va_start(ap, str);
35637a7bc39SJason Zhu do {
35737a7bc39SJason Zhu size_t str_len = avb_strlen(str);
35837a7bc39SJason Zhu strings[num_strings] = str;
35937a7bc39SJason Zhu lengths[num_strings] = str_len;
36037a7bc39SJason Zhu if (!avb_safe_add_to(&total_length, str_len)) {
36137a7bc39SJason Zhu avb_fatal("Overflow while determining total length.\n");
36237a7bc39SJason Zhu break;
36337a7bc39SJason Zhu }
36437a7bc39SJason Zhu num_strings++;
36537a7bc39SJason Zhu if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
36637a7bc39SJason Zhu avb_fatal("Too many strings passed.\n");
36737a7bc39SJason Zhu break;
36837a7bc39SJason Zhu }
36937a7bc39SJason Zhu str = va_arg(ap, const char*);
37037a7bc39SJason Zhu } while (str != NULL);
37137a7bc39SJason Zhu va_end(ap);
37237a7bc39SJason Zhu
37337a7bc39SJason Zhu ret = avb_malloc(total_length + 1);
37437a7bc39SJason Zhu if (ret == NULL) {
37537a7bc39SJason Zhu goto out;
37637a7bc39SJason Zhu }
37737a7bc39SJason Zhu
37837a7bc39SJason Zhu dest = ret;
37937a7bc39SJason Zhu for (n = 0; n < num_strings; n++) {
38037a7bc39SJason Zhu avb_memcpy(dest, strings[n], lengths[n]);
38137a7bc39SJason Zhu dest += lengths[n];
38237a7bc39SJason Zhu }
38337a7bc39SJason Zhu *dest = '\0';
38437a7bc39SJason Zhu avb_assert(dest == ret + total_length);
38537a7bc39SJason Zhu
38637a7bc39SJason Zhu out:
38737a7bc39SJason Zhu return ret;
38837a7bc39SJason Zhu }
38937a7bc39SJason Zhu
avb_basename(const char * str)39037a7bc39SJason Zhu const char* avb_basename(const char* str) {
39137a7bc39SJason Zhu int64_t n;
39237a7bc39SJason Zhu size_t len;
39337a7bc39SJason Zhu
39437a7bc39SJason Zhu len = avb_strlen(str);
39537a7bc39SJason Zhu if (len >= 2) {
39637a7bc39SJason Zhu for (n = len - 2; n >= 0; n--) {
39737a7bc39SJason Zhu if (str[n] == '/') {
39837a7bc39SJason Zhu return str + n + 1;
39937a7bc39SJason Zhu }
40037a7bc39SJason Zhu }
40137a7bc39SJason Zhu }
40237a7bc39SJason Zhu return str;
40337a7bc39SJason Zhu }
404*ab608f80SJason Zhu
avb_uppercase(char * str)405*ab608f80SJason Zhu void avb_uppercase(char* str) {
406*ab608f80SJason Zhu size_t i;
407*ab608f80SJason Zhu for (i = 0; str[i] != '\0'; ++i) {
408*ab608f80SJason Zhu if (str[i] <= 0x7A && str[i] >= 0x61) {
409*ab608f80SJason Zhu str[i] -= 0x20;
410*ab608f80SJason Zhu }
411*ab608f80SJason Zhu }
412*ab608f80SJason Zhu }
413*ab608f80SJason Zhu
avb_bin2hex(const uint8_t * data,size_t data_len)414*ab608f80SJason Zhu char* avb_bin2hex(const uint8_t* data, size_t data_len) {
415*ab608f80SJason Zhu const char hex_digits[17] = "0123456789abcdef";
416*ab608f80SJason Zhu char* hex_data;
417*ab608f80SJason Zhu size_t n;
418*ab608f80SJason Zhu
419*ab608f80SJason Zhu hex_data = avb_malloc(data_len * 2 + 1);
420*ab608f80SJason Zhu if (hex_data == NULL) {
421*ab608f80SJason Zhu return NULL;
422*ab608f80SJason Zhu }
423*ab608f80SJason Zhu
424*ab608f80SJason Zhu for (n = 0; n < data_len; n++) {
425*ab608f80SJason Zhu hex_data[n * 2] = hex_digits[data[n] >> 4];
426*ab608f80SJason Zhu hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
427*ab608f80SJason Zhu }
428*ab608f80SJason Zhu hex_data[n * 2] = '\0';
429*ab608f80SJason Zhu return hex_data;
430*ab608f80SJason Zhu }
431