source: lib/data-struct/vector.c @ 0a474e3

develop
Last change on this file since 0a474e3 was 0a474e3, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

And more..

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26#include "vector.h"
27
28#include <stdlib.h>
29#include <string.h>
30#include <assert.h>
31
32DLLEXPORT void libtrace_vector_init(libtrace_vector_t *v, size_t element_size) {
33        v->element_size = element_size;
34        v->size = 0; // Starts empty
35        v->max_size = 128; // Pick a largish size to begin with
36        v->elements = malloc(v->max_size * v->element_size);
37        ASSERT_RET(pthread_mutex_init(&v->lock, NULL), == 0);
38}
39
40DLLEXPORT void libtrace_vector_destroy(libtrace_vector_t *v) {
41        ASSERT_RET(pthread_mutex_destroy(&v->lock), == 0);
42        free(v->elements);
43        // Be safe make sure we wont work any more
44        v->elements = NULL;
45        v->size = 0;
46        v->max_size = 0;
47        v->element_size = 0;
48}
49
50DLLEXPORT void libtrace_vector_push_back(libtrace_vector_t *v, void *d) {
51        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
52        if (v->size >= v->max_size) {
53                /* Resize */
54                v->max_size *= 2;
55                v->elements = realloc(v->elements, v->max_size * v->element_size);
56                /*assert(v->elements);*/
57                if (!v->elements) {
58                        fprintf(stderr, "Unable to allocate memory for v->elements in libtrace_vector_push_back()\n");
59                        return;
60                }
61        }
62        memcpy(&v->elements[v->size*v->element_size], d, v->element_size);
63        v->size++;
64        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
65}
66
67DLLEXPORT size_t libtrace_vector_get_size(libtrace_vector_t *v) {
68        return v->size;
69}
70
71DLLEXPORT int libtrace_vector_get(libtrace_vector_t *v, size_t location, void *d) {
72        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
73        if (location >= v->size) {
74                ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
75                return 0;
76        }
77        memcpy(d, &v->elements[location*v->element_size], v->element_size);
78        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
79        return 1;
80}
81
82DLLEXPORT int libtrace_vector_remove_front(libtrace_vector_t *v) {
83        size_t i;
84        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
85        if (!v->size) {
86                ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
87                return 0;
88        }
89        v->size--;
90        // Of course this is mega slow
91        for (i = 0; i < v->size * v->element_size; i++)
92                v->elements[i] = v->elements[i+v->element_size];
93        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
94        return 1;
95}
96
97static inline void memswap(void *a, void *b, size_t size) {
98        char c;
99        size_t i;
100        for (i=0; i<size; i++) {
101                c = ((char *)a)[i];
102                ((char *)a)[i] = ((char *)b)[i];
103                ((char *)b)[i] = c;
104        }
105}
106// Note elements must be the same size
107// This also empties the second source array
108DLLEXPORT void libtrace_vector_append(libtrace_vector_t *dest, libtrace_vector_t *src)
109{
110        /*assert(dest->element_size == src->element_size);*/
111        if (dest->element_size != src->element_size) {
112                fprintf(stderr, "Elements must be the same size in libtrace_vector_append()\n");
113                return;
114        }
115        if (src->size == 0) // Nothing to do if this is the case
116                return;
117        ASSERT_RET(pthread_mutex_lock(&dest->lock), == 0);
118        ASSERT_RET(pthread_mutex_lock(&src->lock), == 0);
119        if (src->size == 0) // Double check now we've got the locks - Nothing to do if this is the case
120                goto unlock;
121        if (dest->size == 0) {
122                memswap(&dest->max_size, &src->max_size, sizeof(src->max_size));
123                memswap(&dest->size, &src->size, sizeof(src->size));
124                memswap(&dest->element_size, &src->element_size, sizeof(src->element_size));
125                memswap(&dest->elements, &src->elements, sizeof(src->elements));
126        } else {
127                size_t oldmax = dest->max_size;
128                while (dest->max_size - dest->size < src->size) dest->max_size *= 2;
129                if (oldmax != dest->max_size)
130                        dest->elements = realloc(dest->elements, dest->max_size * dest->element_size);
131                // Now do the move
132                memcpy(&dest->elements[dest->element_size * dest->size], src->elements, src->element_size * src->size);
133                // Update the dest size
134                dest->size += src->size;
135                // Wipe the src
136                src->size = 0;
137        }
138unlock:
139        ASSERT_RET(pthread_mutex_unlock(&src->lock), == 0);
140        ASSERT_RET(pthread_mutex_unlock(&dest->lock), == 0);
141}
142
143DLLEXPORT void libtrace_zero_vector(libtrace_vector_t *v)
144{
145        v->max_size = 0;
146        v->size = 0;
147        v->element_size = 0;
148        v->elements = NULL;
149}
150
151DLLEXPORT void libtrace_vector_empty(libtrace_vector_t *v) {
152        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
153        v->size = 0;
154        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
155}
156
157
158DLLEXPORT void libtrace_vector_apply_function(libtrace_vector_t *v, vector_data_fn fn)
159{
160        size_t cur;
161        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
162        for (cur = 0; cur < v->size; cur++) {
163                (*fn)(&v->elements[cur*v->element_size]);
164        }
165        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
166}
167
168DLLEXPORT void libtrace_vector_qsort(libtrace_vector_t *v, int (*compar)(const void *, const void*)) {
169        ASSERT_RET(pthread_mutex_lock(&v->lock), == 0);
170        qsort(v->elements, v->element_size, v->element_size, compar);
171        ASSERT_RET(pthread_mutex_unlock(&v->lock), == 0);
172}
Note: See TracBrowser for help on using the repository browser.