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);
111 memcpy((void*)destination->items, (void*)source->items, sizeof(JM_TEMPLATE_INSTANCE_TYPE)*destsize);
112 return destination->size;
115 size_t jm_vector_append(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* destination, jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* source) {
116 size_t oldsize, newsize;
117 oldsize = jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(destination);
118 newsize = jm_vector_resize(JM_TEMPLATE_INSTANCE_TYPE)(destination, source->size + oldsize);
119 memcpy((void*)(destination->items + oldsize), (void*)source->items, sizeof(JM_TEMPLATE_INSTANCE_TYPE)*(newsize - oldsize));
120 return (newsize - oldsize);
123 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) {
125 JM_TEMPLATE_INSTANCE_TYPE* pitem;
126 if(index >= a->size) return 0;
127 if(a->size == a->capacity) {
128 if(a->capacity > JM_VECTOR_MAX_MEMORY_CHUNK)
129 reserve = JM_VECTOR_MAX_MEMORY_CHUNK + a->capacity;
131 reserve = a->capacity * 2;
132 if( jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(a, reserve) != reserve) return 0;
134 assert(a->size < a->capacity);
135 memmove((void*)(a->items+index+1),(void*)(a->items+index), a->size - index);
136 a->items[index] = item;
137 pitem = &(a->items[index]);
142 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_resize1(JM_TEMPLATE_INSTANCE_TYPE) (jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * a) {
144 JM_TEMPLATE_INSTANCE_TYPE* pitem;
145 if(a->size == a->capacity) {
146 if(a->capacity > JM_VECTOR_MAX_MEMORY_CHUNK)
147 reserve = JM_VECTOR_MAX_MEMORY_CHUNK + a->capacity;
149 reserve = a->capacity * 2;
150 if( jm_vector_reserve(JM_TEMPLATE_INSTANCE_TYPE)(a, reserve) != reserve) return 0;
152 assert(a->size < a->capacity);
153 pitem = &(a->items[a->size]);
158 JM_TEMPLATE_INSTANCE_TYPE* jm_vector_push_back(JM_TEMPLATE_INSTANCE_TYPE) (jm_vector(JM_TEMPLATE_INSTANCE_TYPE) * a, JM_TEMPLATE_INSTANCE_TYPE item) {
159 JM_TEMPLATE_INSTANCE_TYPE* pitem= jm_vector_resize1(JM_TEMPLATE_INSTANCE_TYPE) (a);
165 void jm_vector_remove_item(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, size_t index) {
166 size_t n =v->size - index -1;
167 assert(index < v->size);
169 memmove((void*)&(v->items[index]),(void*) &(v->items[index+1]), n * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
174 void jm_vector_zero(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a) {
175 if(jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a) > 0) {
176 memset((void*)a->items,0,a->size * sizeof(JM_TEMPLATE_INSTANCE_TYPE));
180 void jm_vector_foreach_c(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a,
181 void (*f)(JM_TEMPLATE_INSTANCE_TYPE, void*), void * data) {
183 for(i = 0; i < jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a); i++)
184 f(jm_vector_get_item(JM_TEMPLATE_INSTANCE_TYPE)(a, i), data);
187 void jm_vector_foreach(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* a,
188 void (*f)(JM_TEMPLATE_INSTANCE_TYPE)) {
190 for(i = 0; i < jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a); i++)
191 f(jm_vector_get_item(JM_TEMPLATE_INSTANCE_TYPE)(a, i));
194 void jm_vector_qsort(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, jm_compare_ft f) {
195 if(jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v) > 1) {
196 qsort((void*)v->items, jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v), sizeof(JM_TEMPLATE_INSTANCE_TYPE),f);
200 #define jm_vector_ptr2index(T) jm_mangle(jm_vector_ptr2index, T)
202 static size_t jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(jm_vector(JM_TEMPLATE_INSTANCE_TYPE)* v, JM_TEMPLATE_INSTANCE_TYPE* itemp) {
204 return (itemp - v->items);
206 return jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v);
210 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) {
211 return jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(v, jm_vector_bsearch(JM_TEMPLATE_INSTANCE_TYPE)(v, key,f));
214 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) {
215 return bsearch(key, v->items,
216 jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(v),
217 sizeof(JM_TEMPLATE_INSTANCE_TYPE),
221 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) {
222 size_t i = jm_vector_get_size(JM_TEMPLATE_INSTANCE_TYPE)(a);
224 JM_TEMPLATE_INSTANCE_TYPE* cur = jm_vector_get_itemp(JM_TEMPLATE_INSTANCE_TYPE)(a, i);
225 if(f(cur, itemp) == 0)
231 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) {
232 return jm_vector_ptr2index(JM_TEMPLATE_INSTANCE_TYPE)(v,jm_vector_find(JM_TEMPLATE_INSTANCE_TYPE)(v, itemp, f));