project_files/frontlib/buffer.c
author Medo <smaxein@googlemail.com>
Sat, 02 Jun 2012 14:26:52 +0200
changeset 7162 fe76d24a25d7
permissions -rw-r--r--
Demo recording for the frontend library
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7162
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     1
#include "buffer.h"
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     2
#include "logging.h"
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     3
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     4
#include <stdlib.h>
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     5
#include <limits.h>
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     6
#include <string.h>
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     7
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     8
typedef struct _flib_vector {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
     9
	void *data;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    10
	size_t size;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    11
	size_t capacity;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    12
} _flib_vector;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    13
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    14
flib_vector flib_vector_create() {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    15
	flib_vector result = malloc(sizeof(_flib_vector));
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    16
	if(result == NULL) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    17
		return NULL;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    18
	}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    19
	result->data = malloc(16);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    20
	if(result->data == NULL) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    21
		free(result);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    22
		return NULL;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    23
	}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    24
	result->size = 0;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    25
	result->capacity = 16;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    26
	return result;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    27
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    28
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    29
void flib_vector_destroy(flib_vector *vec) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    30
	if(vec && *vec) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    31
		free((*vec)->data);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    32
		free(*vec);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    33
		*vec = NULL;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    34
	}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    35
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    36
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    37
static void try_realloc(flib_vector vec, size_t newCapacity) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    38
	void *newData = realloc(vec->data, newCapacity);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    39
	if(newData) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    40
		vec->data = newData;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    41
		vec->capacity = newCapacity;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    42
	}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    43
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    44
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    45
static size_t getFreeCapacity(flib_vector vec) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    46
	return vec->capacity - vec->size;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    47
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    48
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    49
int flib_vector_append(flib_vector vec, const void *data, size_t len) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    50
	if(getFreeCapacity(vec) < len) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    51
		// Resize exponentially for constant amortized time,
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    52
		// But at least by as much as we need of course,
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    53
		// and be extra careful with integer overflows...
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    54
		size_t extraCapacity = (vec->capacity)/2;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    55
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    56
		size_t minExtraCapacity = len - getFreeCapacity(vec);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    57
		if(extraCapacity < minExtraCapacity) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    58
			extraCapacity = minExtraCapacity;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    59
		}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    60
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    61
		if(extraCapacity <= SIZE_MAX - vec->capacity) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    62
			try_realloc(vec, vec->capacity+extraCapacity);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    63
		}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    64
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    65
		// Check if we were able to resize.
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    66
		// If not, try to allocate at least what we need...
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    67
		if(getFreeCapacity(vec) < len) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    68
			try_realloc(vec, vec->capacity+minExtraCapacity);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    69
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    70
			// Still not working? Then we fail.
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    71
			if(getFreeCapacity(vec) < len) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    72
				return 0;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    73
			}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    74
		}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    75
	}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    76
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    77
	memmove(vec->data + vec->size, data, len);
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    78
	vec->size += len;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    79
	return len;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    80
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    81
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    82
flib_buffer flib_vector_as_buffer(flib_vector vec) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    83
	flib_buffer result = {vec->data, vec->size};
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    84
	return result;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    85
}
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    86
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    87
flib_constbuffer flib_vector_as_constbuffer(flib_vector vec) {
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    88
	flib_constbuffer result = {vec->data, vec->size};
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    89
	return result;
fe76d24a25d7 Demo recording for the frontend library
Medo <smaxein@googlemail.com>
parents:
diff changeset
    90
}