include/mgba-util/vector.h (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#ifndef VECTOR_H
7#define VECTOR_H
8
9#include <mgba-util/common.h>
10
11CXX_GUARD_START
12
13#define DECLARE_VECTOR(NAME, TYPE) \
14 struct NAME { \
15 TYPE* vector; \
16 size_t size; \
17 size_t capacity; \
18 }; \
19 void NAME ## Init(struct NAME* vector, size_t capacity); \
20 void NAME ## Deinit(struct NAME* vector); \
21 TYPE* NAME ## GetPointer(struct NAME* vector, size_t location); \
22 TYPE const* NAME ## GetConstPointer(const struct NAME* vector, size_t location); \
23 TYPE* NAME ## Append(struct NAME* vector); \
24 void NAME ## Clear(struct NAME* vector); \
25 void NAME ## Resize(struct NAME* vector, ssize_t change); \
26 void NAME ## Shift(struct NAME* vector, size_t location, size_t difference); \
27 void NAME ## Unshift(struct NAME* vector, size_t location, size_t difference); \
28 void NAME ## EnsureCapacity(struct NAME* vector, size_t capacity); \
29 size_t NAME ## Size(const struct NAME* vector); \
30 size_t NAME ## Index(const struct NAME* vector, const TYPE* member); \
31 void NAME ## Copy(struct NAME* dest, const struct NAME* src);
32
33#define DEFINE_VECTOR(NAME, TYPE) \
34 void NAME ## Init(struct NAME* vector, size_t capacity) { \
35 vector->size = 0; \
36 if (capacity == 0) { \
37 capacity = 4; \
38 } \
39 vector->capacity = capacity; \
40 vector->vector = malloc(sizeof(TYPE) * capacity); \
41 } \
42 void NAME ## Deinit(struct NAME* vector) { \
43 free(vector->vector); \
44 vector->vector = 0; \
45 vector->capacity = 0; \
46 } \
47 TYPE* NAME ## GetPointer(struct NAME* vector, size_t location) { \
48 return &vector->vector[location]; \
49 } \
50 TYPE const* NAME ## GetConstPointer(const struct NAME* vector, size_t location) { \
51 return &vector->vector[location]; \
52 } \
53 TYPE* NAME ## Append(struct NAME* vector) { \
54 NAME ## Resize(vector, 1); \
55 return &vector->vector[vector->size - 1]; \
56 } \
57 void NAME ## Resize(struct NAME* vector, ssize_t change) { \
58 if (change > 0) { \
59 NAME ## EnsureCapacity(vector, vector->size + change); \
60 } \
61 vector->size += change; \
62 } \
63 void NAME ## Clear(struct NAME* vector) { \
64 vector->size = 0; \
65 } \
66 void NAME ## EnsureCapacity(struct NAME* vector, size_t capacity) { \
67 if (capacity <= vector->capacity) { \
68 return; \
69 } \
70 while (capacity > vector->capacity) { \
71 vector->capacity <<= 1; \
72 } \
73 vector->vector = realloc(vector->vector, vector->capacity * sizeof(TYPE)); \
74 } \
75 void NAME ## Shift(struct NAME* vector, size_t location, size_t difference) { \
76 memmove(&vector->vector[location], &vector->vector[location + difference], (vector->size - location - difference) * sizeof(TYPE)); \
77 vector->size -= difference; \
78 } \
79 void NAME ## Unshift(struct NAME* vector, size_t location, size_t difference) { \
80 NAME ## Resize(vector, difference); \
81 memmove(&vector->vector[location + difference], &vector->vector[location], (vector->size - location - difference) * sizeof(TYPE)); \
82 } \
83 size_t NAME ## Size(const struct NAME* vector) { \
84 return vector->size; \
85 } \
86 size_t NAME ## Index(const struct NAME* vector, const TYPE* member) { \
87 return member - (const TYPE*) vector->vector; \
88 } \
89 void NAME ## Copy(struct NAME* dest, const struct NAME* src) { \
90 NAME ## EnsureCapacity(dest, src->size); \
91 memcpy(dest->vector, src->vector, src->size * sizeof(TYPE)); \
92 dest->size = src->size; \
93 } \
94
95CXX_GUARD_END
96
97#endif