summaryrefslogtreecommitdiffhomepage
path: root/docs/cvec_api.md
blob: f79ad3b0b3ff94b2897a7674ea19bb715119a892 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# STC [cvec](../stc/cvec.h): Vector
![Vector](pics/vector.jpg)

A **cvec** is a sequence container that encapsulates dynamic size arrays.

The storage of the vector is handled automatically, being expanded and contracted as needed. Vectors usually occupy more space than static arrays, because more memory is allocated to handle future growth. This way a vector does not need to reallocate each time an element is inserted, but only when the additional memory is exhausted. The total amount of allocated memory can be queried using *cvec_X_capacity()* function. Extra memory can be returned to the system via a call to *cvec_X_shrink_to_fit()*.

Reallocations are usually costly operations in terms of performance. The *cvec_X_reserve()* function can be used to eliminate reallocations if the number of elements is known beforehand.

See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vector) for a functional description.

## Declaration

```c
using_cvec(X, Value);
using_cvec(X, Value, valueCompareRaw);
using_cvec(X, Value, valueCompareRaw, valueDestroy);
using_cvec(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue);

using_cvec_str()
```
The macro `using_cvec()` can be instantiated with 2, 3, 5, or 7 arguments in the global scope.
Defaults values are given above for args not specified. `X` is a type tag name and
will affect the names of all cvec types and methods. E.g. declaring `using_cvec(my, int);`, `X` should
be replaced by `my` in all of the following documentation.

`using_cvec_str()` is a shorthand for:
```
using_cvec(str, cstr_t, cstr_compare_raw, cstr_del, cstr_from, cstr_c_str, const char*)
```

## Header file

All cvec definitions and prototypes may be included in your C source file by including a single header file.

```c
#include "stc/cvec.h"
```
## Methods

```c
cvec_X              cvec_X_init(void);
cvec_X              cvec_X_with_size(size_t size, Value fill);
cvec_X              cvec_X_with_capacity(size_t size);
cvec_X              cvec_X_clone(cvec_X vec);

void                cvec_X_clear(cvec_X* self);
void                cvec_X_shrink_to_fit(cvec_X* self);
void                cvec_X_reserve(cvec_X* self, size_t cap);
void                cvec_X_resize(cvec_X* self, size_t size, Value fill);
void                cvec_X_swap(cvec_X* a, cvec_X* b);

void                cvec_X_del(cvec_X* self);

bool                cvec_X_empty(cvec_X vec);
size_t              cvec_X_size(cvec_X vec);
size_t              cvec_X_capacity(cvec_X vec);

cvec_X_value_t*     cvec_X_at(cvec_X* self, size_t idx);
cvec_X_value_t*     cvec_X_front(cvec_X* self);
cvec_X_value_t*     cvec_X_back(cvec_X* self);

void                cvec_X_push_back(cvec_X* self, Value value);
void                cvec_X_emplace_back(cvec_X* self, RawValue raw);
void                cvec_X_emplace_n(cvec_X *self, const cvec_X_rawvalue_t arr[], size_t size);

void                cvec_X_pop_back(cvec_X* self);

cvec_X_iter_t       cvec_X_insert(cvec_X* self, size_t idx, Value value);
cvec_X_iter_t       cvec_X_insert_at(cvec_X* self, cvec_X_iter_t pos, Value value);
cvec_X_iter_t       cvec_X_insert_range(cvec_X* self, cvec_X_iter_t pos,
                                        cvec_X_iter_t first, cvec_X_iter_t finish);
cvec_X_iter_t       cvec_X_insert_range_p(cvec_X* self, cvec_X_value_t* pos,
                                          const cvec_X_value_t* pfirst, const cvec_X_value_t* pfinish);
cvec_X_iter_t       cvec_X_emplace(cvec_X* self, size_t idx, RawValue raw);
cvec_X_iter_t       cvec_X_emplace_at(cvec_X* self, cvec_X_iter_t pos, RawValue raw);

cvec_X_iter_t       cvec_X_erase(cvec_X* self, size_t idx, size_t n);
cvec_X_iter_t       cvec_X_erase_at(cvec_X* self, cvec_X_iter_t pos);
cvec_X_iter_t       cvec_X_erase_range(cvec_X* self, cvec_X_iter_t first, cvec_X_iter_t finish);
cvec_X_iter_t       cvec_X_erase_range_p(cvec_X* self, cvec_X_value_t* pfirst, cvec_X_value_t* pfinish);

cvec_X_iter_t       cvec_X_find(const cvec_X* self, RawValue raw);
cvec_X_iter_t       cvec_X_find_in_range(cvec_X_iter_t i1, cvec_X_iter_t i2, RawValue raw);
bool                cvec_X_bsearch(const cvec_X* self, RawValue raw);
bool                cvec_X_bsearch_in_range(cvec_X_iter_t i1, cvec_X_iter_t i2, RawValue raw);
void                cvec_X_sort(cvec_X* self);
void                cvec_X_sort_range(cvec_X_iter_t i1, cvec_X_iter_t i2,
                                      int(*cmp)(const cvec_X_value_t*, const cvec_X_value_t*));

cvec_X_iter_t       cvec_X_begin(const cvec_X* self);
cvec_X_iter_t       cvec_X_end(const cvec_X* self);
void                cvec_X_next(cvec_X_iter_t* it);
cvec_X_value_t*     cvec_X_itval(cvec_X_iter_t it);
size_t              cvec_X_index(const cvec_X vec, cvec_X_iter_t it);

cvec_X_value_t      cvec_X_value_clone(cvec_X_value_t val);
```

