1 #include "buffer.h" |
1 #include "buffer.h" |
2 #include "logging.h" |
2 #include "logging.h" |
|
3 #include "util.h" |
3 |
4 |
4 #include <stdlib.h> |
5 #include <stdlib.h> |
5 #include <limits.h> |
6 #include <limits.h> |
6 #include <string.h> |
7 #include <string.h> |
|
8 |
|
9 #define MIN_VECTOR_CAPACITY 16 |
7 |
10 |
8 typedef struct _flib_vector { |
11 typedef struct _flib_vector { |
9 void *data; |
12 void *data; |
10 size_t size; |
13 size_t size; |
11 size_t capacity; |
14 size_t capacity; |
12 } _flib_vector; |
15 } _flib_vector; |
13 |
16 |
14 flib_vector flib_vector_create() { |
17 flib_vector *flib_vector_create() { |
15 flib_vector result = malloc(sizeof(_flib_vector)); |
18 flib_vector *result = NULL; |
16 if(result == NULL) { |
19 flib_vector *tmpVector = flib_calloc(1, sizeof(_flib_vector)); |
17 return NULL; |
20 if(tmpVector) { |
|
21 tmpVector->data = flib_malloc(MIN_VECTOR_CAPACITY); |
|
22 if(tmpVector->data) { |
|
23 tmpVector->size = 0; |
|
24 tmpVector->capacity = MIN_VECTOR_CAPACITY; |
|
25 result = tmpVector; |
|
26 tmpVector = NULL; |
|
27 } |
18 } |
28 } |
19 result->data = malloc(16); |
29 flib_vector_destroy(tmpVector); |
20 if(result->data == NULL) { |
|
21 free(result); |
|
22 return NULL; |
|
23 } |
|
24 result->size = 0; |
|
25 result->capacity = 16; |
|
26 return result; |
30 return result; |
27 } |
31 } |
28 |
32 |
29 void flib_vector_destroy(flib_vector *vec) { |
33 void flib_vector_destroy(flib_vector *vec) { |
30 if(vec && *vec) { |
34 if(vec) { |
31 free((*vec)->data); |
35 free(vec->data); |
32 free(*vec); |
36 free(vec); |
33 *vec = NULL; |
|
34 } |
37 } |
35 } |
38 } |
36 |
39 |
37 static void try_realloc(flib_vector vec, size_t newCapacity) { |
40 static void try_realloc(flib_vector *vec, size_t newCapacity) { |
38 void *newData = realloc(vec->data, newCapacity); |
41 void *newData = realloc(vec->data, newCapacity); |
39 if(newData) { |
42 if(newData) { |
40 vec->data = newData; |
43 vec->data = newData; |
41 vec->capacity = newCapacity; |
44 vec->capacity = newCapacity; |
42 } |
45 } |
43 } |
46 } |
44 |
47 |
45 static size_t getFreeCapacity(flib_vector vec) { |
48 static size_t getFreeCapacity(flib_vector *vec) { |
46 return vec->capacity - vec->size; |
49 return vec->capacity - vec->size; |
47 } |
50 } |
48 |
51 |
49 int flib_vector_append(flib_vector vec, const void *data, size_t len) { |
52 int flib_vector_append(flib_vector *vec, const void *data, size_t len) { |
|
53 if(!vec) { |
|
54 flib_log_e("null parameter in flib_vector_append"); |
|
55 return 0; |
|
56 } |
|
57 |
50 if(getFreeCapacity(vec) < len) { |
58 if(getFreeCapacity(vec) < len) { |
51 // Resize exponentially for constant amortized time, |
59 // Resize exponentially for constant amortized time, |
52 // But at least by as much as we need of course, |
60 // But at least by as much as we need of course, |
53 // and be extra careful with integer overflows... |
61 // and be extra careful with integer overflows... |
54 size_t extraCapacity = (vec->capacity)/2; |
62 size_t extraCapacity = (vec->capacity)/2; |
61 if(extraCapacity <= SIZE_MAX - vec->capacity) { |
69 if(extraCapacity <= SIZE_MAX - vec->capacity) { |
62 try_realloc(vec, vec->capacity+extraCapacity); |
70 try_realloc(vec, vec->capacity+extraCapacity); |
63 } |
71 } |
64 |
72 |
65 // Check if we were able to resize. |
73 // Check if we were able to resize. |
66 // If not, try to allocate at least what we need... |
74 // If not, try to allocate at least what we need. |
67 if(getFreeCapacity(vec) < len) { |
75 if(getFreeCapacity(vec) < len) { |
68 try_realloc(vec, vec->capacity+minExtraCapacity); |
76 try_realloc(vec, vec->capacity+minExtraCapacity); |
69 |
77 |
70 // Still not working? Then we fail. |
78 // Still not working? Then we fail. |
71 if(getFreeCapacity(vec) < len) { |
79 if(getFreeCapacity(vec) < len) { |
72 return 0; |
80 return 0; |
73 } |
81 } |
74 } |
82 } |
75 } |
83 } |
76 |
84 |
77 memmove(vec->data + vec->size, data, len); |
85 memmove(((uint8_t*)vec->data) + vec->size, data, len); |
78 vec->size += len; |
86 vec->size += len; |
79 return len; |
87 return len; |
80 } |
88 } |
81 |
89 |
82 flib_buffer flib_vector_as_buffer(flib_vector vec) { |
90 flib_buffer flib_vector_as_buffer(flib_vector *vec) { |
83 flib_buffer result = {vec->data, vec->size}; |
91 if(!vec) { |
84 return result; |
92 flib_log_e("null parameter in flib_vector_as_buffer"); |
|
93 flib_buffer result = {NULL, 0}; |
|
94 return result; |
|
95 } else { |
|
96 flib_buffer result = {vec->data, vec->size}; |
|
97 return result; |
|
98 } |
85 } |
99 } |
86 |
100 |
87 flib_constbuffer flib_vector_as_constbuffer(flib_vector vec) { |
101 flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) { |
88 flib_constbuffer result = {vec->data, vec->size}; |
102 if(!vec) { |
89 return result; |
103 flib_log_e("null parameter in flib_vector_as_constbuffer"); |
|
104 flib_constbuffer result = {NULL, 0}; |
|
105 return result; |
|
106 } else { |
|
107 flib_constbuffer result = {vec->data, vec->size}; |
|
108 return result; |
|
109 } |
90 } |
110 } |
|
111 |
|
112 void *flib_vector_data(flib_vector *vec) { |
|
113 if(!vec) { |
|
114 flib_log_e("null parameter in flib_vector_data"); |
|
115 return NULL; |
|
116 } else { |
|
117 return vec->data; |
|
118 } |
|
119 } |
|
120 |
|
121 size_t flib_vector_size(flib_vector *vec) { |
|
122 if(!vec) { |
|
123 flib_log_e("null parameter in flib_vector_size"); |
|
124 return 0; |
|
125 } else { |
|
126 return vec->size; |
|
127 } |
|
128 } |