2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 FMILIB_License.txt file for more details.
12 You should have received a copy of the FMILIB_License.txt file
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
17 * \file jm_vector_template.h
18 * \brief Vector template definition.
20 * This file is supposed to be included into a C-file that instantiate the template.
21 * jm_vector.h must be included before this file.
22 * It expects JM_TEMPLATE_INSTANCE_TYPE to be defined to the template type to be instantiated.
27 #include "jm_vector.h"
29 /** \addtogroup jm_vector A vector of items (dynamic array)*/
33 #ifndef JM_TEMPLATE_INSTANCE_TYPE
34 #error "JM_TEMPLATE_INSTANCE_TYPE must be defined before including this file"
37 jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * jm_vector_alloc(JM_TEMPLATE_INSTANCE_TYPE) (size_t size, size_t capacity, jm_callbacks* c) {
40 jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * v;
44 cc = jm_get_default_callbacks();
47 if(reserve < size) reserve = size;
48 if(reserve > JM_VECTOR_MINIMAL_CAPACITY) {
49 v = (jm_vector(JM_TEMPLATE_INSTANCE_TYPE)*)cc->malloc(
50 sizeof(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)) +
51 sizeof(JM_TEMPLATE_INSTANCE_TYPE) * (reserve -JM_VECTOR_MINIMAL_CAPACITY));
53 v->capacity = reserve;
56 v = (jm_vector(JM_TEMPLATE_INSTANCE_TYPE)*)cc->malloc(sizeof(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)));
58 v->capacity = JM_VECTOR_MINIMAL_CAPACITY;
61 v->items = &(v->preallocated[0]);
66 void jm_vector_free(JM_TEMPLATE_INSTANCE_TYPE) (jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * a) {
68 jm_vector_free_data(JM_TEMPLATE_INSTANCE_TYPE)(a);
69 a->callbacks->free(a);
72 size_t jm_vector_init(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a, size_t initSize, jm_callbacks* c) {
76 a->callbacks = jm_get_default_callbacks();
77 a->items = a->preallocated;
79 a->capacity = JM_VECTOR_MINIMAL_CAPACITY;
81 if(initSize > a->size)
82 return jm_vector_resize(JM_TEMPLATE_INSTANCE_TYPE)(a, initSize);
86 size_t jm_vector_resize(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a, size_t size) {
87 if(size > a->capacity) {
88 if(jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(a, size) < size) {
89 a->size = a->capacity;
97 size_t jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a, size_t size) {
99 if(size <= a->capacity) return a->capacity;
100 newmem = a->callbacks->malloc(size * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
101 if(!newmem) return a->capacity;
102 memcpy(newmem, a->items, a->size * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
103 if(a->items != a->preallocated) a->callbacks->free((void*)(a->items));
109 size_t jm_vector_copy(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* destination, jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* source) {
110 size_t destsize = jm_vector_resize(JM_TEMPLATE_INSTANCE_TYPE)(destination, source->size);
112 memcpy((void*)destination->items, (void*)source->items, sizeof(JM_TEMPLATE_INSTANCE_TYPE)*destsize);
114 return destination->size;
117 size_t jm_vector_append(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* destination, jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* source) {
118 size_t oldsize, newsize;
119 oldsize = jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(destination);
120 newsize = jm_vector_resize(JM_TEMPLATE_INSTANCE_TYPE)(destination, source->size + oldsize);
121 memcpy((void*)(destination->items + oldsize), (void*)source->items, sizeof(JM_TEMPLATE_INSTANCE_TYPE)*(newsize - oldsize));
122 return (newsize - oldsize);
125 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_insert(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a, size_t index, JM_TEMPLATE_INSTANCE_TYPE item) {
127 JM_TEMPLATE_INSTANCE_TYPE* pitem;
128 if(index >= a->size) return 0;
129 if(a->size == a->capacity) {
130 if(a->capacity > JM_VECTOR_MAX_MEMORY_CHUNK)
131 reserve = JM_VECTOR_MAX_MEMORY_CHUNK + a->capacity;
133 reserve = a->capacity * 2;
134 if( jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(a, reserve) != reserve) return 0;
136 assert(a->size < a->capacity);
137 memmove((void*)(a->items+index+1),(void*)(a->items+index), (a->size - index)*sizeof(JM_TEMPLATE_INSTANCE_TYPE));
138 a->items[index] = item;
139 pitem = &(a->items[index]);
144 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_resize1(JM_TEMPLATE_INSTANCE_TYPE) (jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * a) {
146 JM_TEMPLATE_INSTANCE_TYPE* pitem;
147 if(a->size == a->capacity) {
148 if(a->capacity > JM_VECTOR_MAX_MEMORY_CHUNK)
149 reserve = JM_VECTOR_MAX_MEMORY_CHUNK + a->capacity;
151 reserve = a->capacity * 2;
152 if( jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(a, reserve) != reserve) return 0;
154 assert(a->size < a->capacity);
155 pitem = &(a->items[a->size]);
160 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_push_back(JM_TEMPLATE_INSTANCE_TYPE) (jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * a, JM_TEMPLATE_INSTANCE_TYPE item) {
161 JM_TEMPLATE_INSTANCE_TYPE* pitem= jm_vector_resize1(JM_TEMPLATE_INSTANCE_TYPE) (a);
167 void jm_vector_remove_item(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, size_t index) {
168 size_t n =v->size - index -1;
169 assert(index < v->size);
171 memmove((void*)&(v->items[index]),(void*) &(v->items[index+1]), n * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
176 void jm_vector_zero(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a) {
177 if(jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a) > 0) {
178 memset((void*)a->items,0,a->size * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
182 void jm_vector_foreach_c(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a,
183 void (*f)(JM_TEMPLATE_INSTANCE_TYPE, void*), void * data) {
185 for(i = 0; i < jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a); i++)
186 f(jm_vector_get_item(JM_TEMPLATE_INSTANCE_TYPE)(a, i), data);
189 void jm_vector_foreach(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a,
190 void (*f)(JM_TEMPLATE_INSTANCE_TYPE)) {
192 for(i = 0; i < jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a); i++)
193 f(jm_vector_get_item(JM_TEMPLATE_INSTANCE_TYPE)(a, i));
196 void jm_vector_qsort(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, jm_compare_ft f) {
197 if(jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v) > 1) {
198 qsort((void*)v->items, jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v), sizeof(JM_TEMPLATE_INSTANCE_TYPE),f);
202 #define jm_vector_ptr2index(T) jm_mangle(jm_vector_ptr2index, T)
204 static size_t jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, JM_TEMPLATE_INSTANCE_TYPE* itemp) {
206 return (itemp - v->items);
208 return jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v);
212 size_t jm_vector_bsearch_index(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, JM_TEMPLATE_INSTANCE_TYPE* key, jm_compare_ft f) {
213 return jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(v, jm_vector_bsearch(JM_TEMPLATE_INSTANCE_TYPE)(v, key,f));
216 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_bsearch(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, JM_TEMPLATE_INSTANCE_TYPE* key, jm_compare_ft f) {
217 return bsearch(key, v->items,
218 jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v),
219 sizeof(JM_TEMPLATE_INSTANCE_TYPE),
223 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_find(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a, JM_TEMPLATE_INSTANCE_TYPE* itemp, jm_compare_ft f) {
224 size_t i = jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a);
226 JM_TEMPLATE_INSTANCE_TYPE* cur = jm_vector_get_itemp(JM_TEMPLATE_INSTANCE_TYPE)(a, i);
227 if(f(cur, itemp) == 0)
233 size_t jm_vector_find_index(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, JM_TEMPLATE_INSTANCE_TYPE* itemp, jm_compare_ft f) {
234 return jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(v,jm_vector_find(JM_TEMPLATE_INSTANCE_TYPE)(v, itemp, f));