## Types

| Type name            | Type definition                     | Used to represent...   |
|:---------------------|:------------------------------------|:-----------------------|
| `cvec_X`             | `struct { cvec_X_value_t* data; }`  | The cvec type          |
| `cvec_X_value_t`     | `Value`                             | The cvec value type    |
| `cvec_X_rawvalue_t`  | `RawValue`                          | The raw value type     |
| `cvec_X_iter_t`      | `struct { cvec_X_value_t* ref; }`   | The iterator type      |

## Examples
```c
#include <stdio.h>
#include "stc/cvec.h"
using_cvec(i, int);

int main()
{
    // Create a vector containing integers
    cvec_i vec = cvec_i_init();
    c_emplace_items(&vec, cvec_i, {7, 5, 16, 8});

    // Add two more integers to vector
    cvec_i_push_back(&vec, 25);
    cvec_i_push_back(&vec, 13);

    printf("initial: ");
    c_foreach (n, cvec_i, vec) {
        printf(" %d", *n.ref);
    }

    // Sort the vector
    cvec_i_sort(&vec);

    printf("\nsorted: ");
    c_foreach (n, cvec_i, vec) {
        printf(" %d", *n.ref);
    }

    cvec_i_del(&vec);
}
```
Output:
```
initial:  7 5 16 8 25 13
sorted:  5 7 8 13 16 25
```
### Example 2
```c
#include "stc/cstr.h"
#include "stc/cvec.h"

using_cvec_str();

int main() {
    cvec_str names = cvec_str_init();
    cvec_str_emplace_back(&names, "Mary");
    cvec_str_emplace_back(&names, "Joe");
    cstr_assign(&names.data[1], "Jake"); // replace "Joe".

    cstr_t tmp = cstr_from_fmt("%d elements so far", cvec_str_size(names));

    // emplace_back() will not compile if adding a new cstr_t type. Use push_back():
    cvec_str_push_back(&names, tmp); // tmp is moved to names, do not del() it.

    printf("%s\n", names.data[1].str); // Access the second element

    c_foreach (i, cvec_str, names)
        printf("item: %s\n", i.ref->str);
    cvec_str_del(&names);
}
```
Output:
```
Jake
item: Mary
item: Jake
item: 2 elements so far
```
### Example 3

Container with elements of structs:
```c
#include <stc/cstr.h>
#include <stc/cvec.h>

typedef struct {
    cstr name; // dynamic string
    int id;
} User;

int User_compare(const User* a, const User* b) {
    int c = strcmp(a->name.str, b->name.str);
    return c != 0 ? c : a->id - b->id;
}
void User_del(User* self) {
    cstr_del(&self->name);
}
User User_clone(User user) {
    user.name = cstr_clone(user.name);
    return user;
}

// declare a memory managed, clonable vector of users:
using_cvec(u, User, User_compare, User_del, User_clone);

int main(void) {
    cvec_u vec = cvec_u_init();
    cvec_u_push_back(&vec, (User) {cstr_from("admin"), 0});
    cvec_u_push_back(&vec, (User) {cstr_from("joe"), 1});
    
    cvec_u vec2 = cvec_u_clone(vec);
    c_foreach (i, cvec_u, vec2)
        printf("%s: %d\n", i.ref->name.str, i.ref->id);

    c_del(cvec_u, &vec, &vec2); // cleanup
}
```