author | Medo <smaxein@googlemail.com> |
Sat, 09 Jun 2012 03:28:38 +0200 | |
changeset 7179 | f84805e6df03 |
parent 7162 | project_files/frontlib/buffer.c@fe76d24a25d7 |
child 7224 | 5143861c83bd |
permissions | -rw-r--r-- |
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 |
} |