254
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1
|
/*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
2
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
3
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
4
|
* Copyright 2019 Mike Becker, Olaf Wintermann All rights reserved.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
5
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
6
|
* Redistribution and use in source and binary forms, with or without
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
7
|
* modification, are permitted provided that the following conditions are met:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
8
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
9
|
* 1. Redistributions of source code must retain the above copyright
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
10
|
* notice, this list of conditions and the following disclaimer.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
11
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
12
|
* 2. Redistributions in binary form must reproduce the above copyright
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
13
|
* notice, this list of conditions and the following disclaimer in the
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
14
|
* documentation and/or other materials provided with the distribution.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
15
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
16
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
17
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
18
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
19
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
20
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
21
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
22
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
23
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
24
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
25
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
26
|
* POSSIBILITY OF SUCH DAMAGE.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
27
|
*/
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
28
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
29
|
#define _GNU_SOURCE /* we want to use qsort_r(), if available */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
30
|
#define __STDC_WANT_LIB_EXT1__ 1 /* use qsort_s, if available */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
31
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
32
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
33
|
#include "ucx/array.h"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
34
|
#include "ucx/utils.h"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
35
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
36
|
#include <string.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
37
|
#include <stdlib.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
38
|
#include <errno.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
39
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
40
|
#ifndef UCX_ARRAY_DISABLE_QSORT
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
41
|
#ifdef __GLIBC__
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
42
|
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
43
|
#define ucx_array_sort_impl qsort_r
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
44
|
#endif /* glibc version >= 2.8 */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
45
|
#elif /* not __GLIBC__ */ defined(__APPLE__) || defined(__FreeBSD__)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
46
|
#define ucx_array_sort_impl ucx_qsort_r
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
47
|
#define USE_UCX_QSORT_R
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
48
|
#elif /* not (__APPLE || __FreeBSD__) */ defined(__sun)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
49
|
#if __STDC_VERSION__ >= 201112L
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
50
|
#define ucx_array_sort_impl qsort_s
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
51
|
#endif
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
52
|
#endif /* __GLIBC__, __APLE__, __FreeBSD__, __sun */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
53
|
#endif /* UCX_ARRAY_DISABLE_QSORT */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
54
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
55
|
#ifndef ucx_array_sort_impl
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
56
|
#define ucx_array_sort_impl ucx_mergesort
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
57
|
#endif
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
58
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
59
|
static int ucx_array_ensurecap(UcxArray *array, size_t reqcap) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
60
|
size_t required_capacity = array->capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
61
|
while (reqcap > required_capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
62
|
if (required_capacity * 2 < required_capacity)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
63
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
64
|
required_capacity <<= 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
65
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
66
|
if (ucx_array_reserve(array, required_capacity)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
67
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
68
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
69
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
70
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
71
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
72
|
int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
73
|
size_t elmsize, size_t index, ...) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
74
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
75
|
if(!alloc || !capacity || !array) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
76
|
errno = EINVAL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
77
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
78
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
79
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
80
|
size_t newcapacity = *capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
81
|
while(index >= newcapacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
82
|
if(ucx_szmul(newcapacity, 2, &newcapacity)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
83
|
errno = EOVERFLOW;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
84
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
85
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
86
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
87
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
88
|
size_t memlen, offset;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
89
|
if(ucx_szmul(newcapacity, elmsize, &memlen)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
90
|
errno = EOVERFLOW;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
91
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
92
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
93
|
/* we don't need to check index*elmsize - it is smaller than memlen */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
94
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
95
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
96
|
void* newptr = alrealloc(alloc, *array, memlen);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
97
|
if(newptr == NULL) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
98
|
errno = ENOMEM; /* we cannot assume that every allocator sets this */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
99
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
100
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
101
|
*array = newptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
102
|
*capacity = newcapacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
103
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
104
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
105
|
char* dest = *array;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
106
|
dest += elmsize*index;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
107
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
108
|
va_list ap;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
109
|
va_start(ap, index);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
110
|
int elem = va_arg(ap, int);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
111
|
memcpy(dest, &elem, elmsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
112
|
va_end(ap);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
113
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
114
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
115
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
116
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
117
|
UcxArray* ucx_array_new(size_t capacity, size_t elemsize) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
118
|
return ucx_array_new_a(capacity, elemsize, ucx_default_allocator());
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
119
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
120
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
121
|
UcxArray* ucx_array_new_a(size_t capacity, size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
122
|
UcxAllocator* allocator) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
123
|
UcxArray* array = almalloc(allocator, sizeof(UcxArray));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
124
|
if(array) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
125
|
ucx_array_init_a(array, capacity, elemsize, allocator);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
126
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
127
|
return array;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
128
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
129
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
130
|
void ucx_array_init(UcxArray* array, size_t capacity, size_t elemsize) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
131
|
ucx_array_init_a(array, capacity, elemsize, ucx_default_allocator());
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
132
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
133
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
134
|
void ucx_array_init_a(UcxArray* array, size_t capacity, size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
135
|
UcxAllocator* allocator) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
136
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
137
|
array->allocator = allocator;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
138
|
array->elemsize = elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
139
|
array->size = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
140
|
array->data = alcalloc(allocator, capacity, elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
141
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
142
|
if (array->data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
143
|
array->capacity = capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
144
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
145
|
array->capacity = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
146
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
147
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
148
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
149
|
int ucx_array_clone(UcxArray* dest, UcxArray const* src) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
150
|
if (ucx_array_ensurecap(dest, src->capacity)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
151
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
152
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
153
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
154
|
dest->elemsize = src->elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
155
|
dest->size = src->size;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
156
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
157
|
if (dest->data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
158
|
memcpy(dest->data, src->data, src->size*src->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
159
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
160
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
161
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
162
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
163
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
164
|
int ucx_array_equals(UcxArray const *array1, UcxArray const *array2,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
165
|
cmp_func cmpfnc, void* data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
166
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
167
|
if (array1->size != array2->size || array1->elemsize != array2->elemsize) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
168
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
169
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
170
|
if (array1->size == 0)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
171
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
172
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
173
|
size_t elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
174
|
if (cmpfnc == NULL) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
175
|
cmpfnc = ucx_cmp_mem;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
176
|
elemsize = array1->elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
177
|
data = &elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
178
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
179
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
180
|
for (size_t i = 0 ; i < array1->size ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
181
|
int r = cmpfnc(
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
182
|
ucx_array_at(array1, i),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
183
|
ucx_array_at(array2, i),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
184
|
data);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
185
|
if (r != 0)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
186
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
187
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
188
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
189
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
190
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
191
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
192
|
void ucx_array_destroy(UcxArray *array) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
193
|
if(array->data)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
194
|
alfree(array->allocator, array->data);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
195
|
array->data = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
196
|
array->capacity = array->size = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
197
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
198
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
199
|
void ucx_array_free(UcxArray *array) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
200
|
ucx_array_destroy(array);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
201
|
alfree(array->allocator, array);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
202
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
203
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
204
|
int ucx_array_append_from(UcxArray *array, void *data, size_t count) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
205
|
if (ucx_array_ensurecap(array, array->size + count))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
206
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
207
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
208
|
void* dest = ucx_array_at(array, array->size);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
209
|
if (data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
210
|
memcpy(dest, data, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
211
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
212
|
memset(dest, 0, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
213
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
214
|
array->size += count;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
215
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
216
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
217
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
218
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
219
|
int ucx_array_prepend_from(UcxArray *array, void *data, size_t count) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
220
|
if (ucx_array_ensurecap(array, array->size + count))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
221
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
222
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
223
|
if (array->size > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
224
|
void *dest = ucx_array_at(array, count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
225
|
memmove(dest, array->data, array->elemsize*array->size);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
226
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
227
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
228
|
if (data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
229
|
memcpy(array->data, data, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
230
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
231
|
memset(array->data, 0, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
232
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
233
|
array->size += count;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
234
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
235
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
236
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
237
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
238
|
int ucx_array_set_from(UcxArray *array, size_t index,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
239
|
void *data, size_t count) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
240
|
if (ucx_array_ensurecap(array, index + count))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
241
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
242
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
243
|
if (index+count > array->size) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
244
|
array->size = index+count;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
245
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
246
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
247
|
void *dest = ucx_array_at(array, index);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
248
|
if (data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
249
|
memcpy(dest, data, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
250
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
251
|
memset(dest, 0, array->elemsize*count);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
252
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
253
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
254
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
255
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
256
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
257
|
int ucx_array_appendv(UcxArray *array, ...) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
258
|
va_list ap;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
259
|
va_start(ap, array);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
260
|
int elem = va_arg(ap, int);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
261
|
int ret = ucx_array_append_from(array, &elem, 1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
262
|
va_end(ap);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
263
|
return ret;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
264
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
265
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
266
|
int ucx_array_prependv(UcxArray *array, ...) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
267
|
va_list ap;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
268
|
va_start(ap, array);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
269
|
int elem = va_arg(ap, int);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
270
|
int ret = ucx_array_prepend_from(array, &elem, 1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
271
|
va_end(ap);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
272
|
return ret;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
273
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
274
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
275
|
int ucx_array_setv(UcxArray *array, size_t index, ...) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
276
|
va_list ap;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
277
|
va_start(ap, index);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
278
|
int elem = va_arg(ap, int);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
279
|
int ret = ucx_array_set_from(array, index, &elem, 1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
280
|
va_end(ap);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
281
|
return ret;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
282
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
283
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
284
|
int ucx_array_concat(UcxArray *array1, const UcxArray *array2) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
285
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
286
|
if (array1->elemsize != array2->elemsize)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
287
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
288
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
289
|
size_t capacity = array1->capacity+array2->capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
290
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
291
|
if (array1->capacity < capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
292
|
if (ucx_array_reserve(array1, capacity)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
293
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
294
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
295
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
296
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
297
|
void* dest = ucx_array_at(array1, array1->size);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
298
|
memcpy(dest, array2->data, array2->size*array2->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
299
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
300
|
array1->size += array2->size;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
301
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
302
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
303
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
304
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
305
|
void *ucx_array_at(UcxArray const *array, size_t index) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
306
|
char* memory = array->data;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
307
|
char* loc = memory + index*array->elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
308
|
return loc;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
309
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
310
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
311
|
size_t ucx_array_find(UcxArray const *array, void *elem,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
312
|
cmp_func cmpfnc, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
313
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
314
|
size_t elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
315
|
if (cmpfnc == NULL) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
316
|
cmpfnc = ucx_cmp_mem;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
317
|
elemsize = array->elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
318
|
data = &elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
319
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
320
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
321
|
if (array->size > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
322
|
for (size_t i = 0 ; i < array->size ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
323
|
void* ptr = ucx_array_at(array, i);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
324
|
if (cmpfnc(ptr, elem, data) == 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
325
|
return i;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
326
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
327
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
328
|
return array->size;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
329
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
330
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
331
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
332
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
333
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
334
|
int ucx_array_contains(UcxArray const *array, void *elem,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
335
|
cmp_func cmpfnc, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
336
|
return ucx_array_find(array, elem, cmpfnc, data) != array->size;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
337
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
338
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
339
|
static void ucx_mergesort_merge(void *arrdata,size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
340
|
cmp_func cmpfnc, void *data,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
341
|
size_t start, size_t mid, size_t end) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
342
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
343
|
char* array = arrdata;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
344
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
345
|
size_t rightstart = mid + 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
346
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
347
|
if (cmpfnc(array + mid*elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
348
|
array + rightstart*elemsize, data) <= 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
349
|
/* already sorted */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
350
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
351
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
352
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
353
|
/* we need memory for one element */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
354
|
void *value = malloc(elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
355
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
356
|
while (start <= mid && rightstart <= end) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
357
|
if (cmpfnc(array + start*elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
358
|
array + rightstart*elemsize, data) <= 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
359
|
start++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
360
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
361
|
/* save the value from the right */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
362
|
memcpy(value, array + rightstart*elemsize, elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
363
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
364
|
/* shift all left elements one element to the right */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
365
|
size_t shiftcount = rightstart-start;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
366
|
void *startptr = array + start*elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
367
|
void *dest = array + (start+1)*elemsize;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
368
|
memmove(dest, startptr, shiftcount*elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
369
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
370
|
/* bring the first value from the right to the left */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
371
|
memcpy(startptr, value, elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
372
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
373
|
start++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
374
|
mid++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
375
|
rightstart++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
376
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
377
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
378
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
379
|
/* free the temporary memory */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
380
|
free(value);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
381
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
382
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
383
|
static void ucx_mergesort_impl(void *arrdata, size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
384
|
cmp_func cmpfnc, void *data, size_t l, size_t r) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
385
|
if (l < r) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
386
|
size_t m = l + (r - l) / 2;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
387
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
388
|
ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, l, m);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
389
|
ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, m + 1, r);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
390
|
ucx_mergesort_merge(arrdata, elemsize, cmpfnc, data, l, m, r);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
391
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
392
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
393
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
394
|
static void ucx_mergesort(void *arrdata, size_t count, size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
395
|
cmp_func cmpfnc, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
396
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
397
|
ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, 0, count-1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
398
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
399
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
400
|
#ifdef USE_UCX_QSORT_R
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
401
|
struct cmpfnc_swapargs_info {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
402
|
cmp_func func;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
403
|
void *data;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
404
|
};
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
405
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
406
|
static int cmp_func_swap_args(void *data, const void *x, const void *y) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
407
|
cmpfnc_swapargs_info* info = data;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
408
|
return info->func(x, y, info->data);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
409
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
410
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
411
|
static void ucx_qsort_r(void *array, size_t count, size_t elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
412
|
cmp_func cmpfnc, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
413
|
struct cmpfnc_swapargs_info info;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
414
|
info.func = cmpfnc;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
415
|
info.data = data;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
416
|
qsort_r(array, count, elemsize, &info, cmp_func_swap_args);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
417
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
418
|
#endif /* USE_UCX_QSORT_R */
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
419
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
420
|
void ucx_array_sort(UcxArray* array, cmp_func cmpfnc, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
421
|
ucx_array_sort_impl(array->data, array->size, array->elemsize,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
422
|
cmpfnc, data);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
423
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
424
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
425
|
void ucx_array_remove(UcxArray *array, size_t index) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
426
|
array->size--;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
427
|
if (index < array->size) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
428
|
void* dest = ucx_array_at(array, index);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
429
|
void* src = ucx_array_at(array, index+1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
430
|
memmove(dest, src, (array->size - index)*array->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
431
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
432
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
433
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
434
|
void ucx_array_remove_fast(UcxArray *array, size_t index) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
435
|
array->size--;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
436
|
if (index < array->size) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
437
|
void* dest = ucx_array_at(array, index);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
438
|
void* src = ucx_array_at(array, array->size);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
439
|
memcpy(dest, src, array->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
440
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
441
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
442
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
443
|
int ucx_array_shrink(UcxArray* array) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
444
|
void* newptr = alrealloc(array->allocator, array->data,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
445
|
array->size*array->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
446
|
if (newptr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
447
|
array->data = newptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
448
|
array->capacity = array->size;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
449
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
450
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
451
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
452
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
453
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
454
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
455
|
int ucx_array_resize(UcxArray* array, size_t capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
456
|
if (array->capacity >= capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
457
|
void* newptr = alrealloc(array->allocator, array->data,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
458
|
capacity*array->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
459
|
if (newptr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
460
|
array->data = newptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
461
|
array->capacity = capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
462
|
if (array->size > array->capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
463
|
array->size = array->capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
464
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
465
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
466
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
467
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
468
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
469
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
470
|
return ucx_array_reserve(array, capacity);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
471
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
472
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
473
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
474
|
int ucx_array_reserve(UcxArray* array, size_t capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
475
|
if (array->capacity > capacity) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
476
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
477
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
478
|
void* newptr = alrealloc(array->allocator, array->data,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
479
|
capacity*array->elemsize);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
480
|
if (newptr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
481
|
array->data = newptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
482
|
array->capacity = capacity;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
483
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
484
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
485
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
486
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
487
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
488
|
}
|