1*d289c2baSAndroid Build Coastguard Worker /*
2*d289c2baSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*d289c2baSAndroid Build Coastguard Worker *
4*d289c2baSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person
5*d289c2baSAndroid Build Coastguard Worker * obtaining a copy of this software and associated documentation
6*d289c2baSAndroid Build Coastguard Worker * files (the "Software"), to deal in the Software without
7*d289c2baSAndroid Build Coastguard Worker * restriction, including without limitation the rights to use, copy,
8*d289c2baSAndroid Build Coastguard Worker * modify, merge, publish, distribute, sublicense, and/or sell copies
9*d289c2baSAndroid Build Coastguard Worker * of the Software, and to permit persons to whom the Software is
10*d289c2baSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
11*d289c2baSAndroid Build Coastguard Worker *
12*d289c2baSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*d289c2baSAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*d289c2baSAndroid Build Coastguard Worker *
15*d289c2baSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*d289c2baSAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*d289c2baSAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*d289c2baSAndroid Build Coastguard Worker * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*d289c2baSAndroid Build Coastguard Worker * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*d289c2baSAndroid Build Coastguard Worker * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*d289c2baSAndroid Build Coastguard Worker * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*d289c2baSAndroid Build Coastguard Worker * SOFTWARE.
23*d289c2baSAndroid Build Coastguard Worker */
24*d289c2baSAndroid Build Coastguard Worker
25*d289c2baSAndroid Build Coastguard Worker #include "avb_util.h"
26*d289c2baSAndroid Build Coastguard Worker
27*d289c2baSAndroid Build Coastguard Worker #include <stdarg.h>
28*d289c2baSAndroid Build Coastguard Worker
avb_be16toh(uint16_t in)29*d289c2baSAndroid Build Coastguard Worker uint16_t avb_be16toh(uint16_t in) {
30*d289c2baSAndroid Build Coastguard Worker uint8_t* d = (uint8_t*)∈
31*d289c2baSAndroid Build Coastguard Worker uint16_t ret;
32*d289c2baSAndroid Build Coastguard Worker ret = ((uint16_t)d[0]) << 8;
33*d289c2baSAndroid Build Coastguard Worker ret |= ((uint16_t)d[1]);
34*d289c2baSAndroid Build Coastguard Worker return ret;
35*d289c2baSAndroid Build Coastguard Worker }
36*d289c2baSAndroid Build Coastguard Worker
avb_be32toh(uint32_t in)37*d289c2baSAndroid Build Coastguard Worker uint32_t avb_be32toh(uint32_t in) {
38*d289c2baSAndroid Build Coastguard Worker uint8_t* d = (uint8_t*)∈
39*d289c2baSAndroid Build Coastguard Worker uint32_t ret;
40*d289c2baSAndroid Build Coastguard Worker ret = ((uint32_t)d[0]) << 24;
41*d289c2baSAndroid Build Coastguard Worker ret |= ((uint32_t)d[1]) << 16;
42*d289c2baSAndroid Build Coastguard Worker ret |= ((uint32_t)d[2]) << 8;
43*d289c2baSAndroid Build Coastguard Worker ret |= ((uint32_t)d[3]);
44*d289c2baSAndroid Build Coastguard Worker return ret;
45*d289c2baSAndroid Build Coastguard Worker }
46*d289c2baSAndroid Build Coastguard Worker
avb_be64toh(uint64_t in)47*d289c2baSAndroid Build Coastguard Worker uint64_t avb_be64toh(uint64_t in) {
48*d289c2baSAndroid Build Coastguard Worker uint8_t* d = (uint8_t*)∈
49*d289c2baSAndroid Build Coastguard Worker uint64_t ret;
50*d289c2baSAndroid Build Coastguard Worker ret = ((uint64_t)d[0]) << 56;
51*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[1]) << 48;
52*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[2]) << 40;
53*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[3]) << 32;
54*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[4]) << 24;
55*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[5]) << 16;
56*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[6]) << 8;
57*d289c2baSAndroid Build Coastguard Worker ret |= ((uint64_t)d[7]);
58*d289c2baSAndroid Build Coastguard Worker return ret;
59*d289c2baSAndroid Build Coastguard Worker }
60*d289c2baSAndroid Build Coastguard Worker
61*d289c2baSAndroid Build Coastguard Worker /* Converts a 16-bit unsigned integer from host to big-endian byte order. */
avb_htobe16(uint16_t in)62*d289c2baSAndroid Build Coastguard Worker uint16_t avb_htobe16(uint16_t in) {
63*d289c2baSAndroid Build Coastguard Worker union {
64*d289c2baSAndroid Build Coastguard Worker uint16_t word;
65*d289c2baSAndroid Build Coastguard Worker uint8_t bytes[2];
66*d289c2baSAndroid Build Coastguard Worker } ret;
67*d289c2baSAndroid Build Coastguard Worker ret.bytes[0] = (in >> 8) & 0xff;
68*d289c2baSAndroid Build Coastguard Worker ret.bytes[1] = in & 0xff;
69*d289c2baSAndroid Build Coastguard Worker return ret.word;
70*d289c2baSAndroid Build Coastguard Worker }
71*d289c2baSAndroid Build Coastguard Worker
72*d289c2baSAndroid Build Coastguard Worker /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
avb_htobe32(uint32_t in)73*d289c2baSAndroid Build Coastguard Worker uint32_t avb_htobe32(uint32_t in) {
74*d289c2baSAndroid Build Coastguard Worker union {
75*d289c2baSAndroid Build Coastguard Worker uint32_t word;
76*d289c2baSAndroid Build Coastguard Worker uint8_t bytes[4];
77*d289c2baSAndroid Build Coastguard Worker } ret;
78*d289c2baSAndroid Build Coastguard Worker ret.bytes[0] = (in >> 24) & 0xff;
79*d289c2baSAndroid Build Coastguard Worker ret.bytes[1] = (in >> 16) & 0xff;
80*d289c2baSAndroid Build Coastguard Worker ret.bytes[2] = (in >> 8) & 0xff;
81*d289c2baSAndroid Build Coastguard Worker ret.bytes[3] = in & 0xff;
82*d289c2baSAndroid Build Coastguard Worker return ret.word;
83*d289c2baSAndroid Build Coastguard Worker }
84*d289c2baSAndroid Build Coastguard Worker
85*d289c2baSAndroid Build Coastguard Worker /* Converts a 64-bit unsigned integer from host to big-endian byte order. */
avb_htobe64(uint64_t in)86*d289c2baSAndroid Build Coastguard Worker uint64_t avb_htobe64(uint64_t in) {
87*d289c2baSAndroid Build Coastguard Worker union {
88*d289c2baSAndroid Build Coastguard Worker uint64_t word;
89*d289c2baSAndroid Build Coastguard Worker uint8_t bytes[8];
90*d289c2baSAndroid Build Coastguard Worker } ret;
91*d289c2baSAndroid Build Coastguard Worker ret.bytes[0] = (in >> 56) & 0xff;
92*d289c2baSAndroid Build Coastguard Worker ret.bytes[1] = (in >> 48) & 0xff;
93*d289c2baSAndroid Build Coastguard Worker ret.bytes[2] = (in >> 40) & 0xff;
94*d289c2baSAndroid Build Coastguard Worker ret.bytes[3] = (in >> 32) & 0xff;
95*d289c2baSAndroid Build Coastguard Worker ret.bytes[4] = (in >> 24) & 0xff;
96*d289c2baSAndroid Build Coastguard Worker ret.bytes[5] = (in >> 16) & 0xff;
97*d289c2baSAndroid Build Coastguard Worker ret.bytes[6] = (in >> 8) & 0xff;
98*d289c2baSAndroid Build Coastguard Worker ret.bytes[7] = in & 0xff;
99*d289c2baSAndroid Build Coastguard Worker return ret.word;
100*d289c2baSAndroid Build Coastguard Worker }
101*d289c2baSAndroid Build Coastguard Worker
avb_safe_memcmp(const void * s1,const void * s2,size_t n)102*d289c2baSAndroid Build Coastguard Worker int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
103*d289c2baSAndroid Build Coastguard Worker const unsigned char* us1 = s1;
104*d289c2baSAndroid Build Coastguard Worker const unsigned char* us2 = s2;
105*d289c2baSAndroid Build Coastguard Worker int result = 0;
106*d289c2baSAndroid Build Coastguard Worker
107*d289c2baSAndroid Build Coastguard Worker if (0 == n) {
108*d289c2baSAndroid Build Coastguard Worker return 0;
109*d289c2baSAndroid Build Coastguard Worker }
110*d289c2baSAndroid Build Coastguard Worker
111*d289c2baSAndroid Build Coastguard Worker /*
112*d289c2baSAndroid Build Coastguard Worker * Code snippet without data-dependent branch due to Nate Lawson
113*d289c2baSAndroid Build Coastguard Worker * ([email protected]) of Root Labs.
114*d289c2baSAndroid Build Coastguard Worker */
115*d289c2baSAndroid Build Coastguard Worker while (n--) {
116*d289c2baSAndroid Build Coastguard Worker result |= *us1++ ^ *us2++;
117*d289c2baSAndroid Build Coastguard Worker }
118*d289c2baSAndroid Build Coastguard Worker
119*d289c2baSAndroid Build Coastguard Worker return result != 0;
120*d289c2baSAndroid Build Coastguard Worker }
121*d289c2baSAndroid Build Coastguard Worker
avb_safe_add_to(uint64_t * value,uint64_t value_to_add)122*d289c2baSAndroid Build Coastguard Worker bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
123*d289c2baSAndroid Build Coastguard Worker uint64_t original_value;
124*d289c2baSAndroid Build Coastguard Worker
125*d289c2baSAndroid Build Coastguard Worker avb_assert(value != NULL);
126*d289c2baSAndroid Build Coastguard Worker
127*d289c2baSAndroid Build Coastguard Worker original_value = *value;
128*d289c2baSAndroid Build Coastguard Worker
129*d289c2baSAndroid Build Coastguard Worker *value += value_to_add;
130*d289c2baSAndroid Build Coastguard Worker if (*value < original_value) {
131*d289c2baSAndroid Build Coastguard Worker avb_error("Overflow when adding values.\n");
132*d289c2baSAndroid Build Coastguard Worker return false;
133*d289c2baSAndroid Build Coastguard Worker }
134*d289c2baSAndroid Build Coastguard Worker
135*d289c2baSAndroid Build Coastguard Worker return true;
136*d289c2baSAndroid Build Coastguard Worker }
137*d289c2baSAndroid Build Coastguard Worker
avb_safe_add(uint64_t * out_result,uint64_t a,uint64_t b)138*d289c2baSAndroid Build Coastguard Worker bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
139*d289c2baSAndroid Build Coastguard Worker uint64_t dummy;
140*d289c2baSAndroid Build Coastguard Worker if (out_result == NULL) {
141*d289c2baSAndroid Build Coastguard Worker out_result = &dummy;
142*d289c2baSAndroid Build Coastguard Worker }
143*d289c2baSAndroid Build Coastguard Worker *out_result = a;
144*d289c2baSAndroid Build Coastguard Worker return avb_safe_add_to(out_result, b);
145*d289c2baSAndroid Build Coastguard Worker }
146*d289c2baSAndroid Build Coastguard Worker
avb_validate_utf8(const uint8_t * data,size_t num_bytes)147*d289c2baSAndroid Build Coastguard Worker bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
148*d289c2baSAndroid Build Coastguard Worker size_t n;
149*d289c2baSAndroid Build Coastguard Worker unsigned int num_cc;
150*d289c2baSAndroid Build Coastguard Worker
151*d289c2baSAndroid Build Coastguard Worker for (n = 0, num_cc = 0; n < num_bytes; n++) {
152*d289c2baSAndroid Build Coastguard Worker uint8_t c = data[n];
153*d289c2baSAndroid Build Coastguard Worker
154*d289c2baSAndroid Build Coastguard Worker if (num_cc > 0) {
155*d289c2baSAndroid Build Coastguard Worker if ((c & (0x80 | 0x40)) == 0x80) {
156*d289c2baSAndroid Build Coastguard Worker /* 10xx xxxx */
157*d289c2baSAndroid Build Coastguard Worker } else {
158*d289c2baSAndroid Build Coastguard Worker goto fail;
159*d289c2baSAndroid Build Coastguard Worker }
160*d289c2baSAndroid Build Coastguard Worker num_cc--;
161*d289c2baSAndroid Build Coastguard Worker } else {
162*d289c2baSAndroid Build Coastguard Worker if (c < 0x80) {
163*d289c2baSAndroid Build Coastguard Worker num_cc = 0;
164*d289c2baSAndroid Build Coastguard Worker } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
165*d289c2baSAndroid Build Coastguard Worker /* 110x xxxx */
166*d289c2baSAndroid Build Coastguard Worker num_cc = 1;
167*d289c2baSAndroid Build Coastguard Worker } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
168*d289c2baSAndroid Build Coastguard Worker /* 1110 xxxx */
169*d289c2baSAndroid Build Coastguard Worker num_cc = 2;
170*d289c2baSAndroid Build Coastguard Worker } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
171*d289c2baSAndroid Build Coastguard Worker (0x80 | 0x40 | 0x20 | 0x10)) {
172*d289c2baSAndroid Build Coastguard Worker /* 1111 0xxx */
173*d289c2baSAndroid Build Coastguard Worker num_cc = 3;
174*d289c2baSAndroid Build Coastguard Worker } else {
175*d289c2baSAndroid Build Coastguard Worker goto fail;
176*d289c2baSAndroid Build Coastguard Worker }
177*d289c2baSAndroid Build Coastguard Worker }
178*d289c2baSAndroid Build Coastguard Worker }
179*d289c2baSAndroid Build Coastguard Worker
180*d289c2baSAndroid Build Coastguard Worker if (num_cc != 0) {
181*d289c2baSAndroid Build Coastguard Worker goto fail;
182*d289c2baSAndroid Build Coastguard Worker }
183*d289c2baSAndroid Build Coastguard Worker
184*d289c2baSAndroid Build Coastguard Worker return true;
185*d289c2baSAndroid Build Coastguard Worker
186*d289c2baSAndroid Build Coastguard Worker fail:
187*d289c2baSAndroid Build Coastguard Worker return false;
188*d289c2baSAndroid Build Coastguard Worker }
189*d289c2baSAndroid Build Coastguard Worker
avb_str_concat(char * buf,size_t buf_size,const char * str1,size_t str1_len,const char * str2,size_t str2_len)190*d289c2baSAndroid Build Coastguard Worker bool avb_str_concat(char* buf,
191*d289c2baSAndroid Build Coastguard Worker size_t buf_size,
192*d289c2baSAndroid Build Coastguard Worker const char* str1,
193*d289c2baSAndroid Build Coastguard Worker size_t str1_len,
194*d289c2baSAndroid Build Coastguard Worker const char* str2,
195*d289c2baSAndroid Build Coastguard Worker size_t str2_len) {
196*d289c2baSAndroid Build Coastguard Worker uint64_t combined_len;
197*d289c2baSAndroid Build Coastguard Worker
198*d289c2baSAndroid Build Coastguard Worker // Doesn't make sense to pass 0 for buf_size since there's
199*d289c2baSAndroid Build Coastguard Worker // no room for the terminating NUL byte.
200*d289c2baSAndroid Build Coastguard Worker if (buf_size == 0) {
201*d289c2baSAndroid Build Coastguard Worker return false;
202*d289c2baSAndroid Build Coastguard Worker }
203*d289c2baSAndroid Build Coastguard Worker
204*d289c2baSAndroid Build Coastguard Worker if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
205*d289c2baSAndroid Build Coastguard Worker avb_error("Overflow when adding string sizes.\n");
206*d289c2baSAndroid Build Coastguard Worker return false;
207*d289c2baSAndroid Build Coastguard Worker }
208*d289c2baSAndroid Build Coastguard Worker
209*d289c2baSAndroid Build Coastguard Worker if (combined_len > buf_size - 1) {
210*d289c2baSAndroid Build Coastguard Worker avb_error("Insufficient buffer space.\n");
211*d289c2baSAndroid Build Coastguard Worker return false;
212*d289c2baSAndroid Build Coastguard Worker }
213*d289c2baSAndroid Build Coastguard Worker
214*d289c2baSAndroid Build Coastguard Worker avb_memcpy(buf, str1, str1_len);
215*d289c2baSAndroid Build Coastguard Worker avb_memcpy(buf + str1_len, str2, str2_len);
216*d289c2baSAndroid Build Coastguard Worker buf[combined_len] = '\0';
217*d289c2baSAndroid Build Coastguard Worker
218*d289c2baSAndroid Build Coastguard Worker return true;
219*d289c2baSAndroid Build Coastguard Worker }
220*d289c2baSAndroid Build Coastguard Worker
avb_malloc(size_t size)221*d289c2baSAndroid Build Coastguard Worker void* avb_malloc(size_t size) {
222*d289c2baSAndroid Build Coastguard Worker void* ret = avb_malloc_(size);
223*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
224*d289c2baSAndroid Build Coastguard Worker avb_error("Failed to allocate memory.\n");
225*d289c2baSAndroid Build Coastguard Worker return NULL;
226*d289c2baSAndroid Build Coastguard Worker }
227*d289c2baSAndroid Build Coastguard Worker return ret;
228*d289c2baSAndroid Build Coastguard Worker }
229*d289c2baSAndroid Build Coastguard Worker
avb_calloc(size_t size)230*d289c2baSAndroid Build Coastguard Worker void* avb_calloc(size_t size) {
231*d289c2baSAndroid Build Coastguard Worker void* ret = avb_malloc(size);
232*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
233*d289c2baSAndroid Build Coastguard Worker return NULL;
234*d289c2baSAndroid Build Coastguard Worker }
235*d289c2baSAndroid Build Coastguard Worker
236*d289c2baSAndroid Build Coastguard Worker avb_memset(ret, '\0', size);
237*d289c2baSAndroid Build Coastguard Worker return ret;
238*d289c2baSAndroid Build Coastguard Worker }
239*d289c2baSAndroid Build Coastguard Worker
avb_strdup(const char * str)240*d289c2baSAndroid Build Coastguard Worker char* avb_strdup(const char* str) {
241*d289c2baSAndroid Build Coastguard Worker size_t len = avb_strlen(str);
242*d289c2baSAndroid Build Coastguard Worker char* ret = avb_malloc(len + 1);
243*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
244*d289c2baSAndroid Build Coastguard Worker return NULL;
245*d289c2baSAndroid Build Coastguard Worker }
246*d289c2baSAndroid Build Coastguard Worker
247*d289c2baSAndroid Build Coastguard Worker avb_memcpy(ret, str, len);
248*d289c2baSAndroid Build Coastguard Worker ret[len] = '\0';
249*d289c2baSAndroid Build Coastguard Worker
250*d289c2baSAndroid Build Coastguard Worker return ret;
251*d289c2baSAndroid Build Coastguard Worker }
252*d289c2baSAndroid Build Coastguard Worker
avb_strstr(const char * haystack,const char * needle)253*d289c2baSAndroid Build Coastguard Worker const char* avb_strstr(const char* haystack, const char* needle) {
254*d289c2baSAndroid Build Coastguard Worker size_t n, m;
255*d289c2baSAndroid Build Coastguard Worker
256*d289c2baSAndroid Build Coastguard Worker /* Look through |haystack| and check if the first character of
257*d289c2baSAndroid Build Coastguard Worker * |needle| matches. If so, check the rest of |needle|.
258*d289c2baSAndroid Build Coastguard Worker */
259*d289c2baSAndroid Build Coastguard Worker for (n = 0; haystack[n] != '\0'; n++) {
260*d289c2baSAndroid Build Coastguard Worker if (haystack[n] != needle[0]) {
261*d289c2baSAndroid Build Coastguard Worker continue;
262*d289c2baSAndroid Build Coastguard Worker }
263*d289c2baSAndroid Build Coastguard Worker
264*d289c2baSAndroid Build Coastguard Worker for (m = 1;; m++) {
265*d289c2baSAndroid Build Coastguard Worker if (needle[m] == '\0') {
266*d289c2baSAndroid Build Coastguard Worker return haystack + n;
267*d289c2baSAndroid Build Coastguard Worker }
268*d289c2baSAndroid Build Coastguard Worker
269*d289c2baSAndroid Build Coastguard Worker if (haystack[n + m] != needle[m]) {
270*d289c2baSAndroid Build Coastguard Worker break;
271*d289c2baSAndroid Build Coastguard Worker }
272*d289c2baSAndroid Build Coastguard Worker }
273*d289c2baSAndroid Build Coastguard Worker }
274*d289c2baSAndroid Build Coastguard Worker
275*d289c2baSAndroid Build Coastguard Worker return NULL;
276*d289c2baSAndroid Build Coastguard Worker }
277*d289c2baSAndroid Build Coastguard Worker
avb_strv_find_str(const char * const * strings,const char * str,size_t str_size)278*d289c2baSAndroid Build Coastguard Worker const char* avb_strv_find_str(const char* const* strings,
279*d289c2baSAndroid Build Coastguard Worker const char* str,
280*d289c2baSAndroid Build Coastguard Worker size_t str_size) {
281*d289c2baSAndroid Build Coastguard Worker size_t n;
282*d289c2baSAndroid Build Coastguard Worker for (n = 0; strings[n] != NULL; n++) {
283*d289c2baSAndroid Build Coastguard Worker if (avb_strlen(strings[n]) == str_size &&
284*d289c2baSAndroid Build Coastguard Worker avb_memcmp(strings[n], str, str_size) == 0) {
285*d289c2baSAndroid Build Coastguard Worker return strings[n];
286*d289c2baSAndroid Build Coastguard Worker }
287*d289c2baSAndroid Build Coastguard Worker }
288*d289c2baSAndroid Build Coastguard Worker return NULL;
289*d289c2baSAndroid Build Coastguard Worker }
290*d289c2baSAndroid Build Coastguard Worker
avb_replace(const char * str,const char * search,const char * replace)291*d289c2baSAndroid Build Coastguard Worker char* avb_replace(const char* str, const char* search, const char* replace) {
292*d289c2baSAndroid Build Coastguard Worker char* ret = NULL;
293*d289c2baSAndroid Build Coastguard Worker size_t ret_len = 0;
294*d289c2baSAndroid Build Coastguard Worker size_t search_len, replace_len;
295*d289c2baSAndroid Build Coastguard Worker const char* str_after_last_replace;
296*d289c2baSAndroid Build Coastguard Worker
297*d289c2baSAndroid Build Coastguard Worker search_len = avb_strlen(search);
298*d289c2baSAndroid Build Coastguard Worker replace_len = avb_strlen(replace);
299*d289c2baSAndroid Build Coastguard Worker
300*d289c2baSAndroid Build Coastguard Worker str_after_last_replace = str;
301*d289c2baSAndroid Build Coastguard Worker while (*str != '\0') {
302*d289c2baSAndroid Build Coastguard Worker const char* s;
303*d289c2baSAndroid Build Coastguard Worker size_t num_before;
304*d289c2baSAndroid Build Coastguard Worker size_t num_new;
305*d289c2baSAndroid Build Coastguard Worker
306*d289c2baSAndroid Build Coastguard Worker s = avb_strstr(str, search);
307*d289c2baSAndroid Build Coastguard Worker if (s == NULL) {
308*d289c2baSAndroid Build Coastguard Worker break;
309*d289c2baSAndroid Build Coastguard Worker }
310*d289c2baSAndroid Build Coastguard Worker
311*d289c2baSAndroid Build Coastguard Worker num_before = s - str;
312*d289c2baSAndroid Build Coastguard Worker
313*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
314*d289c2baSAndroid Build Coastguard Worker num_new = num_before + replace_len + 1;
315*d289c2baSAndroid Build Coastguard Worker ret = avb_malloc(num_new);
316*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
317*d289c2baSAndroid Build Coastguard Worker goto out;
318*d289c2baSAndroid Build Coastguard Worker }
319*d289c2baSAndroid Build Coastguard Worker avb_memcpy(ret, str, num_before);
320*d289c2baSAndroid Build Coastguard Worker avb_memcpy(ret + num_before, replace, replace_len);
321*d289c2baSAndroid Build Coastguard Worker ret[num_new - 1] = '\0';
322*d289c2baSAndroid Build Coastguard Worker ret_len = num_new - 1;
323*d289c2baSAndroid Build Coastguard Worker } else {
324*d289c2baSAndroid Build Coastguard Worker char* new_str;
325*d289c2baSAndroid Build Coastguard Worker num_new = ret_len + num_before + replace_len + 1;
326*d289c2baSAndroid Build Coastguard Worker new_str = avb_malloc(num_new);
327*d289c2baSAndroid Build Coastguard Worker if (new_str == NULL) {
328*d289c2baSAndroid Build Coastguard Worker goto out;
329*d289c2baSAndroid Build Coastguard Worker }
330*d289c2baSAndroid Build Coastguard Worker avb_memcpy(new_str, ret, ret_len);
331*d289c2baSAndroid Build Coastguard Worker avb_memcpy(new_str + ret_len, str, num_before);
332*d289c2baSAndroid Build Coastguard Worker avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
333*d289c2baSAndroid Build Coastguard Worker new_str[num_new - 1] = '\0';
334*d289c2baSAndroid Build Coastguard Worker avb_free(ret);
335*d289c2baSAndroid Build Coastguard Worker ret = new_str;
336*d289c2baSAndroid Build Coastguard Worker ret_len = num_new - 1;
337*d289c2baSAndroid Build Coastguard Worker }
338*d289c2baSAndroid Build Coastguard Worker
339*d289c2baSAndroid Build Coastguard Worker str = s + search_len;
340*d289c2baSAndroid Build Coastguard Worker str_after_last_replace = str;
341*d289c2baSAndroid Build Coastguard Worker }
342*d289c2baSAndroid Build Coastguard Worker
343*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
344*d289c2baSAndroid Build Coastguard Worker ret = avb_strdup(str_after_last_replace);
345*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
346*d289c2baSAndroid Build Coastguard Worker goto out;
347*d289c2baSAndroid Build Coastguard Worker }
348*d289c2baSAndroid Build Coastguard Worker } else {
349*d289c2baSAndroid Build Coastguard Worker size_t num_remaining = avb_strlen(str_after_last_replace);
350*d289c2baSAndroid Build Coastguard Worker size_t num_new = ret_len + num_remaining + 1;
351*d289c2baSAndroid Build Coastguard Worker char* new_str = avb_malloc(num_new);
352*d289c2baSAndroid Build Coastguard Worker if (new_str == NULL) {
353*d289c2baSAndroid Build Coastguard Worker goto out;
354*d289c2baSAndroid Build Coastguard Worker }
355*d289c2baSAndroid Build Coastguard Worker avb_memcpy(new_str, ret, ret_len);
356*d289c2baSAndroid Build Coastguard Worker avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
357*d289c2baSAndroid Build Coastguard Worker new_str[num_new - 1] = '\0';
358*d289c2baSAndroid Build Coastguard Worker avb_free(ret);
359*d289c2baSAndroid Build Coastguard Worker ret = new_str;
360*d289c2baSAndroid Build Coastguard Worker ret_len = num_new - 1;
361*d289c2baSAndroid Build Coastguard Worker }
362*d289c2baSAndroid Build Coastguard Worker
363*d289c2baSAndroid Build Coastguard Worker out:
364*d289c2baSAndroid Build Coastguard Worker return ret;
365*d289c2baSAndroid Build Coastguard Worker }
366*d289c2baSAndroid Build Coastguard Worker
367*d289c2baSAndroid Build Coastguard Worker /* We only support a limited amount of strings in avb_strdupv(). */
368*d289c2baSAndroid Build Coastguard Worker #define AVB_STRDUPV_MAX_NUM_STRINGS 32
369*d289c2baSAndroid Build Coastguard Worker
avb_strdupv(const char * str,...)370*d289c2baSAndroid Build Coastguard Worker char* avb_strdupv(const char* str, ...) {
371*d289c2baSAndroid Build Coastguard Worker va_list ap;
372*d289c2baSAndroid Build Coastguard Worker const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
373*d289c2baSAndroid Build Coastguard Worker size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
374*d289c2baSAndroid Build Coastguard Worker size_t num_strings, n;
375*d289c2baSAndroid Build Coastguard Worker uint64_t total_length;
376*d289c2baSAndroid Build Coastguard Worker char *ret = NULL, *dest;
377*d289c2baSAndroid Build Coastguard Worker
378*d289c2baSAndroid Build Coastguard Worker num_strings = 0;
379*d289c2baSAndroid Build Coastguard Worker total_length = 0;
380*d289c2baSAndroid Build Coastguard Worker va_start(ap, str);
381*d289c2baSAndroid Build Coastguard Worker do {
382*d289c2baSAndroid Build Coastguard Worker size_t str_len = avb_strlen(str);
383*d289c2baSAndroid Build Coastguard Worker strings[num_strings] = str;
384*d289c2baSAndroid Build Coastguard Worker lengths[num_strings] = str_len;
385*d289c2baSAndroid Build Coastguard Worker if (!avb_safe_add_to(&total_length, str_len)) {
386*d289c2baSAndroid Build Coastguard Worker avb_fatal("Overflow while determining total length.\n");
387*d289c2baSAndroid Build Coastguard Worker break;
388*d289c2baSAndroid Build Coastguard Worker }
389*d289c2baSAndroid Build Coastguard Worker num_strings++;
390*d289c2baSAndroid Build Coastguard Worker if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
391*d289c2baSAndroid Build Coastguard Worker avb_fatal("Too many strings passed.\n");
392*d289c2baSAndroid Build Coastguard Worker break;
393*d289c2baSAndroid Build Coastguard Worker }
394*d289c2baSAndroid Build Coastguard Worker str = va_arg(ap, const char*);
395*d289c2baSAndroid Build Coastguard Worker } while (str != NULL);
396*d289c2baSAndroid Build Coastguard Worker va_end(ap);
397*d289c2baSAndroid Build Coastguard Worker
398*d289c2baSAndroid Build Coastguard Worker ret = avb_malloc(total_length + 1);
399*d289c2baSAndroid Build Coastguard Worker if (ret == NULL) {
400*d289c2baSAndroid Build Coastguard Worker goto out;
401*d289c2baSAndroid Build Coastguard Worker }
402*d289c2baSAndroid Build Coastguard Worker
403*d289c2baSAndroid Build Coastguard Worker dest = ret;
404*d289c2baSAndroid Build Coastguard Worker for (n = 0; n < num_strings; n++) {
405*d289c2baSAndroid Build Coastguard Worker avb_memcpy(dest, strings[n], lengths[n]);
406*d289c2baSAndroid Build Coastguard Worker dest += lengths[n];
407*d289c2baSAndroid Build Coastguard Worker }
408*d289c2baSAndroid Build Coastguard Worker *dest = '\0';
409*d289c2baSAndroid Build Coastguard Worker avb_assert(dest == ret + total_length);
410*d289c2baSAndroid Build Coastguard Worker
411*d289c2baSAndroid Build Coastguard Worker out:
412*d289c2baSAndroid Build Coastguard Worker return ret;
413*d289c2baSAndroid Build Coastguard Worker }
414*d289c2baSAndroid Build Coastguard Worker
avb_basename(const char * str)415*d289c2baSAndroid Build Coastguard Worker const char* avb_basename(const char* str) {
416*d289c2baSAndroid Build Coastguard Worker int64_t n;
417*d289c2baSAndroid Build Coastguard Worker size_t len;
418*d289c2baSAndroid Build Coastguard Worker
419*d289c2baSAndroid Build Coastguard Worker len = avb_strlen(str);
420*d289c2baSAndroid Build Coastguard Worker if (len >= 2) {
421*d289c2baSAndroid Build Coastguard Worker for (n = len - 2; n >= 0; n--) {
422*d289c2baSAndroid Build Coastguard Worker if (str[n] == '/') {
423*d289c2baSAndroid Build Coastguard Worker return str + n + 1;
424*d289c2baSAndroid Build Coastguard Worker }
425*d289c2baSAndroid Build Coastguard Worker }
426*d289c2baSAndroid Build Coastguard Worker }
427*d289c2baSAndroid Build Coastguard Worker return str;
428*d289c2baSAndroid Build Coastguard Worker }
429*d289c2baSAndroid Build Coastguard Worker
avb_uppercase(char * str)430*d289c2baSAndroid Build Coastguard Worker void avb_uppercase(char* str) {
431*d289c2baSAndroid Build Coastguard Worker size_t i;
432*d289c2baSAndroid Build Coastguard Worker for (i = 0; str[i] != '\0'; ++i) {
433*d289c2baSAndroid Build Coastguard Worker if (str[i] <= 0x7A && str[i] >= 0x61) {
434*d289c2baSAndroid Build Coastguard Worker str[i] -= 0x20;
435*d289c2baSAndroid Build Coastguard Worker }
436*d289c2baSAndroid Build Coastguard Worker }
437*d289c2baSAndroid Build Coastguard Worker }
438*d289c2baSAndroid Build Coastguard Worker
avb_bin2hex(const uint8_t * data,size_t data_len)439*d289c2baSAndroid Build Coastguard Worker char* avb_bin2hex(const uint8_t* data, size_t data_len) {
440*d289c2baSAndroid Build Coastguard Worker const char hex_digits[17] = "0123456789abcdef";
441*d289c2baSAndroid Build Coastguard Worker char* hex_data;
442*d289c2baSAndroid Build Coastguard Worker size_t n;
443*d289c2baSAndroid Build Coastguard Worker
444*d289c2baSAndroid Build Coastguard Worker hex_data = avb_malloc(data_len * 2 + 1);
445*d289c2baSAndroid Build Coastguard Worker if (hex_data == NULL) {
446*d289c2baSAndroid Build Coastguard Worker return NULL;
447*d289c2baSAndroid Build Coastguard Worker }
448*d289c2baSAndroid Build Coastguard Worker
449*d289c2baSAndroid Build Coastguard Worker for (n = 0; n < data_len; n++) {
450*d289c2baSAndroid Build Coastguard Worker hex_data[n * 2] = hex_digits[data[n] >> 4];
451*d289c2baSAndroid Build Coastguard Worker hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
452*d289c2baSAndroid Build Coastguard Worker }
453*d289c2baSAndroid Build Coastguard Worker hex_data[n * 2] = '\0';
454*d289c2baSAndroid Build Coastguard Worker return hex_data;
455*d289c2baSAndroid Build Coastguard Worker }
456*d289c2baSAndroid Build Coastguard Worker
avb_uint64_to_base10(uint64_t value,char digits[AVB_MAX_DIGITS_UINT64])457*d289c2baSAndroid Build Coastguard Worker size_t avb_uint64_to_base10(uint64_t value,
458*d289c2baSAndroid Build Coastguard Worker char digits[AVB_MAX_DIGITS_UINT64]) {
459*d289c2baSAndroid Build Coastguard Worker char rev_digits[AVB_MAX_DIGITS_UINT64];
460*d289c2baSAndroid Build Coastguard Worker size_t n, num_digits;
461*d289c2baSAndroid Build Coastguard Worker
462*d289c2baSAndroid Build Coastguard Worker for (num_digits = 0; num_digits < AVB_MAX_DIGITS_UINT64 - 1;) {
463*d289c2baSAndroid Build Coastguard Worker rev_digits[num_digits++] = avb_div_by_10(&value) + '0';
464*d289c2baSAndroid Build Coastguard Worker if (value == 0) {
465*d289c2baSAndroid Build Coastguard Worker break;
466*d289c2baSAndroid Build Coastguard Worker }
467*d289c2baSAndroid Build Coastguard Worker }
468*d289c2baSAndroid Build Coastguard Worker
469*d289c2baSAndroid Build Coastguard Worker for (n = 0; n < num_digits; n++) {
470*d289c2baSAndroid Build Coastguard Worker digits[n] = rev_digits[num_digits - 1 - n];
471*d289c2baSAndroid Build Coastguard Worker }
472*d289c2baSAndroid Build Coastguard Worker digits[n] = '\0';
473*d289c2baSAndroid Build Coastguard Worker return n;
474*d289c2baSAndroid Build Coastguard Worker }
475