161 lines
4.4 KiB
C
161 lines
4.4 KiB
C
/// dynamic array class
|
|
/// written by: Harry Irving
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
typedef enum LineState {
|
|
UNMODIFIED,
|
|
MODIFIED,
|
|
ADDED,
|
|
REMOVED,
|
|
} LineState;
|
|
|
|
typedef struct {
|
|
uint32_t size; // Current number of elements
|
|
uint32_t capacity; // Total capacity allocated
|
|
LineState* data; // Array of LineState values
|
|
} StateArray;
|
|
|
|
StateArray arr_init(int capacity) {
|
|
// creates a new array to store the state
|
|
StateArray arr;
|
|
arr.size = capacity;
|
|
arr.capacity = capacity;
|
|
arr.data = (LineState*)calloc(capacity, sizeof(LineState));
|
|
// Initialize all elements to UNMODIFIED
|
|
for (int i = 0; i < capacity; i++) {
|
|
arr.data[i] = UNMODIFIED;
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
// prints the state of the array into a file
|
|
// this method is for debug purposes!
|
|
// void arr_print(StateArray* self) {
|
|
// FILE* log_file = fopen("diff.txt", "w");
|
|
// if (log_file == NULL) {
|
|
// fprintf(stderr, "Error: Could not open log file\n");
|
|
// }
|
|
|
|
// for (int i = 0; i < self->size; i++) {
|
|
// switch (self->data[i]) {
|
|
// case UNMODIFIED:
|
|
// fwrite("UNMODIFIED\n", sizeof(char), strlen("UNMODIFIED\n"), log_file);
|
|
// break;
|
|
// case MODIFIED:
|
|
// fwrite("MODIFIED\n", sizeof(char), strlen("MODIFIED\n"), log_file);
|
|
// break;
|
|
// case ADDED:
|
|
// fwrite("ADDED\n", sizeof(char), strlen("ADDED\n"), log_file);
|
|
// break;
|
|
// case REMOVED:
|
|
// fwrite("REMOVED\n", sizeof(char), strlen("REMOVED\n"), log_file);
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// fclose(log_file);
|
|
// }
|
|
|
|
// calculates an offset to use for indexing into the state relative to the buffer.
|
|
// this is because some elements might not be aligned due to needing to insert the "REMOVED" element in some cases.
|
|
int arr_added_or_removed_before(StateArray* self, int index) {
|
|
int count = 0;
|
|
for (int i = 0; i < index; i++) {
|
|
// if (self->data[i] == ADDED || self->data[i] == REMOVED) {
|
|
// if (self->data[i] == REMOVED) {
|
|
// // every time a "REMOVED" element is found, we increase the index by 1
|
|
// index++;
|
|
// }
|
|
// count++;
|
|
// }
|
|
if (self->data[i] == REMOVED) {
|
|
// every time a "REMOVED" element is found, we increase the index by 1
|
|
index++;
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
void arr_set(StateArray* self, int index, LineState state) {
|
|
int offset = arr_added_or_removed_before(self, index);
|
|
self->data[index] = state;
|
|
}
|
|
|
|
LineState arr_remove(StateArray* self, int index) {
|
|
int offset = arr_added_or_removed_before(self, index);
|
|
|
|
if (index >= self->size) {
|
|
return -1;
|
|
}
|
|
|
|
LineState removed = self->data[index];
|
|
|
|
// Shift remaining elements left
|
|
for (int i = index; i < self->size - 1; i++) {
|
|
self->data[i] = self->data[i + 1];
|
|
}
|
|
self->size--;
|
|
|
|
return removed;
|
|
}
|
|
|
|
int arr_insert(StateArray* self, int index, LineState state) {
|
|
int offset = arr_added_or_removed_before(self, index);
|
|
|
|
if (index > self->size) {
|
|
return -1;
|
|
}
|
|
self->size++;
|
|
|
|
// Grow array if needed
|
|
if (self->size > self->capacity) {
|
|
self->capacity = (self->size) * sizeof(LineState);
|
|
self->data = (LineState*)realloc(self->data, self->capacity * sizeof(LineState));
|
|
}
|
|
|
|
// Shift elements right to make room
|
|
for (int i = self->size - 1; i > index; i--) {
|
|
self->data[i] = self->data[i - 1];
|
|
}
|
|
self->data[index] = state;
|
|
return 0;
|
|
}
|
|
|
|
LineState arr_get(StateArray* self, int index) {
|
|
int offset = arr_added_or_removed_before(self, index);
|
|
return self->data[index];
|
|
}
|
|
|
|
int arr_original_offset(StateArray* self, int index) {
|
|
int offset = 0;
|
|
for (int i = 0; i < index; i++) {
|
|
if (self->data[i] == ADDED) {
|
|
offset--;
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
int arr_modified_offset(StateArray* self, int index) {
|
|
int offset = 0;
|
|
for (int i = 0; i < index; i++) {
|
|
if (self->data[i] == REMOVED) {
|
|
offset--;
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
int arr_dealloc(StateArray* self) {
|
|
free(self->data);
|
|
self->data = NULL;
|
|
self->size = 0;
|
|
self->capacity = 0;
|
|
return 0;
|
|
} |