#include #include #include #include #include #include #include "circ_buff.h" // Defines the circular buffer structure struct circ_buf_t { char **buffer; size_t head; size_t tail; size_t max; // of the buffer size_t el_size; bool full; }; // Private Functions unit_static void advance_pointer(cbuf_handle_t cbuf) { assert(cbuf); if(cbuf->full) { cbuf->tail = (cbuf->tail + 1) % cbuf->max; } cbuf->head = (cbuf->head + 1) % cbuf->max; // We mark full because we will advance tail on the next time around cbuf->full = (cbuf->head == cbuf->tail); } unit_static void retreat_pointer(cbuf_handle_t cbuf) { assert(cbuf); cbuf->full = false; cbuf->tail = (cbuf->tail + 1) % cbuf->max; } // Compares the buffers cbuf1 and cbuf2. Elements present on cbuf1 that do not // exist on cbuf2 are added to the array add2, elements present on cbuf2 that do // not exist on cbuf1 are added to the array add1. // Both buffers must be ordered on the same way! unit_static void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, char ***add1, char ***add2) { assert(cbuf1 && cbuf2 && (circ_buf_element_size(cbuf1) == circ_buf_element_size(cbuf2)) && (circ_buf_capacity(cbuf1) == circ_buf_capacity(cbuf2))); // Initializes the diff arrays (*add1) = (char **) malloc(circ_buf_capacity(cbuf2) * sizeof(char *)); (*add2) = (char **) malloc(circ_buf_capacity(cbuf1) * sizeof(char *)); char *curr_str1 = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); char *curr_str2 = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); /*uint8_t diff_array_index = 0; for (uint8_t i = 0; i < circ_buf_size(cbuf1); ++i) { // Reads current element of cbuf1 circ_buf_read(cbuf1, i, curr_str1); bool element_exists = false; for (uint8_t j = 0; j < circ_buf_size(cbuf2); ++j) { circ_buf_read(cbuf2, j, curr_str2); // Checks against cbuf2 elements if (!strcmp(curr_str2, curr_str1)) { element_exists = true; break; } } if (!element_exists) { (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); strcpy((*add2)[diff_array_index], curr_str1); ++diff_array_index; } } (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); strcpy((*add1)[diff_array_index], EOB); diff_array_index = 0; for (uint8_t i = 0; i < circ_buf_size(cbuf2); ++i) { // Reads current element of cbuf2 circ_buf_read(cbuf2, i, curr_str2); bool element_exists = false; for (uint8_t j = 0; j < circ_buf_size(cbuf1); ++j) { circ_buf_read(cbuf1, j, curr_str1); // Checks against cbuf1 elements if (!strcmp(curr_str1, curr_str2)) { element_exists = true; break; } } if (!element_exists) { (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); strcpy((*add1)[diff_array_index], curr_str2); ++diff_array_index; } } (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); strcpy((*add2)[diff_array_index], EOB);*/ uint8_t cbuf1_idx = 0, cbuf2_idx = 0, add1_arr_idx = 0, add2_arr_idx = 0; while ((cbuf1_idx < circ_buf_size(cbuf1)) && (cbuf2_idx < circ_buf_size(cbuf2))) { circ_buf_read(cbuf1, cbuf1_idx, curr_str1); circ_buf_read(cbuf2, cbuf2_idx, curr_str2); int strcmp_res = strcmp(curr_str1, curr_str2); if (!strcmp_res) { ++cbuf1_idx; ++cbuf2_idx; } else { // TODO: change the inner comparisons (strtok etc) if (strcmp_res < 0) { (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); strcpy((*add2)[add2_arr_idx], curr_str1); ++add2_arr_idx; ++cbuf1_idx; } else if (strcmp_res > 0) { (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); strcpy((*add1)[add1_arr_idx], curr_str2); ++add1_arr_idx; ++cbuf2_idx; } } } while (cbuf1_idx < circ_buf_size(cbuf1)) { (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); circ_buf_read(cbuf1, cbuf1_idx, curr_str1); strcpy((*add2)[add2_arr_idx], curr_str1); ++add2_arr_idx; ++cbuf1_idx; } while (cbuf2_idx < circ_buf_size(cbuf2)) { (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); circ_buf_read(cbuf2, cbuf2_idx, curr_str2); strcpy((*add1)[add1_arr_idx], curr_str2); ++add1_arr_idx; ++cbuf2_idx; } (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); strcpy((*add1)[add1_arr_idx], EOB); (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); strcpy((*add2)[add2_arr_idx], EOB); free(curr_str1); free(curr_str2); /*uint8_t i = 0; printf("add1:\n"); while (strcmp((*add1)[i], EOB)) { printf("%s\n", (*add1)[i]); ++i; } i = 0; printf("add2:\n"); while (strcmp((*add2)[i], EOB)) { printf("%s\n", (*add2)[i]); ++i; }*/ } // APIs cbuf_handle_t circ_buf_init(char **buffer, size_t size, size_t element_size) { assert(buffer && size); cbuf_handle_t cbuf = malloc(sizeof(circ_buf_t)); assert(cbuf); cbuf->buffer = buffer; cbuf->max = size; cbuf->el_size = element_size; circ_buf_reset(cbuf); assert(circ_buf_empty(cbuf)); return cbuf; } void circ_buf_free(cbuf_handle_t cbuf) { assert(cbuf); free(cbuf); } void circ_buf_reset(cbuf_handle_t cbuf) { assert(cbuf); cbuf->head = 0; cbuf->tail = 0; cbuf->full = false; } size_t circ_buf_size(cbuf_handle_t cbuf) { assert(cbuf); size_t size = cbuf->max; if(!cbuf->full) { if(cbuf->head >= cbuf->tail) { size = (cbuf->head - cbuf->tail); } else { size = (cbuf->max + cbuf->head - cbuf->tail); } } return size; } size_t circ_buf_capacity(cbuf_handle_t cbuf) { assert(cbuf); return cbuf->max; } void circ_buf_put(cbuf_handle_t cbuf, const char *data) { assert(cbuf && cbuf->buffer); strcpy(cbuf->buffer[cbuf->head], data); advance_pointer(cbuf); } void circ_buf_mul_add(cbuf_handle_t cbuf, char **data, uint8_t size, int (*compar)(const void *, const void *)) { assert(cbuf && data && cbuf->buffer); qsort(data, size, sizeof(char*), compar); char *last_element = (char*) malloc(circ_buf_element_size(cbuf) * sizeof(char)); for (uint8_t i = 0; i < size; ++i) { circ_buf_read(cbuf, 0, last_element); if (compar(&data[i], &last_element) < 0) { continue; } circ_buf_put(cbuf, data[i]); } free(last_element); int end_buffer_size = circ_buf_size(cbuf); char **temp_array = (char **) malloc(end_buffer_size * sizeof(char *)); for (uint8_t buff_el = 0; buff_el < end_buffer_size; ++buff_el) { temp_array[buff_el] = (char *) malloc(circ_buf_element_size(cbuf) * sizeof(char)); circ_buf_get(cbuf, temp_array[buff_el]); } qsort(temp_array, end_buffer_size, sizeof(char*), compar); for (uint8_t i = 0; i < end_buffer_size; ++i) { circ_buf_put(cbuf, temp_array[i]); } for (uint8_t buff_el = 0; buff_el < end_buffer_size; ++buff_el) { free(temp_array[buff_el]); } free(temp_array); } int circ_buf_get(cbuf_handle_t cbuf, char *data) { assert(cbuf && data && cbuf->buffer); int r = -1; if(!circ_buf_empty(cbuf)) { strcpy(data, cbuf->buffer[cbuf->tail]); retreat_pointer(cbuf); r = 0; } return r; } int circ_buf_read(cbuf_handle_t cbuf, size_t position, char *data) { assert(cbuf && data && cbuf->buffer && (position < circ_buf_size(cbuf))); int r = -1; if(!circ_buf_empty(cbuf)) { strcpy(data, cbuf->buffer[(cbuf->tail + position) % cbuf->max]); r = 0; } return r; } int circ_buf_serialize(cbuf_handle_t cbuf, char **serialized) { char *temp = (char*) malloc(circ_buf_element_size(cbuf) * sizeof(char)); const char separator[2] = "\r"; uint8_t char_sum = circ_buf_size(cbuf) - 1; uint8_t i; for (i = 0; i < circ_buf_size(cbuf); ++i) { circ_buf_read(cbuf, i, temp); char_sum += strlen(temp); } (*serialized) = (char*) malloc((char_sum + 1) * sizeof(char)); strcpy((*serialized), ""); for (i = 0; i < circ_buf_size(cbuf) - 1; ++i) { circ_buf_read(cbuf, i, temp); strcat((*serialized), temp); strcat((*serialized), separator); } circ_buf_read(cbuf, i, temp); strcat((*serialized), temp); free(temp); return strlen((*serialized)); } int circ_buf_deserialize(cbuf_handle_t cbuf, const char *serialized) { char *str = calloc(strlen(serialized) + 1, sizeof(char)); strcpy(str, serialized); const char separator[2] = "\r"; char *token; token = strtok(str, separator); while (token != NULL) { circ_buf_put(cbuf, token); token = strtok(NULL, separator); } return circ_buf_size(cbuf); } bool circ_buf_empty(cbuf_handle_t cbuf) { assert(cbuf); return (!cbuf->full && (cbuf->head == cbuf->tail)); } bool circ_buf_full(cbuf_handle_t cbuf) { assert(cbuf); return cbuf->full; } size_t circ_buf_element_size(cbuf_handle_t cbuf) { assert(cbuf); return cbuf->el_size; }