/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "avb_util.h"

uint32_t avb_be32toh(uint32_t in) {
  uint8_t* d = (uint8_t*)&in;
  uint32_t ret;
  ret = ((uint32_t)d[0]) << 24;
  ret |= ((uint32_t)d[1]) << 16;
  ret |= ((uint32_t)d[2]) << 8;
  ret |= ((uint32_t)d[3]);
  return ret;
}

uint64_t avb_be64toh(uint64_t in) {
  uint8_t* d = (uint8_t*)&in;
  uint64_t ret;
  ret = ((uint64_t)d[0]) << 56;
  ret |= ((uint64_t)d[1]) << 48;
  ret |= ((uint64_t)d[2]) << 40;
  ret |= ((uint64_t)d[3]) << 32;
  ret |= ((uint64_t)d[4]) << 24;
  ret |= ((uint64_t)d[5]) << 16;
  ret |= ((uint64_t)d[6]) << 8;
  ret |= ((uint64_t)d[7]);
  return ret;
}

/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
uint32_t avb_htobe32(uint32_t in) {
  union {
    uint32_t word;
    uint8_t bytes[4];
  } ret;
  ret.bytes[0] = (in >> 24) & 0xff;
  ret.bytes[1] = (in >> 16) & 0xff;
  ret.bytes[2] = (in >> 8) & 0xff;
  ret.bytes[3] = in & 0xff;
  return ret.word;
}

/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
uint64_t avb_htobe64(uint64_t in) {
  union {
    uint64_t word;
    uint8_t bytes[8];
  } ret;
  ret.bytes[0] = (in >> 56) & 0xff;
  ret.bytes[1] = (in >> 48) & 0xff;
  ret.bytes[2] = (in >> 40) & 0xff;
  ret.bytes[3] = (in >> 32) & 0xff;
  ret.bytes[4] = (in >> 24) & 0xff;
  ret.bytes[5] = (in >> 16) & 0xff;
  ret.bytes[6] = (in >> 8) & 0xff;
  ret.bytes[7] = in & 0xff;
  return ret.word;
}

int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
  const unsigned char* us1 = s1;
  const unsigned char* us2 = s2;
  int result = 0;

  if (0 == n) return 0;

  /*
   * Code snippet without data-dependent branch due to Nate Lawson
   * (nate@root.org) of Root Labs.
   */
  while (n--) result |= *us1++ ^ *us2++;

  return result != 0;
}

bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
  uint64_t original_value;

  avb_assert(value != NULL);

  original_value = *value;

  *value += value_to_add;
  if (*value < original_value) {
    avb_error("Overflow when adding values.\n");
    return false;
  }

  return true;
}

bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
  uint64_t dummy;
  if (out_result == NULL) out_result = &dummy;
  *out_result = a;
  return avb_safe_add_to(out_result, b);
}

bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
  size_t n;
  unsigned int num_cc;

  for (n = 0, num_cc = 0; n < num_bytes; n++) {
    uint8_t c = data[n];

    if (num_cc > 0) {
      if ((c & (0x80 | 0x40)) == 0x80) {
        /* 10xx xxxx */
      } else {
        goto fail;
      }
      num_cc--;
    } else {
      if (c < 0x80) {
        num_cc = 0;
      } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
        /* 110x xxxx */
        num_cc = 1;
      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
        /* 1110 xxxx */
        num_cc = 2;
      } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
                 (0x80 | 0x40 | 0x20 | 0x10)) {
        /* 1111 0xxx */
        num_cc = 3;
      } else {
        goto fail;
      }
    }
  }

  if (num_cc != 0) {
    goto fail;
  }

  return true;

fail:
  return false;
}

bool avb_str_concat(char* buf, size_t buf_size, const char* str1,
                    size_t str1_len, const char* str2, size_t str2_len) {
  uint64_t combined_len;

  if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
    avb_error("Overflow when adding string sizes.\n");
    return false;
  }

  if (combined_len > buf_size - 1) {
    avb_error("Insufficient buffer space.\n");
    return false;
  }

  avb_memcpy(buf, str1, str1_len);
  avb_memcpy(buf + str1_len, str2, str2_len);
  buf[combined_len] = '\0';

  return true;
}

void* avb_malloc(size_t size) {
  void* ret = avb_malloc_(size);
  if (ret == NULL) {
    avb_error("Failed to allocate memory.\n");
    return NULL;
  }
  return ret;
}

void* avb_calloc(size_t size) {
  void* ret = avb_malloc(size);
  if (ret == NULL) {
    return NULL;
  }

  avb_memset(ret, '\0', size);
  return ret;
}

char* avb_strdup(const char* str) {
  size_t len = avb_strlen(str);
  char* ret = avb_malloc(len + 1);
  if (ret == NULL) {
    return NULL;
  }

  avb_memcpy(ret, str, len);
  ret[len] = '\0';

  return ret;
}

const char* avb_strstr(const char* haystack, const char* needle) {
  size_t n, m;

  /* Look through |haystack| and check if the first character of
   * |needle| matches. If so, check the rest of |needle|.
   */
  for (n = 0; haystack[n] != '\0'; n++) {
    if (haystack[n] != needle[0]) continue;

    for (m = 1;; m++) {
      if (needle[m] == '\0') {
        return haystack + n;
      }

      if (haystack[n + m] != needle[m]) break;
    }
  }

  return NULL;
}

char* avb_replace(const char* str, const char* search, const char* replace) {
  char* ret = NULL;
  size_t ret_len = 0;
  size_t search_len, replace_len;
  const char* str_after_last_replace;

  search_len = avb_strlen(search);
  replace_len = avb_strlen(replace);

  str_after_last_replace = str;
  while (*str != '\0') {
    const char* s;
    size_t num_before;
    size_t num_new;

    s = avb_strstr(str, search);
    if (s == NULL) break;

    num_before = s - str;

    if (ret == NULL) {
      num_new = num_before + replace_len + 1;
      ret = avb_malloc(num_new);
      if (ret == NULL) {
        goto out;
      }
      avb_memcpy(ret, str, num_before);
      avb_memcpy(ret + num_before, replace, replace_len);
      ret[num_new - 1] = '\0';
      ret_len = num_new - 1;
    } else {
      char* new_str;
      num_new = ret_len + num_before + replace_len + 1;
      new_str = avb_malloc(num_new);
      if (ret == NULL) {
        goto out;
      }
      avb_memcpy(new_str, ret, ret_len);
      avb_memcpy(new_str + ret_len, str, num_before);
      avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
      new_str[num_new - 1] = '\0';
      avb_free(ret);
      ret = new_str;
      ret_len = num_new - 1;
    }

    str = s + search_len;
    str_after_last_replace = str;
  }

  if (ret == NULL) {
    ret = avb_strdup(str_after_last_replace);
    if (ret == NULL) {
      goto out;
    }
  } else {
    size_t num_remaining = avb_strlen(str_after_last_replace);
    size_t num_new = ret_len + num_remaining + 1;
    char* new_str = avb_malloc(num_new);
    if (ret == NULL) goto out;
    avb_memcpy(new_str, ret, ret_len);
    avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
    new_str[num_new - 1] = '\0';
    avb_free(ret);
    ret = new_str;
    ret_len = num_new - 1;
  }

out:
  return ret;
}
