Squashed 'third_party/rawrtc/rawrtc/' content from commit aa3ae4b24
Change-Id: I38a655a4259b62f591334e90a1315bd4e7e4d8ec
git-subtree-dir: third_party/rawrtc/rawrtc
git-subtree-split: aa3ae4b247275cc6e69c30613b3a4ba7fdc82d1b
diff --git a/src/utils/utils.c b/src/utils/utils.c
new file mode 100644
index 0000000..26af2a9
--- /dev/null
+++ b/src/utils/utils.c
@@ -0,0 +1,163 @@
+#include "utils.h"
+#include <rawrtc/utils.h>
+#include <rawrtcc/code.h>
+#include <re.h>
+#include <stdarg.h> // va_*
+#include <stdio.h> // sprintf
+#include <string.h> // strlen
+
+/*
+ * Convert binary to hex string where each value is separated by a
+ * colon.
+ */
+enum rawrtc_code rawrtc_bin_to_colon_hex(
+ char** const destinationp, // de-referenced
+ uint8_t* const source,
+ size_t const length) {
+ char* hex_str;
+ char* hex_ptr;
+ size_t i;
+ int ret;
+ enum rawrtc_code error = RAWRTC_CODE_SUCCESS;
+
+ // Check arguments
+ if (!destinationp || !source) {
+ return RAWRTC_CODE_INVALID_ARGUMENT;
+ }
+
+ // Allocate hex string
+ hex_str = mem_zalloc(length > 0 ? (length * 3) : 1, NULL);
+ if (!hex_str) {
+ return RAWRTC_CODE_NO_MEMORY;
+ }
+
+ // Bin to hex
+ hex_ptr = hex_str;
+ for (i = 0; i < length; ++i) {
+ if (i > 0) {
+ *hex_ptr = ':';
+ ++hex_ptr;
+ }
+ ret = sprintf(hex_ptr, "%02X", source[i]);
+ if (ret != 2) {
+ error = RAWRTC_CODE_UNKNOWN_ERROR;
+ goto out;
+ } else {
+ hex_ptr += ret;
+ }
+ }
+
+out:
+ if (error) {
+ mem_deref(hex_str);
+ } else {
+ // Set pointer
+ *destinationp = hex_str;
+ }
+ return error;
+}
+
+/*
+ * Convert hex string with colon-separated hex values to binary.
+ */
+enum rawrtc_code rawrtc_colon_hex_to_bin(
+ size_t* const bytes_written, // de-referenced
+ uint8_t* const buffer, // written into
+ size_t const buffer_size,
+ char* source) {
+ size_t hex_length;
+ size_t bin_length;
+ size_t i;
+
+ // Check arguments
+ if (!bytes_written || !buffer || !source) {
+ return RAWRTC_CODE_INVALID_ARGUMENT;
+ }
+
+ // Validate length
+ hex_length = strlen(source);
+ if (hex_length > 0 && hex_length % 3 != 2) {
+ return RAWRTC_CODE_INVALID_ARGUMENT;
+ }
+
+ // Determine size
+ bin_length = hex_length > 0 ? (size_t)((hex_length + 1) / 3) : 0;
+ if (bin_length > buffer_size) {
+ return RAWRTC_CODE_INSUFFICIENT_SPACE;
+ }
+
+ // Hex to bin
+ for (i = 0; i < bin_length; ++i) {
+ if (i > 0) {
+ // Skip colon
+ ++source;
+ }
+ buffer[i] = ch_hex(*source) << 4;
+ ++source;
+ buffer[i] += ch_hex(*source);
+ ++source;
+ }
+
+ // Done
+ *bytes_written = bin_length;
+ return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Destructor for an existing array container that did reference each
+ * item.
+ */
+static void rawrtc_array_container_destroy(void* arg) {
+ struct rawrtc_array_container* const container = arg;
+ size_t i;
+
+ // Un-reference each item
+ for (i = 0; i < container->n_items; ++i) {
+ mem_deref(container->items[i]);
+ }
+}
+
+/*
+ * Convert a list to a dynamically allocated array container.
+ *
+ * If `reference` is set to `true`, each item in the list will be
+ * referenced and a destructor will be added that unreferences each
+ * item when unreferencing the array.
+ */
+enum rawrtc_code rawrtc_list_to_array(
+ struct rawrtc_array_container** containerp, // de-referenced
+ struct list const* const list,
+ bool reference) {
+ size_t n;
+ struct rawrtc_array_container* container;
+ struct le* le;
+ size_t i;
+
+ // Check arguments
+ if (!containerp || !list) {
+ return RAWRTC_CODE_INVALID_ARGUMENT;
+ }
+
+ // Get list length
+ n = list_count(list);
+
+ // Allocate array & set length immediately
+ container = mem_zalloc(
+ sizeof(*container) + sizeof(void*) * n, reference ? rawrtc_array_container_destroy : NULL);
+ if (!container) {
+ return RAWRTC_CODE_NO_MEMORY;
+ }
+ container->n_items = n;
+
+ // Copy pointer to each item
+ for (le = list_head(list), i = 0; le != NULL; le = le->next, ++i) {
+ if (reference) {
+ mem_ref(le->data);
+ }
+ container->items[i] = le->data;
+ }
+
+ // Set pointer & done
+ *containerp = container;
+ return RAWRTC_CODE_SUCCESS;
+}