121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen/*
221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen * Copyright (C) 2016 The Android Open Source Project
321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
4c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * Permission is hereby granted, free of charge, to any person
5c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * obtaining a copy of this software and associated documentation
6c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * files (the "Software"), to deal in the Software without
7c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * restriction, including without limitation the rights to use, copy,
8c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * modify, merge, publish, distribute, sublicense, and/or sell copies
9c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * of the Software, and to permit persons to whom the Software is
10c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * furnished to do so, subject to the following conditions:
1121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
12c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * The above copyright notice and this permission notice shall be
13c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * included in all copies or substantial portions of the Software.
1421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen *
15c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22c612e2e353444f6ad714e43702c2afd057516254David Zeuthen * SOFTWARE.
2321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen */
2421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen#include "avb_util.h"
2621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2719c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen#include <stdarg.h>
2819c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
2921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenuint32_t avb_be32toh(uint32_t in) {
3021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint8_t* d = (uint8_t*)&in;
3121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint32_t ret;
3221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret = ((uint32_t)d[0]) << 24;
3321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint32_t)d[1]) << 16;
3421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint32_t)d[2]) << 8;
3521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint32_t)d[3]);
3621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
3721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
3821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
3921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenuint64_t avb_be64toh(uint64_t in) {
4021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint8_t* d = (uint8_t*)&in;
4121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t ret;
4221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret = ((uint64_t)d[0]) << 56;
4321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[1]) << 48;
4421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[2]) << 40;
4521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[3]) << 32;
4621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[4]) << 24;
4721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[5]) << 16;
4821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[6]) << 8;
4921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret |= ((uint64_t)d[7]);
5021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
5121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
5221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
538b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
548b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthenuint32_t avb_htobe32(uint32_t in) {
558b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  union {
568b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen    uint32_t word;
578b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen    uint8_t bytes[4];
588b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  } ret;
598b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[0] = (in >> 24) & 0xff;
608b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[1] = (in >> 16) & 0xff;
618b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[2] = (in >> 8) & 0xff;
628b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[3] = in & 0xff;
638b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  return ret.word;
648b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen}
658b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen
668b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
678b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthenuint64_t avb_htobe64(uint64_t in) {
688b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  union {
698b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen    uint64_t word;
708b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen    uint8_t bytes[8];
718b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  } ret;
728b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[0] = (in >> 56) & 0xff;
738b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[1] = (in >> 48) & 0xff;
748b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[2] = (in >> 40) & 0xff;
758b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[3] = (in >> 32) & 0xff;
768b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[4] = (in >> 24) & 0xff;
778b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[5] = (in >> 16) & 0xff;
788b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[6] = (in >> 8) & 0xff;
798b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  ret.bytes[7] = in & 0xff;
808b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen  return ret.word;
818b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen}
828b6973be7468f5c0db42ff8fcd91f8e97a345a27David Zeuthen
8321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenint avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
8421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const unsigned char* us1 = s1;
8521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const unsigned char* us2 = s2;
8621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  int result = 0;
8721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
884b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (0 == n) {
894b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    return 0;
904b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
9121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
9221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /*
9321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * Code snippet without data-dependent branch due to Nate Lawson
9421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * (nate@root.org) of Root Labs.
9521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
964b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  while (n--) {
974b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    result |= *us1++ ^ *us2++;
984b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
9921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
10021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return result != 0;
10121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
10221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
10321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenbool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
10421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t original_value;
10521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
10621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_assert(value != NULL);
10721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
10821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  original_value = *value;
10921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
11021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  *value += value_to_add;
11121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (*value < original_value) {
11221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Overflow when adding values.\n");
11321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return false;
11421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
11521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
11621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return true;
11721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
11821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
11921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenbool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
12021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t dummy;
1214b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  if (out_result == NULL) {
1224b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    out_result = &dummy;
1234b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen  }
12421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  *out_result = a;
12521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return avb_safe_add_to(out_result, b);
12621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
12721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
12821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenbool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
12921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t n;
13021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  unsigned int num_cc;
13121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
13221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (n = 0, num_cc = 0; n < num_bytes; n++) {
13321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    uint8_t c = data[n];
13421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
13521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    if (num_cc > 0) {
13621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      if ((c & (0x80 | 0x40)) == 0x80) {
13721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        /* 10xx xxxx */
13821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      } else {
13921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        goto fail;
14021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      }
14121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      num_cc--;
14221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    } else {
14321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      if (c < 0x80) {
14421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        num_cc = 0;
14521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
14621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        /* 110x xxxx */
14721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        num_cc = 1;
14821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
14921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        /* 1110 xxxx */
15021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        num_cc = 2;
15121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
15221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen                 (0x80 | 0x40 | 0x20 | 0x10)) {
15321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        /* 1111 0xxx */
15421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        num_cc = 3;
15521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      } else {
15621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        goto fail;
15721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      }
15821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    }
15921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
16021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
16121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (num_cc != 0) {
16221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    goto fail;
16321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
16421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
16521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return true;
16621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
16721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenfail:
16821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return false;
16921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
17021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
1714b6a634e48353da1e119ebe0287299f7b919d778David Zeuthenbool avb_str_concat(char* buf,
1724b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t buf_size,
1734b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    const char* str1,
1744b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t str1_len,
1754b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    const char* str2,
1764b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                    size_t str2_len) {
17721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  uint64_t combined_len;
17821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
17921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
18021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Overflow when adding string sizes.\n");
18121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return false;
18221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
18321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
18421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (combined_len > buf_size - 1) {
18521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Insufficient buffer space.\n");
18621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return false;
18721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
18821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
18921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memcpy(buf, str1, str1_len);
19021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memcpy(buf + str1_len, str2, str2_len);
19121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  buf[combined_len] = '\0';
19221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
19321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return true;
19421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
19521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
19621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenvoid* avb_malloc(size_t size) {
19721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  void* ret = avb_malloc_(size);
19821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (ret == NULL) {
19921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_error("Failed to allocate memory.\n");
20021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return NULL;
20121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
20221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
20321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
20421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
20521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenvoid* avb_calloc(size_t size) {
20621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  void* ret = avb_malloc(size);
20721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (ret == NULL) {
20821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return NULL;
20921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
21021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
21121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memset(ret, '\0', size);
21221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
21321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
21421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
21521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenchar* avb_strdup(const char* str) {
21621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t len = avb_strlen(str);
21721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  char* ret = avb_malloc(len + 1);
21821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (ret == NULL) {
21921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    return NULL;
22021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
22121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
22221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  avb_memcpy(ret, str, len);
22321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  ret[len] = '\0';
22421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
22521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
22621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
22721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
22821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenconst char* avb_strstr(const char* haystack, const char* needle) {
22921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t n, m;
23021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
23121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  /* Look through |haystack| and check if the first character of
23221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   * |needle| matches. If so, check the rest of |needle|.
23321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen   */
23421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  for (n = 0; haystack[n] != '\0'; n++) {
2354b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (haystack[n] != needle[0]) {
2364b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      continue;
2374b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    }
23821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
23921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    for (m = 1;; m++) {
24021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      if (needle[m] == '\0') {
24121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        return haystack + n;
24221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      }
24321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2444b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      if (haystack[n + m] != needle[m]) {
2454b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen        break;
2464b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      }
24721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    }
24821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
24921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
25021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return NULL;
25121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
25221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
2534b6a634e48353da1e119ebe0287299f7b919d778David Zeuthenconst char* avb_strv_find_str(const char* const* strings,
2544b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen                              const char* str,
255a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen                              size_t str_size) {
256a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen  size_t n;
257a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen  for (n = 0; strings[n] != NULL; n++) {
258a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen    if (avb_strlen(strings[n]) == str_size &&
259a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen        avb_memcmp(strings[n], str, str_size) == 0) {
260a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen      return strings[n];
261a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen    }
262a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen  }
263a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen  return NULL;
264a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen}
265a8bb9a0e8635e3562367ebfe89b1870b4e2cc8e2David Zeuthen
26621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenchar* avb_replace(const char* str, const char* search, const char* replace) {
26721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  char* ret = NULL;
26821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t ret_len = 0;
26921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  size_t search_len, replace_len;
27021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  const char* str_after_last_replace;
27121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
27221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  search_len = avb_strlen(search);
27321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  replace_len = avb_strlen(replace);
27421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
27521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  str_after_last_replace = str;
27621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  while (*str != '\0') {
27721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    const char* s;
27821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    size_t num_before;
27921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    size_t num_new;
28021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
28121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    s = avb_strstr(str, search);
2824b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (s == NULL) {
2834b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      break;
2844b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    }
28521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
28621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    num_before = s - str;
28721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
28821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    if (ret == NULL) {
28921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      num_new = num_before + replace_len + 1;
29021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      ret = avb_malloc(num_new);
29121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      if (ret == NULL) {
29221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        goto out;
29321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      }
29421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_memcpy(ret, str, num_before);
29521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_memcpy(ret + num_before, replace, replace_len);
29621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      ret[num_new - 1] = '\0';
29721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      ret_len = num_new - 1;
29821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    } else {
29921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      char* new_str;
30021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      num_new = ret_len + num_before + replace_len + 1;
30121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      new_str = avb_malloc(num_new);
30221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      if (ret == NULL) {
30321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen        goto out;
30421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      }
30521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_memcpy(new_str, ret, ret_len);
30621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_memcpy(new_str + ret_len, str, num_before);
30721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
30821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      new_str[num_new - 1] = '\0';
30921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      avb_free(ret);
31021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      ret = new_str;
31121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      ret_len = num_new - 1;
31221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    }
31321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
31421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    str = s + search_len;
31521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    str_after_last_replace = str;
31621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
31721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
31821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  if (ret == NULL) {
31921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret = avb_strdup(str_after_last_replace);
32021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    if (ret == NULL) {
32121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen      goto out;
32221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    }
32321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  } else {
32421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    size_t num_remaining = avb_strlen(str_after_last_replace);
32521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    size_t num_new = ret_len + num_remaining + 1;
32621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    char* new_str = avb_malloc(num_new);
3274b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    if (ret == NULL) {
3284b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen      goto out;
3294b6a634e48353da1e119ebe0287299f7b919d778David Zeuthen    }
33021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_memcpy(new_str, ret, ret_len);
33121e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
33221e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    new_str[num_new - 1] = '\0';
33321e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    avb_free(ret);
33421e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret = new_str;
33521e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen    ret_len = num_new - 1;
33621e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  }
33721e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen
33821e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthenout:
33921e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen  return ret;
34021e95266704e572ced1c633bbc4aea9f42afa0a5David Zeuthen}
34119c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
34219c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen/* We only support a limited amount of strings in avb_strdupv(). */
343bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen#define AVB_STRDUPV_MAX_NUM_STRINGS 32
34419c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
34519c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthenchar* avb_strdupv(const char* str, ...) {
34619c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  va_list ap;
347bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen  const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
348bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen  size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
349bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen  size_t num_strings, n;
350bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen  uint64_t total_length;
35119c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  char *ret = NULL, *dest;
35219c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
35319c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  num_strings = 0;
35419c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  total_length = 0;
35519c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  va_start(ap, str);
35619c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  do {
357bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen    size_t str_len = avb_strlen(str);
35819c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    strings[num_strings] = str;
359bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen    lengths[num_strings] = str_len;
360bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen    if (!avb_safe_add_to(&total_length, str_len)) {
361bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen      avb_fatal("Overflow while determining total length.\n");
362bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen      break;
363bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen    }
36419c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    num_strings++;
365bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen    if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
366bc41cead048a90f63e3dd4335097c5588ec09345David Zeuthen      avb_fatal("Too many strings passed.\n");
36719c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen      break;
36819c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    }
36919c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    str = va_arg(ap, const char*);
37019c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  } while (str != NULL);
37119c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  va_end(ap);
37219c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
37319c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  ret = avb_malloc(total_length + 1);
37419c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  if (ret == NULL) {
37519c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    goto out;
37619c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  }
37719c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
37819c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  dest = ret;
37919c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  for (n = 0; n < num_strings; n++) {
38019c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    avb_memcpy(dest, strings[n], lengths[n]);
38119c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen    dest += lengths[n];
38219c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  }
38319c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  *dest = '\0';
38419c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  avb_assert(dest == ret + total_length);
38519c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen
38619c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthenout:
38719c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen  return ret;
38819c38437eb77101ac30b29135cca58fbc684eaceDavid Zeuthen}
389f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen
390f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthenconst char* avb_basename(const char* str) {
391f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  int64_t n;
392f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  size_t len;
393f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen
394f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  len = avb_strlen(str);
395f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  if (len >= 2) {
396f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen    for (n = len - 2; n >= 0; n--) {
397f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen      if (str[n] == '/') {
398f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen        return str + n + 1;
399f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen      }
400f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen    }
401f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  }
402f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen  return str;
403f1bdec37f0f97c0640667178b2ac152c54442dfcDavid Zeuthen}
404