Compare commits
5
Commits
b89579a5e7
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12b560fb37 | ||
|
|
0e7c2cafaa | ||
|
|
1654b86640 | ||
|
|
4d96592a1e | ||
|
|
813390b6ac |
@@ -3,3 +3,6 @@ build/
|
|||||||
tests/cache/
|
tests/cache/
|
||||||
tests/bin/
|
tests/bin/
|
||||||
coverage.html
|
coverage.html
|
||||||
|
|
||||||
|
tests
|
||||||
|
Makefile
|
||||||
|
|||||||
@@ -1,270 +0,0 @@
|
|||||||
# libvec bug tracker
|
|
||||||
|
|
||||||
**Pass 12** — verified **2026-10-12** — `char.c` @ 957 lines · `char.h` @ 108
|
|
||||||
|
|
||||||
| Open | S1 | S2 | S3 | C | DECIDE | Fixed |
|
|
||||||
|:----:|:--:|:--:|:--:|:-:|:------:|:-----:|
|
|
||||||
| **42** | 8 | 15 | 7 | 12 | 0 | 63 |
|
|
||||||
|
|
||||||
`S1` memory safety · `S2` wrong result / broken contract · `S3` edge case · `C` cleanup · `DECIDE` open design question
|
|
||||||
|
|
||||||
> **Line numbers are the only field that drifts.** Re-verify before trusting them.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contents
|
|
||||||
|
|
||||||
- [Triage — the 8 open S1s](#triage)
|
|
||||||
- [Findings](#findings)
|
|
||||||
- [Core storage](#core-storage)
|
|
||||||
- [Validation & accessors](#validation--accessors)
|
|
||||||
- [Algorithms](#algorithms)
|
|
||||||
- [Support](#support)
|
|
||||||
- [Fixed](#fixed)
|
|
||||||
- [ID map](#id-map)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a id="triage"></a>
|
|
||||||
|
|
||||||
## Triage — the 8 open S1s
|
|
||||||
|
|
||||||
In suggested fixing order.
|
|
||||||
|
|
||||||
| # | ID | Location | Summary |
|
|
||||||
|:-:|:---|:---------|:--------|
|
|
||||||
| 1 | `IV-5` | char.c:40-44 | `__null_check`'s NULL-`status` branch derefs the very NULL it just tested, and seven call sites pass the caller's `err` through here → `SEGV` at 42. **ASan Pass 12: SEGV in `__null_check`** |
|
|
||||||
| 2 | `FB-1` | char.c:457-462, 475-480 | `front`/`back` guard inverted: populated vectors return 0 + `ERR_OUT_OF_BOUNDS`; drained vectors fall through to `*nullptr` → SEGV at 462/480. `back` probes index 0 |
|
|
||||||
| 3 | `IN-10` | char.c:886-893 | amount-insert never validates: guard at 887 reads a fresh local (always 0), NULL `ptr` derefs at 893 → SEGV |
|
|
||||||
| 4 | `ER-4` | char.c:541-542 | range-erase zeroing `memset` length is the whole `_internal_size`, not `diff`, so it writes past the buffer → `heap-buffer-overflow` WRITE at 541 |
|
|
||||||
| 5 | `RZ-10` | char.c:626-629, 712-715 | resize-shrink `memset` length is the whole old `_internal_size`, not `old - new` → `heap-buffer-overflow` WRITE at 628/714 |
|
|
||||||
| 6 | `RZ-11` | char.c:630-634, 716-720 | resize-growth `memset` length is `_internal_arr[size]` (an element value) instead of `size - _internal_size`; reads one past the block when `size == capacity` → `heap-buffer-overflow` READ at 633/719 |
|
|
||||||
| 7 | `RS-1` | char.c:264-269 | truncation zeroed through the post-realloc pointer: `memset(&arr[capacity], 0, size - capacity)` (267) writes past the shrunk block → `heap-buffer-overflow` WRITE at 267 |
|
|
||||||
| 8 | `DL-2` | char.h:8-14 | no ownership marker, by-value struct copy double-frees |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a id="findings"></a>
|
|
||||||
|
|
||||||
## Findings
|
|
||||||
|
|
||||||
<a id="core-storage"></a>
|
|
||||||
|
|
||||||
### Core storage
|
|
||||||
|
|
||||||
#### `_vec_char_push_back` / `_vec_char_pop_back` — char.c:141, 202
|
|
||||||
|
|
||||||
*1 S2*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `PB-9` | S2 | char.c:161-173 vs 242-254 vs 839-853 | three blank-materialize paths, no shared shape. `push_back`: `malloc(1)`, `capacity=1`, `size=0`, writes `arr[0]`. `reserve`: `calloc(capacity)` and commits `capacity`. `insert` one-arg: `malloc(1)`, `capacity=1`, `size=1`, writes `arr[0]`. Same input state, three allocations, three struct results; `insert` and `resize` disagree with `push_back` on which blank states are accepted |
|
|
||||||
|
|
||||||
#### `_vec_char_cpy` — char.c:103 — *Clear*
|
|
||||||
|
|
||||||
#### `_vec_char_reserve` — char.c:221
|
|
||||||
|
|
||||||
*1 S1*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `RS-1` | S1 | char.c:264-269 | `ptr->_internal_arr = res` (264) runs before the truncation, so the discarded tail is zeroed through the NEW pointer — but `realloc` already shrunk the block to `capacity` bytes, and `memset(&ptr->_internal_arr[capacity], 0, ptr->_internal_size - capacity)` (267-268) writes past it. **ASan Pass 12: `heap-buffer-overflow` WRITE at 267** — push 4, `reserve(&v, 2)`. The tail to zero no longer exists after a shrinking realloc: the `memset` must run on the old buffer before `realloc`, or be dropped — spare slots are uninitialized by contract |
|
|
||||||
|
|
||||||
#### `_vec_char_shrink_to_fit` — char.c:277 — *Clear*
|
|
||||||
|
|
||||||
#### `_vec_char_swap` — char.c:295 — *Clear*
|
|
||||||
|
|
||||||
#### `_vec_char_delete` — char.c:364
|
|
||||||
|
|
||||||
*1 S1*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `DL-2` | S1 | char.h:8-14 | no ownership marker on the struct, so a by-value copy yields two owners of one buffer; each `delete` clears only its own struct's pointer, so the second free hits the first's freed block. **ASan Pass 12: `attempting double-free` at char.c:376** — `w = v; delete(&v); delete(&w)` |
|
|
||||||
|
|
||||||
#### `_vec_char_clear` / `_vec_char_print_vec` — char.c:383, 89 — *Clear*
|
|
||||||
|
|
||||||
<a id="validation--accessors"></a>
|
|
||||||
|
|
||||||
### Validation & accessors
|
|
||||||
|
|
||||||
#### `__null_check` / `__origin_override` — char.c:37, 69
|
|
||||||
|
|
||||||
*1 S1*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `IV-5` | S1 | char.c:40-44 | the `status == nullptr` branch exists to catch a NULL `err_t*` but dereferences `status` on the next line (`status->flags = ...`, 42; `status->origin = ...`, 43). Seven call sites hand `__null_check` the caller's `err` verbatim (print_vec 92, pop_back 205, begin 425, end 438, front 451, back 469, empty 487), so any of those with a NULL `err` is a live null-deref. **ASan Pass 12: SEGV in `__null_check` at char.c:42.** Either return before the deref or drop the branch |
|
|
||||||
|
|
||||||
#### `_vec_char_capacity` / `_vec_char_max_size` / `_vec_char_data` / `_vec_char_size` — char.c:338, 351, 312, 325
|
|
||||||
|
|
||||||
*1 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `AC-3` | C | char.c:326-335 | new `size` accessor records its failure origin as `"CAPACITY"` (331), copied from `_vec_char_capacity`. It also takes a non-`const` `_VecCharInternal*` (326) while only reading, unlike its `const` siblings |
|
|
||||||
|
|
||||||
#### `_vec_char_at` — char.c:400
|
|
||||||
|
|
||||||
*1 S3 · 1 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `AT-2` | S3 | char.c:410-417 | the OOB path sets `err` (flags + origin AT) and returns `nullptr`, but still prints a raw line to **stdout** via `printf` (412-413), polluting program output and bypassing the error channel. The residual hazard moved to the callers: `front`/`back` dereference the `nullptr` (462, 480) → SEGV (FB-1) |
|
|
||||||
| `AT-3` | C | char.c:400, 418 | `at()` returns a mutable `char*` into the buffer of a `const _VecCharInternal*` — const-laundering callers can write elements behind the API's back, bypassing `push_back`/`resize` bookkeeping; the pointer also invalidates on any realloc |
|
|
||||||
|
|
||||||
#### `_vec_char_begin` / `_vec_char_end` — char.c:421, 434
|
|
||||||
|
|
||||||
*1 S2*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `BE-1` | S2 | char.c:421-432, 434-445, 749-750, 799-800 | `begin` returns raw `status.flags` (bitmask 2/4) as an index on failure (429), and `end`'s `(size_t)(size - 1)` (444) is **reachable for a drained vector** — `size == 0` wraps to `SIZE_MAX` (harness Pass 12: end(drained) = 18446744073709551615, flags=0). Flags-as-index and SIZE_MAX-as-end are indistinguishable from real positions; `SIZE_MAX + 1` wraps to 0 at 749-750, 799-800, so `assign` into a drained destination erases `[0, 0)` and fails with `ERR_OUT_OF_BOUNDS` (AS-1) |
|
|
||||||
|
|
||||||
#### `_vec_char_front` / `_vec_char_back` / `_vec_char_empty` — char.c:447, 465, 483
|
|
||||||
|
|
||||||
*1 S1 · 1 S2*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `FB-1` | S1 | char.c:457-462, 475-480 | the guard meant to kill the drained SEGV is **inverted and probes the wrong index**. `at()` returns `nullptr` on failure, so `if (_vec_char_at(...) != nullptr)` fires for *valid* vectors: **`front`/`back` on a populated vector return 0 with `ERR_OUT_OF_BOUNDS`** (harness Pass 12: front('ab')=0/flags=16, back=0/flags=16 — expected 97/98). For a drained vector `at` returns nullptr, the condition is false, control falls through to the deref — `front` → `*_vec_char_at(ptr, 0, err)` (462), `back` → `*_vec_char_at(ptr, size - 1, err)` (480) — **SEGV** (ASan Pass 12: SEGV at 462 and 480). `back` also probes index 0 (475) instead of `size - 1`. Condition must be `== nullptr`, and `back` must probe the last index |
|
|
||||||
| `AC-2` | S2 | char.c:483-498 | `empty()` still returns 0 in *both* directions: a drained vector takes the `size == 0` branch and `return SUCCESS` (493-496), a populated one falls through to `return status.flags`, also 0 (497) — so `if (empty(&v))` is never true for a valid vector. **Harness Pass 12: drained → 0/err 0, populated → 0/err 0** |
|
|
||||||
|
|
||||||
<a id="algorithms"></a>
|
|
||||||
|
|
||||||
### Algorithms
|
|
||||||
|
|
||||||
#### `_vec_char_erase` (both overloads) — char.c:501, 520
|
|
||||||
|
|
||||||
*1 S1 · 1 S2 · 1 S3 · 1 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `ER-4` | S1 | char.c:541-542 | the trailing-zero `memset` starts at `_internal_size - diff` but its length is `sizeof(char) * ptr->_internal_size` (the *whole* old size, though `_internal_size` is not decremented until 543), so it writes `[size - diff, 2*size - diff)` — past the block whenever more than `diff` elements remain. Should be `diff` bytes. **ASan Pass 12: `heap-buffer-overflow` WRITE at 541** — 10 elements in a 13-byte block, `erase(&v, 0, 1)` |
|
|
||||||
| `ER-1` | S2 | char.c:532-537 | `erase` on an empty vector never no-ops: a drained vector passes the `__null_check` guard now, then the range check (`size < iter_end \|\| iter_end <= iter_start`) fires — `[0, 1)` because `0 < 1`, and even `[0, 0)` because `0 <= 0`. **Harness Pass 12: erase(v, 0, 1) on drained → err=16, origin ERASE** |
|
|
||||||
| `ER-3` | S3 | char.c:511 | the single-arg overload silently returns on `iter >= size` with `err` untouched (harness Pass 12: erase index 99 → flags=0), while the range overload reports `ERR_OUT_OF_BOUNDS` for the same condition. A typo'd index is invisible to an err-driven caller |
|
|
||||||
| `ER-2` | C | char.c:500, 519 | two stale `// TODO: Fix return value` comments remain (the second doubled as `// // TODO`) |
|
|
||||||
|
|
||||||
#### `_vec_char_resize` (both overloads) — char.c:547, 639
|
|
||||||
|
|
||||||
*2 S1 · 2 S2 · 2 S3 · 3 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `RZ-10` | S1 | char.c:626-629, 712-715 | shrink zeroing `memset(&arr[size], 0, ptr->_internal_size)` uses the *whole old* `_internal_size` as the length instead of `old - new`, so it writes past the block whenever `0 < size < old`. Should be `_internal_size - size` bytes. **ASan Pass 12: `heap-buffer-overflow` WRITE at 628** — 5 elements in a 6-byte block, `resize(&v, 2)` (also 714 for the 3-arg overload) |
|
|
||||||
| `RZ-11` | S1 | char.c:630-634, 716-720 | growth fill `memset(&arr[_internal_size], 0, ptr->_internal_arr[size])` passes `_internal_arr[size]` — an *element value* (or 0xbe uninitialized) — as the byte count instead of `size - _internal_size`, and when `size == _internal_capacity` that read is one past the block. **ASan Pass 12: `heap-buffer-overflow` READ at 633** — 5 elements in a 6-byte block, `resize(&v, 6)` (also 719 for the 3-arg overload) |
|
|
||||||
| `RZ-3` | S2 | char.c:573-596, 665-688 | the `max_size` save/restore (575/594, 667/686) is pure belt-and-braces now that `reserve` leaves `max_size` alone, and looks removable. Nothing documents that |
|
|
||||||
| `RZ-1` | S2 | char.c:559-564, 651-656 | `size == _internal_size` returns `ERR_OUT_OF_BOUNDS` for a legitimate no-op; the code is also semantically wrong |
|
|
||||||
| `RZ-4` | S3 | char.c:594-596 vs 686-688 | the 3-arg blank branch fills with `val`, the 2-arg with `0`. `data()` exposes the difference |
|
|
||||||
| `RZ-2` | S3 | char.c:605, 695 | unguarded `tmpcp *= 2` wraps on overflow. Defensive |
|
|
||||||
| `RZ-5` | C | char.c:584-589, 607-611, 618-623, 676-681, 699-703 | dead post-`reserve` capacity checks in the blank branches (584, 676) and the 2-arg growth branch (618); the 3-arg growth branch has no check at all, relying on `reserve` to be exact |
|
|
||||||
| `RZ-6` | C | char.c:547-637 vs 639-723 | two ~90-line near-identical bodies, with the growth blocks copy-pasted between them |
|
|
||||||
| `RZ-7` | C | char.c:590-593, 682-685 | the blank-branch fill loops should be `memset` |
|
|
||||||
|
|
||||||
#### `_vec_char_assign` (both overloads) — char.c:725, 783
|
|
||||||
|
|
||||||
*4 S2 · 1 S3 · 1 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `AS-1` | S2 | char.c:730-735, 749-750, 799-800 | fails on any empty destination. A **blank** destination trips the `__null_check` guard (730-735) → err=4, origin ASSIGN. A **drained** one passes the guard, then `end()` returns `SIZE_MAX` (BE-1) and `end + 1` wraps to 0 (749, 799), so `erase(0, 0)` fails the range check → err=16. Two paths, same refusal |
|
|
||||||
| `AS-2` | S2 | char.c:749-778, 799-823 | not atomic: `erase` → `reserve` → `push_back` loop. Reserve failure leaves the destination wiped; a `push_back` failure mid-loop leaves it partially filled. Still no rollback |
|
|
||||||
| `AS-3` | S2 | char.c:757, 807 | no `> _internal_max_size` guard on the assign count |
|
|
||||||
| `AS-7` | S2 | char.c:764-770 | the `at()` guard in assign1 is **inverted**: `at()` returns `nullptr` on failure, so the `!= nullptr` branch fires for *valid* iterators — assign1 fails with `ERR_OUT_OF_BOUNDS` on the first element of **every non-empty source**, after erase already wiped the destination (harness Pass 12: dest `{x,y}` ← src `{a,b}` → flags=16, size=0). Condition must be `== nullptr` |
|
|
||||||
| `AS-9` | S3 | char.c:788-792 | the null guard in the amount overload has **no `return`**, unlike assign1 — control falls through with `err` already flagged. Masked today only because the `erase` at 799 rejects the same state downstream |
|
|
||||||
| `AS-6` | C | char.c:725-781 vs 783-825 | near-duplicate overloads differing only in the value source |
|
|
||||||
|
|
||||||
#### `_vec_char_insert` (all three overloads) — char.c:827, 882, 918
|
|
||||||
|
|
||||||
*1 S1 · 2 S2 · 2 S3 · 2 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `IN-10` | S1 | char.c:886-893 | the amount overload never calls `__null_check`: the guard at 887-892 tests a freshly-initialized local `status`, which is always 0, so it can never fire; `ptr` is then dereferenced raw at 893. Every other entry point validates first. **ASan Pass 12: SEGV at char.c:893** — `_vec_char_insert(nullptr, 0, 2, 'x', &e)` |
|
|
||||||
| `IN-1` | S2 | char.c:932-938 | inverted range check: `iter_end > iter_start` rejects every non-empty range with `ERR_OUT_OF_BOUNDS` and accepts only empty ranges, which then silently do nothing (loop at 945 never runs). Valid insert-range never inserts. **Harness Pass 12: dest `{a,b}`, src `{Z}`, insert at 1 range [0,1) → err=16, size stays 2** |
|
|
||||||
| `IN-4` | S2 | char.c:854-859, 884-893 | no `max_size` pre-check in the amount overload: the loop pushes until one-arg insert trips `size+1 > max_size` (854) and then returns, but everything already inserted stays — an oversized `amount` half-inserts and leaves the vector half-modified |
|
|
||||||
| `IN-5` | S3 | char.c:899-904 | `amount <= 0` on a `size_t` is always just `== 0` |
|
|
||||||
| `IN-6` | S3 | char.c:905 | `iter + amount` can overflow `size_t`, wrapping the loop bound and exiting early — a silent partial insert |
|
|
||||||
| `IN-8` | C | char.c:945-955 | the loop reads `iterator->_internal_arr[i]` raw (948) instead of a bounds-checked accessor. **Unreachable today**: IN-1's inversion rejects every non-empty range, so the body never runs. The `iter_end > iterator->_internal_size` clause at 932 does bound the read once IN-1 is fixed, so this stays a style finding |
|
|
||||||
| `IN-9` | C | char.c:905-914 | O(amount²) loop of single inserts where one grow + `memmove` would do |
|
|
||||||
|
|
||||||
<a id="support"></a>
|
|
||||||
|
|
||||||
### Support
|
|
||||||
|
|
||||||
#### `utils.h` / `utils.c`
|
|
||||||
|
|
||||||
*3 S2 · 1 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `UT-1` | S2 | utils.h:9 | `SIZE_MAX / sizeof(int)` is what the `char` vector uses as `_internal_max_size`, capping it at 1/4 of the usable address space |
|
|
||||||
| `UT-6` | S2 | utils.c:14-16 | `vec_get_error_desc`'s default case is an expression statement — `"Unknown";` with no `return` — so an out-of-range code falls off the end of a non-void function: UB, and the caller printf's a garbage `char*`. Current call sites only pass constants, so it is one cast away |
|
|
||||||
| `UT-7` | S2 | utils.c:22-35 | `vec_print_errs` prints `err.origin` only on the SUCCESS branch (24), where it is always NULL on an untouched `err_t` — `%s` of NULL, UB — and the failure branch (27-35) never prints origin at all. The root-cause feature surfaces exactly backwards |
|
|
||||||
| `UT-4` | C | utils.h:7-9, 63-65 | `static const` in a header gives every TU its own copy; `ERR_SIZE_ZERO` message mentions `< 0` on a `size_t`; `LOG`/`DEBUG` are hardwired to stdout and single-arg; `find_len` is UB for pointers; `CAPACITY` (7) and `VEC_FAULT_BITS` (8) are now referenced by nothing in the tree |
|
|
||||||
|
|
||||||
#### `char.h` — *Clear*
|
|
||||||
|
|
||||||
#### Project
|
|
||||||
|
|
||||||
*2 C*
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding |
|
|
||||||
|:---|:--:|:---------|:--------|
|
|
||||||
| `PR-8` | C | char.c:72, 112 (and every guard) | no function checks `err` for NULL before the first error path derefs it; a NULL `err_t*` segfaults on the first failure. Now documented (char.c:27-30) — a cheap defensive check would still harden the API. IV-5 is the same hazard at the one site that *tries* to check |
|
|
||||||
| `PR-2` | C | char.c:179, 500, 519 | mixed brace style (single-line `if` at 179 vs expanded blocks) and stale `TODO` comments at 500/519; `.clang-format` exists and is not run |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a id="fixed"></a>
|
|
||||||
|
|
||||||
## Fixed
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>63 fixed IDs — no rows</b></summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
PB-1 PB-2 PB-3 PB-4 PB-6 PB-7 PB-8 PB-14 PB-15 PB-16 PB-17 PB-18 PB-20 PB-21
|
|
||||||
RS-2 RS-3 RS-4 RS-6 RS-7 RS-8
|
|
||||||
IV-1 IV-3 IV-4
|
|
||||||
CH-1 CH-3 CH-7
|
|
||||||
CR-3 CR-4 CR-6 CR-7 CR-8 CR-10 CR-11
|
|
||||||
SW-1 SW-2
|
|
||||||
FB-2
|
|
||||||
AC-1 DA-1
|
|
||||||
AT-1
|
|
||||||
DL-1 DL-3
|
|
||||||
UT-2 UT-3 UT-5
|
|
||||||
PR-1 PR-3 PR-4
|
|
||||||
CL-1 CL-2
|
|
||||||
RZ-8 RZ-9
|
|
||||||
AS-4 AS-8
|
|
||||||
ST-1 ST-2
|
|
||||||
IN-2 IN-11 IN-12
|
|
||||||
FX-2 FX-3 FX-4 FX-5
|
|
||||||
BE-2
|
|
||||||
```
|
|
||||||
|
|
||||||
Closed by owner decision (not counted fixed): `CH-9` (leading `_` intended private), `PR-7` (main not the test harness), `CH-4` (header includes), `CH-5` (doc comments), `CH-8` (struct naming), `PR-5` (placeholder comments), `CH-2` (const on by-value params for LSP/clarity).
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a id="id-map"></a>
|
|
||||||
|
|
||||||
## ID map
|
|
||||||
|
|
||||||
| Prefix | Scope | Prefix | Scope |
|
|
||||||
|:------:|:------|:------:|:------|
|
|
||||||
| `PB-` | push_back, pop_back | `AT-` | at |
|
|
||||||
| `RS-` | reserve | `FB-` | front, back |
|
|
||||||
| `ST-` | shrink_to_fit | `BE-` | begin, end |
|
|
||||||
| `CR-` | create → cpy | `SW-` | swap |
|
|
||||||
| `AC-` | accessors | `CL-` | clear, print_vec |
|
|
||||||
| `DA-` | data | `IV-` | is_valid → __null_check |
|
|
||||||
| `DL-` | delete | `UT-` | utils.h, utils.c |
|
|
||||||
| `ER-` | erase | `CH-` | char.h |
|
|
||||||
| `RZ-` | resize | `PR-` | project |
|
|
||||||
| `AS-` | assign | `FX-` | retired first-pass IDs |
|
|
||||||
| `IN-` | insert | | |
|
|
||||||
+16
-7
@@ -5,15 +5,24 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
add_library(libvec STATIC
|
add_library(libvec STATIC
|
||||||
src/libvec.c
|
src/char.c
|
||||||
src/lib/char/char.c
|
src/int.c
|
||||||
src/lib/utils/utils.c
|
src/utils.c
|
||||||
|
src/float.c
|
||||||
|
src/string.c
|
||||||
# Add your other types here as you implement them:
|
# Add your other types here as you implement them:
|
||||||
# src/lib/float/float.c
|
|
||||||
# src/lib/int/int.c
|
|
||||||
# src/lib/string/string.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(libstr
|
||||||
|
GIT_REPOSITORY https://git.moomancer.xyz/DarthMooMancer/libstr.git
|
||||||
|
GIT_TAG main
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(libstr)
|
||||||
|
|
||||||
|
target_link_libraries(libvec PRIVATE libstr)
|
||||||
|
|
||||||
target_include_directories(libvec
|
target_include_directories(libvec
|
||||||
# PRIVATE: Internal headers under src/lib are only visible
|
# PRIVATE: Internal headers under src/lib are only visible
|
||||||
# to files being compiled into libvec (char.c, utils.c, libvec.c).
|
# to files being compiled into libvec (char.c, utils.c, libvec.c).
|
||||||
@@ -22,7 +31,7 @@ target_include_directories(libvec
|
|||||||
# PUBLIC: Consumers (and test_runner) are granted access ONLY to include/
|
# PUBLIC: Consumers (and test_runner) are granted access ONLY to include/
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/lib # Turn back to private when ready
|
# ${CMAKE_CURRENT_SOURCE_DIR}/src/lib # Turn back to private when ready
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(libvec_bin src/main.c)
|
add_executable(libvec_bin src/main.c)
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ LLVM_PROFDATA := $(LLVM_DIR)/llvm-profdata
|
|||||||
LLVM_COV := $(LLVM_DIR)/llvm-cov
|
LLVM_COV := $(LLVM_DIR)/llvm-cov
|
||||||
CPPCHECK := cppcheck
|
CPPCHECK := cppcheck
|
||||||
|
|
||||||
|
# libstr is populated by CMake's FetchContent (run `cmake -B build` once)
|
||||||
|
LIBSTR_DIR := build/_deps/libstr-src
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Flags & Directories
|
# Flags & Directories
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
@@ -14,7 +17,7 @@ CFLAGS := -std=c23 -Wall -Wextra -Wpedantic -Wshadow \
|
|||||||
-Wconversion -Wsign-conversion \
|
-Wconversion -Wsign-conversion \
|
||||||
-g -O1 -fno-omit-frame-pointer
|
-g -O1 -fno-omit-frame-pointer
|
||||||
SAN_FLAGS := -fsanitize=address,undefined
|
SAN_FLAGS := -fsanitize=address,undefined
|
||||||
INCLUDES := -Iinclude -Isrc/lib -Isrc/lib/char -Isrc/lib/utils
|
INCLUDES := -Iinclude -Isrc/lib -Isrc/lib/int -Isrc/lib/utils
|
||||||
|
|
||||||
ASAN_ENV := ASAN_OPTIONS="allocator_may_return_null=1:detect_stack_use_after_return=1" \
|
ASAN_ENV := ASAN_OPTIONS="allocator_may_return_null=1:detect_stack_use_after_return=1" \
|
||||||
UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1"
|
UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1"
|
||||||
@@ -31,10 +34,13 @@ CPPCHECK_FLAGS := --enable=all \
|
|||||||
$(INCLUDES)
|
$(INCLUDES)
|
||||||
|
|
||||||
# Sources & Build Directories
|
# Sources & Build Directories
|
||||||
SRCS := src/lib/char/char.c src/lib/utils/utils.c
|
SRCS := src/lib/int/int.c src/lib/utils/utils.c
|
||||||
TEST_SRC := tests/test_learn.c
|
TEST_SRC := tests/test_learn.c
|
||||||
FUZZ_SRC := tests/fuzz_char.c
|
FUZZ_SRC := tests/fuzz_char.c
|
||||||
|
|
||||||
|
STRING_SRCS := src/string.c src/utils.c $(LIBSTR_DIR)/src/string.c
|
||||||
|
TEST_STRING_SRC := tests/test_string.c
|
||||||
|
|
||||||
BIN_DIR := tests/bin
|
BIN_DIR := tests/bin
|
||||||
CACHE_DIR := tests/cache
|
CACHE_DIR := tests/cache
|
||||||
|
|
||||||
@@ -42,11 +48,12 @@ TEST_BIN := $(BIN_DIR)/test_learn_runner
|
|||||||
TSAN_BIN := $(BIN_DIR)/test_tsan_runner
|
TSAN_BIN := $(BIN_DIR)/test_tsan_runner
|
||||||
FUZZ_BIN := $(BIN_DIR)/fuzz_char_runner
|
FUZZ_BIN := $(BIN_DIR)/fuzz_char_runner
|
||||||
COV_BIN := $(BIN_DIR)/test_cov_runner
|
COV_BIN := $(BIN_DIR)/test_cov_runner
|
||||||
|
TEST_STRING_BIN := $(BIN_DIR)/test_string_runner
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Targets & Workflow Rules
|
# Targets & Workflow Rules
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
.PHONY: all test sanitize check check-sources analyze cppcheck fuzz cov-build cov clean
|
.PHONY: all test test-string sanitize check check-sources analyze cppcheck fuzz cov-build cov clean
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
@@ -58,6 +65,9 @@ $(BIN_DIR) $(CACHE_DIR):
|
|||||||
$(TEST_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
$(TEST_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||||
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) $^ -o $@
|
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) $^ -o $@
|
||||||
|
|
||||||
|
$(TEST_STRING_BIN): $(STRING_SRCS) $(TEST_STRING_SRC) | $(BIN_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -I$(LIBSTR_DIR)/include $^ -o $@
|
||||||
|
|
||||||
$(TSAN_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
$(TSAN_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||||
$(CC) $(CFLAGS) -fsanitize=thread $(INCLUDES) $^ -o $@
|
$(CC) $(CFLAGS) -fsanitize=thread $(INCLUDES) $^ -o $@
|
||||||
|
|
||||||
@@ -70,6 +80,10 @@ test: $(TEST_BIN)
|
|||||||
@echo "=== Running Unit Tests (ASan + UBSan) ==="
|
@echo "=== Running Unit Tests (ASan + UBSan) ==="
|
||||||
@$(ASAN_ENV) ./$(TEST_BIN)
|
@$(ASAN_ENV) ./$(TEST_BIN)
|
||||||
|
|
||||||
|
test-string: $(TEST_STRING_BIN)
|
||||||
|
@echo "=== Running vec_string Unit Tests (ASan + UBSan) ==="
|
||||||
|
@$(ASAN_ENV) ./$(TEST_STRING_BIN)
|
||||||
|
|
||||||
sanitize: $(TEST_BIN) $(TSAN_BIN)
|
sanitize: $(TEST_BIN) $(TSAN_BIN)
|
||||||
@echo "\n=== [1/2] Running Address + UndefinedBehavior Sanitizers ==="
|
@echo "\n=== [1/2] Running Address + UndefinedBehavior Sanitizers ==="
|
||||||
@$(ASAN_ENV) ./$(TEST_BIN)
|
@$(ASAN_ENV) ./$(TEST_BIN)
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef LIBVEC_H
|
|
||||||
#define LIBVEC_H
|
|
||||||
|
|
||||||
// Add code here
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
#ifndef LIBVEC_CHAR_H
|
||||||
|
#define LIBVEC_CHAR_H
|
||||||
|
|
||||||
|
#include <libvec/utils.h>
|
||||||
|
|
||||||
|
// Will add DOCS later
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* array;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
size_t max_size;
|
||||||
|
} vec_char;
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_char* ptr, err_t* status);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const char* ptr, err_t* status);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
__origin_override(err_t* status, char* str);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_print_vec(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
vec_char
|
||||||
|
vec_char_cpy(const char* src, const size_t src_size, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_push_back(vec_char* ptr, const char val, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_pop_back(vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_reserve(vec_char* ptr, const size_t capacity, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_shrink_to_fit(vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_swap(vec_char* ptr_a, vec_char* ptr_b, err_t* err);
|
||||||
|
|
||||||
|
const char*
|
||||||
|
vec_char_data(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_size(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_capacity(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_max_size(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_delete(vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_clear(vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
char*
|
||||||
|
vec_char_at(const vec_char* ptr, const size_t idx, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_begin(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_end(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
char
|
||||||
|
vec_char_front(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
char
|
||||||
|
vec_char_back(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_empty(const vec_char* ptr, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_erase(vec_char* ptr, const size_t iter, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_erase(vec_char* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_resize(vec_char* ptr, const size_t size, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_resize(vec_char* ptr, const size_t size, const char val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_assign(vec_char* ptr, const vec_char* iterator,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_assign(vec_char* ptr, const size_t amount, const char val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const size_t iter, const char val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const size_t iter, const size_t amount,
|
||||||
|
const char val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const vec_char* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef LIBVEC_FLOAT_H
|
||||||
|
#define LIBVEC_FLOAT_H
|
||||||
|
|
||||||
|
#include <libvec/utils.h>
|
||||||
|
|
||||||
|
// Will add DOCS later
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float* array;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
size_t max_size;
|
||||||
|
} vec_float;
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_print_vec(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
vec_float
|
||||||
|
vec_float_cpy(const float* src, const size_t src_size, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_push_back(vec_float* ptr, const float val, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_pop_back(vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_reserve(vec_float* ptr, const size_t capacity, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_shrink_to_fit(vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_swap(vec_float* ptr_a, vec_float* ptr_b, err_t* err);
|
||||||
|
|
||||||
|
const float*
|
||||||
|
vec_float_data(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_size(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_capacity(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_max_size(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_delete(vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_clear(vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
float*
|
||||||
|
vec_float_at(const vec_float* ptr, const size_t idx, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_begin(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_end(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
float
|
||||||
|
vec_float_front(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
float
|
||||||
|
vec_float_back(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_empty(const vec_float* ptr, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_erase(vec_float* ptr, const size_t iter, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_erase(vec_float* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_resize(vec_float* ptr, const size_t size, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_resize(vec_float* ptr, const size_t size, const float val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_assign(vec_float* ptr, const vec_float* iterator,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_assign(vec_float* ptr, const size_t amount, const float val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const size_t iter, const float val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const size_t iter, const size_t amount,
|
||||||
|
const float val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const vec_float* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
#ifndef LIBVEC_INT_H
|
||||||
|
#define LIBVEC_INT_H
|
||||||
|
|
||||||
|
#include <libvec/utils.h>
|
||||||
|
|
||||||
|
// Will add DOCS later
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int* array;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
size_t max_size;
|
||||||
|
} vec_int;
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_int* ptr, err_t* status);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const int* ptr, err_t* status);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
__origin_override(err_t* status, char* str);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_print_vec(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
vec_int
|
||||||
|
vec_int_cpy(const int* src, const size_t src_size, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_push_back(vec_int* ptr, const int val, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_pop_back(vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_reserve(vec_int* ptr, const size_t capacity, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_shrink_to_fit(vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_swap(vec_int* ptr_a, vec_int* ptr_b, err_t* err);
|
||||||
|
|
||||||
|
const int*
|
||||||
|
vec_int_data(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_size(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_capacity(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_max_size(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_delete(vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_clear(vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
int*
|
||||||
|
vec_int_at(const vec_int* ptr, const size_t idx, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_begin(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_end(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
int
|
||||||
|
vec_int_front(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
int
|
||||||
|
vec_int_back(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_empty(const vec_int* ptr, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_erase(vec_int* ptr, const size_t iter, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_erase(vec_int* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_resize(vec_int* ptr, const size_t size, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_resize(vec_int* ptr, const size_t size, const int val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_assign(vec_int* ptr, const vec_int* iterator, const size_t iter_start,
|
||||||
|
const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_assign(vec_int* ptr, const size_t amount, const int val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const size_t iter, const int val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const size_t iter, const size_t amount,
|
||||||
|
const int val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const vec_int* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#ifndef LIBVEC_STRING_H
|
||||||
|
#define LIBVEC_STRING_H
|
||||||
|
|
||||||
|
#include <libstr/string.h>
|
||||||
|
#include <libvec/utils.h>
|
||||||
|
|
||||||
|
// Will add DOCS later
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
String* array;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
size_t max_size;
|
||||||
|
} vec_string;
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_string* ptr, err_t* status);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const char* ptr, err_t* status);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_print_vec(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
vec_string
|
||||||
|
vec_string_cpy(const String* src, const size_t src_size, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_push_back(vec_string* ptr, const String val, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_pop_back(vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_reserve(vec_string* ptr, const size_t capacity, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_shrink_to_fit(vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_swap(vec_string* ptr_a, vec_string* ptr_b, err_t* err);
|
||||||
|
|
||||||
|
const String*
|
||||||
|
vec_string_data(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_size(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_capacity(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_max_size(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_delete(vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_clear(vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
String*
|
||||||
|
vec_string_at(const vec_string* ptr, const size_t idx, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_begin(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_end(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
String
|
||||||
|
vec_string_front(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
String
|
||||||
|
vec_string_back(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_empty(const vec_string* ptr, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_erase(vec_string* ptr, const size_t iter, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_erase(vec_string* ptr, const size_t iter_start,
|
||||||
|
const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_resize(vec_string* ptr, const size_t size, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_resize(vec_string* ptr, const size_t size, const String val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_assign(vec_string* ptr, const vec_string* iterator,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_assign(vec_string* ptr, const size_t amount, const String val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_insert(vec_string* ptr, const size_t iter, const String val,
|
||||||
|
err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_insert(vec_string* ptr, const size_t iter, const size_t amount,
|
||||||
|
const String val, err_t* err);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_insert(vec_string* ptr, const vec_string* iterator,
|
||||||
|
const size_t iter, const size_t iter_start,
|
||||||
|
const size_t iter_end, err_t* err);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define CAPACITY 1024
|
|
||||||
#define VEC_FAULT_BITS 32
|
|
||||||
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
||||||
|
|
||||||
#define ERROR_LIST(X) \
|
#define ERROR_LIST(X) \
|
||||||
@@ -46,22 +44,22 @@ typedef struct
|
|||||||
|
|
||||||
#define ERR_T_INIT { .flags = 0, .origin = NULL }
|
#define ERR_T_INIT { .flags = 0, .origin = NULL }
|
||||||
#define VEC_INIT \
|
#define VEC_INIT \
|
||||||
{ ._internal_arr = NULL, \
|
{ .array = NULL, .size = 0, .capacity = 0, .max_size = VEC_MAX }
|
||||||
._internal_size = 0, \
|
|
||||||
._internal_capacity = 0, \
|
|
||||||
._internal_max_size = VEC_MAX }
|
|
||||||
|
|
||||||
const char*
|
|
||||||
vec_get_error_desc(ERROR_CODES err);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vec_print_errs(const err_t err);
|
vec_print_errs(const err_t err);
|
||||||
|
|
||||||
void
|
void
|
||||||
print_bits(unsigned int num);
|
vec_print_bits(unsigned int num);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
__origin_override(err_t* status, char* str);
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const float* ptr, err_t* status);
|
||||||
|
|
||||||
#define LOG(msg) printf("LOG: %s\n", msg) /**< Print log message*/
|
#define LOG(msg) printf("LOG: %s\n", msg) /**< Print log message*/
|
||||||
#define DEBUG(msg) printf("DEBUG: %s\n", msg) /**< Print debug message*/
|
#define DEBUG(msg) printf("DEBUG: %s\n", msg) /**< Print debug message*/
|
||||||
#define find_len(arr) sizeof(arr) / sizeof(arr[0])
|
#define find_len(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Vendored
BIN
Binary file not shown.
+891
@@ -0,0 +1,891 @@
|
|||||||
|
#include <libvec/char.h>
|
||||||
|
#include <libvec/utils.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_char* ptr, err_t* status)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_VEC_NULL;
|
||||||
|
return ERR_VEC_NULL;
|
||||||
|
}
|
||||||
|
if (ptr->array == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_BUF_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_print_vec(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
printf("%c ", ptr->array[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_char
|
||||||
|
vec_char_cpy(const char* src, const size_t src_size, err_t* err)
|
||||||
|
{
|
||||||
|
vec_char self = VEC_INIT;
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
|
||||||
|
size_t null = __null_check(src, err);
|
||||||
|
if (null != 0)
|
||||||
|
{
|
||||||
|
if (null & ERR_ERR_T_NULL)
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size > self.max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.array = malloc(src_size * sizeof(char));
|
||||||
|
if (self.array == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
memcpy(self.array, src, src_size * sizeof(char));
|
||||||
|
self.size = src_size;
|
||||||
|
self.capacity = src_size;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_push_back(vec_char* ptr, const char val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
char* res;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size + 1 > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
res = malloc(1 * sizeof(char));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ptr->size + 1 > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||||
|
if (dst_cap == ptr->capacity)
|
||||||
|
{
|
||||||
|
dst_cap++;
|
||||||
|
}
|
||||||
|
if (dst_cap > ptr->max_size)
|
||||||
|
{
|
||||||
|
dst_cap = ptr->max_size;
|
||||||
|
DEBUG(
|
||||||
|
"Capacity cannot be grown any further due "
|
||||||
|
"to hitting max size");
|
||||||
|
}
|
||||||
|
res = realloc(ptr->array, dst_cap * sizeof(char));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = dst_cap;
|
||||||
|
}
|
||||||
|
ptr->array[ptr->size] = val;
|
||||||
|
ptr->size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_pop_back(vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_reserve(vec_char* ptr, const size_t capacity, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->max_size < capacity)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (capacity == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* res = realloc(ptr->array, capacity * sizeof(char));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = capacity;
|
||||||
|
if (ptr->size > capacity)
|
||||||
|
{
|
||||||
|
ptr->size = capacity;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_shrink_to_fit(vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_reserve(ptr, ptr->size, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_swap(vec_char* ptr_a, vec_char* ptr_b, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||||
|
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||||
|
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SWAP");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char self = *ptr_a;
|
||||||
|
*ptr_a = *ptr_b;
|
||||||
|
*ptr_b = self;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
vec_char_data(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DATA");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_size(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_capacity(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CAPACITY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_max_size(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "MAX_SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_delete(vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DELETE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array != nullptr)
|
||||||
|
{
|
||||||
|
free(ptr->array);
|
||||||
|
ptr->array = nullptr;
|
||||||
|
}
|
||||||
|
ptr->size = 0;
|
||||||
|
ptr->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_char_clear(vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CLEAR");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size > 0)
|
||||||
|
{
|
||||||
|
memset(ptr->array, 0, ptr->size);
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
vec_char_at(const vec_char* ptr, const size_t idx, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (idx >= ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_begin(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BEGIN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_end(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return (size_t)(ptr->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
vec_char_front(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "FRONT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_char_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_char_at(ptr, 0, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
vec_char_back(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BACK");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_char_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_char_at(ptr, ptr->size - 1, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_char_empty(const vec_char* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "EMPTY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_erase(vec_char* ptr, const size_t iter, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter >= ptr->size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||||
|
(ptr->size - iter - 1) * sizeof(char));
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_erase(vec_char* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t diff = iter_end - iter_start;
|
||||||
|
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||||
|
(ptr->size - iter_end) * sizeof(char));
|
||||||
|
memset(&ptr->array[ptr->size - diff], 0, sizeof(char) * diff);
|
||||||
|
ptr->size -= diff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_resize(vec_char* ptr, const size_t size, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_char_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = 0;
|
||||||
|
}
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_char_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != tmpcp)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[size], 0, ptr->size - size);
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[ptr->size], 0, size - ptr->size);
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_resize(vec_char* ptr, const size_t size, const char val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_char_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = val;
|
||||||
|
}
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_char_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[size], val, ptr->size - size);
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[ptr->size], val, size - ptr->size);
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_assign(vec_char* ptr, const vec_char* iterator,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0 ||
|
||||||
|
__null_check(iterator, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_erase(ptr, vec_char_begin(ptr, &status),
|
||||||
|
vec_char_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_reserve(ptr, (iter_end - iter_start), &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
char* res = vec_char_at(iterator, i, &status);
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_push_back(ptr, *res, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_assign(vec_char* ptr, const size_t amount, const char val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_erase(ptr, vec_char_begin(ptr, &status),
|
||||||
|
vec_char_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_reserve(ptr, amount, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
vec_char_push_back(ptr, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const size_t iter, const char val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
char* res = malloc(1 * sizeof(char));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_BUF_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->array[0] = val;
|
||||||
|
ptr->size = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->max_size < ptr->size + 1)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_char_push_back(ptr, 0, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||||
|
{
|
||||||
|
ptr->array[i] = ptr->array[i - 1];
|
||||||
|
}
|
||||||
|
ptr->array[iter] = val;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const size_t iter, const size_t amount,
|
||||||
|
const char val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter; i < iter + amount; i++)
|
||||||
|
{
|
||||||
|
vec_char_insert(ptr, i, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_char_insert(vec_char* ptr, const vec_char* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
__null_check(iterator, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||||
|
iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
vec_char_insert(ptr, iter + (i - iter_start),
|
||||||
|
iterator->array[i], &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
+891
@@ -0,0 +1,891 @@
|
|||||||
|
#include <libvec/float.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_float* ptr, err_t* status)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_VEC_NULL;
|
||||||
|
return ERR_VEC_NULL;
|
||||||
|
}
|
||||||
|
if (ptr->array == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_BUF_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_print_vec(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
printf("%f ", ptr->array[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_float
|
||||||
|
vec_float_cpy(const float* src, const size_t src_size, err_t* err)
|
||||||
|
{
|
||||||
|
vec_float self = VEC_INIT;
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
|
||||||
|
size_t null = __null_check(src, err);
|
||||||
|
if (null != 0)
|
||||||
|
{
|
||||||
|
if (null & ERR_ERR_T_NULL)
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size > self.max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.array = malloc(src_size * sizeof(float));
|
||||||
|
if (self.array == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
memcpy(self.array, src, src_size * sizeof(float));
|
||||||
|
self.size = src_size;
|
||||||
|
self.capacity = src_size;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_push_back(vec_float* ptr, const float val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
float* res;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size + 1 > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
res = malloc(1 * sizeof(float));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ptr->size + 1 > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||||
|
if (dst_cap == ptr->capacity)
|
||||||
|
{
|
||||||
|
dst_cap++;
|
||||||
|
}
|
||||||
|
if (dst_cap > ptr->max_size)
|
||||||
|
{
|
||||||
|
dst_cap = ptr->max_size;
|
||||||
|
DEBUG(
|
||||||
|
"Capacity cannot be grown any further due "
|
||||||
|
"to hitting max size");
|
||||||
|
}
|
||||||
|
res = realloc(ptr->array, dst_cap * sizeof(float));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = dst_cap;
|
||||||
|
}
|
||||||
|
ptr->array[ptr->size] = val;
|
||||||
|
ptr->size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_pop_back(vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_reserve(vec_float* ptr, const size_t capacity, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->max_size < capacity)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (capacity == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float* res = realloc(ptr->array, capacity * sizeof(float));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = capacity;
|
||||||
|
if (ptr->size > capacity)
|
||||||
|
{
|
||||||
|
ptr->size = capacity;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_shrink_to_fit(vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_reserve(ptr, ptr->size, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_swap(vec_float* ptr_a, vec_float* ptr_b, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||||
|
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||||
|
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SWAP");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float self = *ptr_a;
|
||||||
|
*ptr_a = *ptr_b;
|
||||||
|
*ptr_b = self;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float*
|
||||||
|
vec_float_data(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DATA");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_size(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_capacity(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CAPACITY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_max_size(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "MAX_SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_delete(vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DELETE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array != nullptr)
|
||||||
|
{
|
||||||
|
free(ptr->array);
|
||||||
|
ptr->array = nullptr;
|
||||||
|
}
|
||||||
|
ptr->size = 0;
|
||||||
|
ptr->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_float_clear(vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CLEAR");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size > 0)
|
||||||
|
{
|
||||||
|
memset(ptr->array, 0, ptr->size);
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float*
|
||||||
|
vec_float_at(const vec_float* ptr, const size_t idx, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (idx >= ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_begin(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BEGIN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_end(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return (size_t)(ptr->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
vec_float_front(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "FRONT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_float_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_float_at(ptr, 0, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
vec_float_back(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BACK");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_float_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_float_at(ptr, ptr->size - 1, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_float_empty(const vec_float* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "EMPTY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_erase(vec_float* ptr, const size_t iter, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter >= ptr->size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||||
|
(ptr->size - iter - 1) * sizeof(float));
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_erase(vec_float* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t diff = iter_end - iter_start;
|
||||||
|
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||||
|
(ptr->size - iter_end) * sizeof(float));
|
||||||
|
memset(&ptr->array[ptr->size - diff], 0, sizeof(float) * diff);
|
||||||
|
ptr->size -= diff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_resize(vec_float* ptr, const size_t size, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_float_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = 0;
|
||||||
|
}
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_float_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != tmpcp)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[size], 0, ptr->size - size);
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[ptr->size], 0, size - ptr->size);
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_resize(vec_float* ptr, const size_t size, const float val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_float_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = val;
|
||||||
|
}
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_float_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[size], val, ptr->size - size);
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[ptr->size], val, size - ptr->size);
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_assign(vec_float* ptr, const vec_float* iterator,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0 ||
|
||||||
|
__null_check(iterator, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_erase(ptr, vec_float_begin(ptr, &status),
|
||||||
|
vec_float_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_reserve(ptr, (iter_end - iter_start), &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
float* res = vec_float_at(iterator, i, &status);
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_push_back(ptr, *res, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_assign(vec_float* ptr, const size_t amount, const float val,
|
||||||
|
err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_erase(ptr, vec_float_begin(ptr, &status),
|
||||||
|
vec_float_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_reserve(ptr, amount, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
vec_float_push_back(ptr, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const size_t iter, const float val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
float* res = malloc(1 * sizeof(float));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_BUF_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->array[0] = val;
|
||||||
|
ptr->size = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->max_size < ptr->size + 1)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_float_push_back(ptr, 0, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||||
|
{
|
||||||
|
ptr->array[i] = ptr->array[i - 1];
|
||||||
|
}
|
||||||
|
ptr->array[iter] = val;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const size_t iter, const size_t amount,
|
||||||
|
const float val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter; i < iter + amount; i++)
|
||||||
|
{
|
||||||
|
vec_float_insert(ptr, i, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_float_insert(vec_float* ptr, const vec_float* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
__null_check(iterator, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||||
|
iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
vec_float_insert(ptr, iter + (i - iter_start),
|
||||||
|
iterator->array[i], &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
@@ -0,0 +1,894 @@
|
|||||||
|
#include <libvec/int.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const vec_int* ptr, err_t* status)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_VEC_NULL;
|
||||||
|
return ERR_VEC_NULL;
|
||||||
|
}
|
||||||
|
if (ptr->array == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_BUF_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_print_vec(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
printf("%d ", ptr->array[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_int
|
||||||
|
vec_int_cpy(const int* src, const size_t src_size, err_t* err)
|
||||||
|
{
|
||||||
|
vec_int self = VEC_INIT;
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
|
||||||
|
size_t null = __null_check(src, err);
|
||||||
|
if (null != 0)
|
||||||
|
{
|
||||||
|
if (null & ERR_ERR_T_NULL)
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if (src_size > self.max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.array = malloc(src_size * sizeof(int));
|
||||||
|
if (self.array == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
memcpy(self.array, src, src_size * sizeof(int));
|
||||||
|
self.size = src_size;
|
||||||
|
self.capacity = src_size;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_push_back(vec_int* ptr, const int val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
int* res;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size + 1 > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
res = malloc(1 * sizeof(int));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ptr->size + 1 > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||||
|
if (dst_cap == ptr->capacity)
|
||||||
|
{
|
||||||
|
dst_cap++;
|
||||||
|
}
|
||||||
|
if (dst_cap > ptr->max_size)
|
||||||
|
{
|
||||||
|
dst_cap = ptr->max_size;
|
||||||
|
DEBUG(
|
||||||
|
"Capacity cannot be grown any further due "
|
||||||
|
"to hitting max size");
|
||||||
|
}
|
||||||
|
res = realloc(ptr->array, dst_cap * sizeof(int));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "PUSH_BACK");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = dst_cap;
|
||||||
|
}
|
||||||
|
ptr->array[ptr->size] = val;
|
||||||
|
ptr->size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_pop_back(vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "POP_BACK");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_reserve(vec_int* ptr, const size_t capacity, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->max_size < capacity)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (capacity == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int* res = realloc(ptr->array, capacity * sizeof(int));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESERVE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = capacity;
|
||||||
|
if (ptr->size > capacity)
|
||||||
|
{
|
||||||
|
ptr->size = capacity;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_shrink_to_fit(vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SHRINK_TO_FIT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_reserve(ptr, ptr->size, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_swap(vec_int* ptr_a, vec_int* ptr_b, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||||
|
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||||
|
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SWAP");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int self = *ptr_a;
|
||||||
|
*ptr_a = *ptr_b;
|
||||||
|
*ptr_b = self;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int*
|
||||||
|
vec_int_data(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DATA");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_size(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_capacity(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CAPACITY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_max_size(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "MAX_SIZE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ptr->max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_delete(vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "DELETE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array != nullptr)
|
||||||
|
{
|
||||||
|
free(ptr->array);
|
||||||
|
ptr->array = nullptr;
|
||||||
|
}
|
||||||
|
ptr->size = 0;
|
||||||
|
ptr->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_int_clear(vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CLEAR");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size > 0)
|
||||||
|
{
|
||||||
|
memset(ptr->array, 0, ptr->size * sizeof(int));
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int*
|
||||||
|
vec_int_at(const vec_int* ptr, const size_t idx, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (idx >= ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "AT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &ptr->array[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_begin(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BEGIN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_end(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "END");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
return (size_t)(ptr->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vec_int_front(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "FRONT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_int_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_int_at(ptr, 0, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vec_int_back(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "BACK");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vec_int_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *vec_int_at(ptr, ptr->size - 1, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_int_empty(const vec_int* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "EMPTY");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
if (ptr->size == 0)
|
||||||
|
{
|
||||||
|
return ptr->size;
|
||||||
|
}
|
||||||
|
return status.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_erase(vec_int* ptr, const size_t iter, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter >= ptr->size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||||
|
(ptr->size - iter - 1) * sizeof(int));
|
||||||
|
ptr->array[ptr->size - 1] = 0;
|
||||||
|
ptr->size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_erase(vec_int* ptr, const size_t iter_start, const size_t iter_end,
|
||||||
|
err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t diff = iter_end - iter_start;
|
||||||
|
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||||
|
(ptr->size - iter_end) * sizeof(int));
|
||||||
|
memset(&ptr->array[ptr->size - diff], 0, sizeof(int) * diff);
|
||||||
|
ptr->size -= diff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_resize(vec_int* ptr, const size_t size, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_int_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(ptr->array, 0, size * sizeof(int));
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_int_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != tmpcp)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[size], 0, (ptr->size - size) * sizeof(int));
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
memset(&ptr->array[ptr->size], 0,
|
||||||
|
(size - ptr->size) * sizeof(int));
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_resize(vec_int* ptr, const size_t size, const int val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_VEC_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->size == size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (size > ptr->max_size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||||
|
{
|
||||||
|
size_t max = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
vec_int_reserve(ptr, size, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->capacity != size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = val;
|
||||||
|
}
|
||||||
|
ptr->max_size = max;
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (size > ptr->capacity)
|
||||||
|
{
|
||||||
|
size_t tmpcp = ptr->capacity;
|
||||||
|
size_t tmpmx = ptr->max_size;
|
||||||
|
err_t verr = ERR_T_INIT;
|
||||||
|
while (size > tmpcp)
|
||||||
|
{
|
||||||
|
tmpcp *= 2;
|
||||||
|
}
|
||||||
|
if (tmpcp > ptr->max_size)
|
||||||
|
{
|
||||||
|
tmpcp = size;
|
||||||
|
}
|
||||||
|
vec_int_reserve(ptr, tmpcp, &verr);
|
||||||
|
if (verr.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "RESIZE");
|
||||||
|
err->flags |= verr.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->max_size = tmpmx;
|
||||||
|
}
|
||||||
|
if (size < ptr->size)
|
||||||
|
{
|
||||||
|
for (size_t i = size; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
for (size_t i = ptr->size; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_assign(vec_int* ptr, const vec_int* iterator, const size_t iter_start,
|
||||||
|
const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0 ||
|
||||||
|
__null_check(iterator, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_erase(ptr, vec_int_begin(ptr, &status),
|
||||||
|
vec_int_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_reserve(ptr, (iter_end - iter_start), &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
int* res = vec_int_at(iterator, i, &status);
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_push_back(ptr, *res, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_assign(vec_int* ptr, const size_t amount, const int val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_erase(ptr, vec_int_begin(ptr, &status),
|
||||||
|
vec_int_end(ptr, &status) + 1, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_reserve(ptr, amount, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
vec_int_push_back(ptr, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const size_t iter, const int val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||||
|
{
|
||||||
|
int* res = malloc(1 * sizeof(int));
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_BUF_NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr->array = res;
|
||||||
|
ptr->capacity = 1;
|
||||||
|
ptr->array[0] = val;
|
||||||
|
ptr->size = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->max_size < ptr->size + 1)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_OVERFLOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_int_push_back(ptr, 0, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||||
|
{
|
||||||
|
ptr->array[i] = ptr->array[i - 1];
|
||||||
|
}
|
||||||
|
ptr->array[iter] = val;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const size_t iter, const size_t amount,
|
||||||
|
const int val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amount == 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_SIZE_ZERO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter; i < iter + amount; i++)
|
||||||
|
{
|
||||||
|
vec_int_insert(ptr, i, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_int_insert(vec_int* ptr, const vec_int* iterator, const size_t iter,
|
||||||
|
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
__null_check(ptr, &status);
|
||||||
|
__null_check(iterator, &status);
|
||||||
|
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||||
|
iter > ptr->size)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ptr->array == iterator->array)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= ERR_DOUBLE_BUF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = iter_start; i < iter_end; i++)
|
||||||
|
{
|
||||||
|
vec_int_insert(ptr, iter + (i - iter_start), iterator->array[i],
|
||||||
|
&status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
Vendored
BIN
Binary file not shown.
@@ -1,117 +0,0 @@
|
|||||||
#ifndef CHAR_H
|
|
||||||
#define CHAR_H
|
|
||||||
|
|
||||||
#include <utils/utils.h>
|
|
||||||
|
|
||||||
// Will add DOCS later
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char* _internal_arr;
|
|
||||||
size_t _internal_size;
|
|
||||||
size_t _internal_capacity;
|
|
||||||
size_t _internal_max_size;
|
|
||||||
} _VecCharInternal;
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
__null_check(const _VecCharInternal* ptr, err_t* status);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
__null_check(const char* ptr, err_t* status);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
__origin_override(err_t* status, char* str);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_print_vec(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
_VecCharInternal
|
|
||||||
_vec_char_cpy(const char* src, const size_t src_size, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_push_back(_VecCharInternal* ptr, const char val, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_pop_back(_VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_reserve(_VecCharInternal* ptr, const size_t capacity, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_shrink_to_fit(_VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_swap(_VecCharInternal* ptr_a, _VecCharInternal* ptr_b, err_t* err);
|
|
||||||
|
|
||||||
const char*
|
|
||||||
_vec_char_data(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_size(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_capacity(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_max_size(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_delete(_VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_clear(_VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
char*
|
|
||||||
_vec_char_at(const _VecCharInternal* ptr, const size_t idx, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_begin(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_end(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
char
|
|
||||||
_vec_char_front(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
char
|
|
||||||
_vec_char_back(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_empty(const _VecCharInternal* ptr, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_erase(_VecCharInternal* ptr, const size_t iter, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_erase(_VecCharInternal* ptr, const size_t iter_start,
|
|
||||||
const size_t iter_end, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_resize(_VecCharInternal* ptr, const size_t size, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_resize(_VecCharInternal* ptr, const size_t size, const char val,
|
|
||||||
err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_assign(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_assign(_VecCharInternal* ptr, const size_t amount, const char val,
|
|
||||||
err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const size_t iter, const char val,
|
|
||||||
err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const size_t iter, const size_t amount,
|
|
||||||
const char val, err_t* err);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) void
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
const size_t iter, const size_t iter_start,
|
|
||||||
const size_t iter_end, err_t* err);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <utils/utils.h>
|
|
||||||
|
|
||||||
const char*
|
|
||||||
vec_get_error_desc(ERROR_CODES err)
|
|
||||||
{
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
#define X(name, val, desc) \
|
|
||||||
case name: \
|
|
||||||
return desc;
|
|
||||||
ERROR_LIST(X)
|
|
||||||
#undef X
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
vec_print_errs(const err_t err)
|
|
||||||
{
|
|
||||||
if (err.flags == SUCCESS)
|
|
||||||
{
|
|
||||||
printf("%s: %s\n", err.origin, vec_get_error_desc(SUCCESS));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
#define X(name, val, desc) \
|
|
||||||
if ((val) != 0 && ((err.flags) & (val))) \
|
|
||||||
{ \
|
|
||||||
printf("%s\n", vec_get_error_desc(name)); \
|
|
||||||
}
|
|
||||||
ERROR_LIST(X)
|
|
||||||
#undef X
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_bits(unsigned int num)
|
|
||||||
{
|
|
||||||
// Determine the number of bits in an unsigned int (usually 32)
|
|
||||||
int total_bits = sizeof(num) * 8;
|
|
||||||
|
|
||||||
// Loop from the most significant bit (MSB) down to the least
|
|
||||||
// significant bit (LSB)
|
|
||||||
for (int i = total_bits - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
// Shift a 1 to the i-th position and check if that bit is set
|
|
||||||
int bit = (num >> i) & 1;
|
|
||||||
printf("%d", bit);
|
|
||||||
|
|
||||||
// Optional: Add a space every 4 or 8 bits for readability
|
|
||||||
if (i % 8 == 0)
|
|
||||||
{
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// void
|
|
||||||
// _vec_update_origin(err_t* err, char* str)
|
|
||||||
// {
|
|
||||||
// err_t res;
|
|
||||||
// if (err == nullptr)
|
|
||||||
// {
|
|
||||||
// res.err = 0;
|
|
||||||
// res.value = 0;
|
|
||||||
// }
|
|
||||||
// if (!err->origin) err->origin = str;
|
|
||||||
// }
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include <libvec.h>
|
|
||||||
+5
-7
@@ -6,19 +6,15 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Types Wanted:
|
* Types Wanted:
|
||||||
* Char 8 Bits
|
|
||||||
* Float 32 Bits with suffix of 'f'
|
|
||||||
* Int 32 bits
|
|
||||||
* String 32 Bits with suffix of 's'
|
* String 32 Bits with suffix of 's'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libvec/utils.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "lib/utils/utils.h"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
print_bits(unsigned int num);
|
print_bits(unsigned int num);
|
||||||
|
|
||||||
@@ -26,6 +22,7 @@ int
|
|||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO:
|
||||||
|
//
|
||||||
// Fix the error checking because you make a status to hold all local
|
// Fix the error checking because you make a status to hold all local
|
||||||
// errors but then in some cases you or them to the main err handler and
|
// errors but then in some cases you or them to the main err handler and
|
||||||
// if the error doesnt need to be there like a good error but one that
|
// if the error doesnt need to be there like a good error but one that
|
||||||
@@ -41,7 +38,8 @@ main()
|
|||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
mask = ERR_BUF_NULL ^ status.flags;
|
mask = ERR_BUF_NULL ^ status.flags;
|
||||||
|
|
||||||
print_bits(mask);
|
vec_print_bits(mask);
|
||||||
print_bits(status.flags);
|
vec_print_bits(status.flags);
|
||||||
|
vec_print_errs(status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+214
-217
File diff suppressed because it is too large
Load Diff
+92
@@ -0,0 +1,92 @@
|
|||||||
|
#include <libvec/utils.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const char*
|
||||||
|
vec_get_error_desc(ERROR_CODES err)
|
||||||
|
{
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
#define X(name, val, desc) \
|
||||||
|
case name: \
|
||||||
|
return desc;
|
||||||
|
ERROR_LIST(X)
|
||||||
|
#undef X
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_print_errs(const err_t err)
|
||||||
|
{
|
||||||
|
if (err.flags == SUCCESS)
|
||||||
|
{
|
||||||
|
printf("%s: %s\n", err.origin, vec_get_error_desc(SUCCESS));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
#define X(name, val, desc) \
|
||||||
|
if ((val) != 0 && ((err.flags) & (val))) \
|
||||||
|
{ \
|
||||||
|
printf("%s\n", vec_get_error_desc(name)); \
|
||||||
|
}
|
||||||
|
ERROR_LIST(X)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_print_bits(unsigned int num)
|
||||||
|
{
|
||||||
|
unsigned int total_bits = sizeof(num) * 8;
|
||||||
|
|
||||||
|
for (unsigned int i = total_bits - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
unsigned int bit = (num >> i) & 1;
|
||||||
|
printf("%d ", bit);
|
||||||
|
|
||||||
|
if (i % 8 == 0)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
__origin_override(err_t* status, char* str)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (status->origin != nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_ORIGIN_UNALTERABLE;
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
else if (str == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_STR_NULL;
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status->origin = str;
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const char* ptr, err_t* status)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_BUF_NULL;
|
||||||
|
}
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
+192
-189
@@ -1,5 +1,5 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <char/char.h>
|
#include <int/int.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -23,15 +23,15 @@ __asan_default_options(void)
|
|||||||
static void
|
static void
|
||||||
test_push_back_single(void)
|
test_push_back_single(void)
|
||||||
{
|
{
|
||||||
printf("[1] Testing push_back with a single character...\n");
|
printf("[1] Testing push_back with a single integer...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'A', &err);
|
_vec_int_push_back(&vec, 65, &err);
|
||||||
|
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_size == 1);
|
assert(vec._internal_size == 1);
|
||||||
assert(vec._internal_arr[0] == 'A');
|
assert(vec._internal_arr[0] == 65);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,13 +39,13 @@ static void
|
|||||||
test_null_guards(void)
|
test_null_guards(void)
|
||||||
{
|
{
|
||||||
printf("[2] Testing null pointer checks in __null_check...\n");
|
printf("[2] Testing null pointer checks in __null_check...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
size_t res1 = __null_check(&vec, nullptr);
|
size_t res1 = __null_check(&vec, nullptr);
|
||||||
assert(res1 == ERR_ERR_T_NULL);
|
assert(res1 == ERR_ERR_T_NULL);
|
||||||
|
|
||||||
size_t res2 = __null_check((const _VecCharInternal*)nullptr, &err);
|
size_t res2 = __null_check((const _VecIntInternal*)nullptr, &err);
|
||||||
assert(res2 == ERR_VEC_NULL);
|
assert(res2 == ERR_VEC_NULL);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ test_null_guards(void)
|
|||||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
size_t res5 = __null_check((const char*)nullptr, nullptr);
|
size_t res5 = __null_check((const int*)nullptr, nullptr);
|
||||||
assert(res5 == ERR_ERR_T_NULL);
|
assert(res5 == ERR_ERR_T_NULL);
|
||||||
|
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
@@ -98,42 +98,42 @@ test_origin_override(void)
|
|||||||
static void
|
static void
|
||||||
test_print_vec(void)
|
test_print_vec(void)
|
||||||
{
|
{
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
printf("[4] Testing print_vec with null vector\n");
|
printf("[4] Testing print_vec with null vector\n");
|
||||||
_vec_char_print_vec(nullptr, &err);
|
_vec_int_print_vec(nullptr, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[5] Testing print_vec with null array\n");
|
printf("[5] Testing print_vec with null array\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_print_vec(&vec, &err);
|
_vec_int_print_vec(&vec, &err);
|
||||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[6] Testing print_vec with null err\n");
|
printf("[6] Testing print_vec with null err\n");
|
||||||
_vec_char_print_vec(&vec, nullptr);
|
_vec_int_print_vec(&vec, nullptr);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[7] Testing print_vec with valid parameters\n");
|
printf("[7] Testing print_vec with valid parameters\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'a', &err);
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
_vec_char_push_back(&vec, 'b', &err);
|
_vec_int_push_back(&vec, 2, &err);
|
||||||
_vec_char_print_vec(&vec, &err);
|
_vec_int_print_vec(&vec, &err);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_cpy(void)
|
test_cpy(void)
|
||||||
{
|
{
|
||||||
char arr[3] = { 'a', 'b', 'c' };
|
int arr[3] = { 1, 2, 3 };
|
||||||
_VecCharInternal blank = VEC_INIT;
|
_VecIntInternal blank = VEC_INIT;
|
||||||
|
|
||||||
printf("[8] Testing _vec_char_cpy with null source arr\n");
|
printf("[8] Testing _vec_int_cpy with null source arr\n");
|
||||||
err_t err1 = ERR_T_INIT;
|
err_t err1 = ERR_T_INIT;
|
||||||
_VecCharInternal tmp = _vec_char_cpy(nullptr, 3, &err1);
|
_VecIntInternal tmp = _vec_int_cpy(nullptr, 3, &err1);
|
||||||
assert(blank._internal_arr == tmp._internal_arr &&
|
assert(blank._internal_arr == tmp._internal_arr &&
|
||||||
blank._internal_capacity == tmp._internal_capacity &&
|
blank._internal_capacity == tmp._internal_capacity &&
|
||||||
blank._internal_size == tmp._internal_size &&
|
blank._internal_size == tmp._internal_size &&
|
||||||
@@ -141,17 +141,17 @@ test_cpy(void)
|
|||||||
assert((err1.flags & ERR_BUF_NULL) != 0);
|
assert((err1.flags & ERR_BUF_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[9] Testing _vec_char_cpy with null err\n");
|
printf("[9] Testing _vec_int_cpy with null err\n");
|
||||||
_VecCharInternal res2 = _vec_char_cpy(arr, 3, nullptr);
|
_VecIntInternal res2 = _vec_int_cpy(arr, 3, nullptr);
|
||||||
assert(blank._internal_arr == res2._internal_arr &&
|
assert(blank._internal_arr == res2._internal_arr &&
|
||||||
blank._internal_capacity == res2._internal_capacity &&
|
blank._internal_capacity == res2._internal_capacity &&
|
||||||
blank._internal_size == res2._internal_size &&
|
blank._internal_size == res2._internal_size &&
|
||||||
blank._internal_max_size == res2._internal_max_size);
|
blank._internal_max_size == res2._internal_max_size);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[10] Testing _vec_char_cpy with size 0\n");
|
printf("[10] Testing _vec_int_cpy with size 0\n");
|
||||||
err_t err3 = ERR_T_INIT;
|
err_t err3 = ERR_T_INIT;
|
||||||
_VecCharInternal res3 = _vec_char_cpy(arr, 0, &err3);
|
_VecIntInternal res3 = _vec_int_cpy(arr, 0, &err3);
|
||||||
assert(blank._internal_arr == res3._internal_arr &&
|
assert(blank._internal_arr == res3._internal_arr &&
|
||||||
blank._internal_capacity == res3._internal_capacity &&
|
blank._internal_capacity == res3._internal_capacity &&
|
||||||
blank._internal_size == res3._internal_size &&
|
blank._internal_size == res3._internal_size &&
|
||||||
@@ -159,10 +159,10 @@ test_cpy(void)
|
|||||||
assert((err3.flags & ERR_SIZE_ZERO) != 0);
|
assert((err3.flags & ERR_SIZE_ZERO) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[11] Testing _vec_char_cpy with size exceeding max_size\n");
|
printf("[11] Testing _vec_int_cpy with size exceeding max_size\n");
|
||||||
err_t err4 = ERR_T_INIT;
|
err_t err4 = ERR_T_INIT;
|
||||||
_VecCharInternal res4 =
|
_VecIntInternal res4 =
|
||||||
_vec_char_cpy(arr, res3._internal_max_size + 1, &err4);
|
_vec_int_cpy(arr, res3._internal_max_size + 1, &err4);
|
||||||
assert(blank._internal_arr == res4._internal_arr &&
|
assert(blank._internal_arr == res4._internal_arr &&
|
||||||
blank._internal_capacity == res4._internal_capacity &&
|
blank._internal_capacity == res4._internal_capacity &&
|
||||||
blank._internal_size == res4._internal_size &&
|
blank._internal_size == res4._internal_size &&
|
||||||
@@ -170,22 +170,23 @@ test_cpy(void)
|
|||||||
assert((err4.flags & ERR_SIZE_OVERFLOW) != 0);
|
assert((err4.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[12] Testing _vec_char_cpy allocation failure\n");
|
printf("[12] Testing _vec_int_cpy allocation failure\n");
|
||||||
err_t err5 = ERR_T_INIT;
|
err_t err5 = ERR_T_INIT;
|
||||||
size_t huge_size = ((size_t)1 << 40);
|
size_t huge_size = ((size_t)1 << 40);
|
||||||
_VecCharInternal res5 = _vec_char_cpy(arr, huge_size, &err5);
|
_VecIntInternal res5 = _vec_int_cpy(arr, huge_size, &err5);
|
||||||
|
assert(res5._internal_arr == blank._internal_arr);
|
||||||
assert((err5.flags & ERR_ALLOC_FAIL) != 0);
|
assert((err5.flags & ERR_ALLOC_FAIL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[13] Testing _vec_char_cpy with valid inputs\n");
|
printf("[13] Testing _vec_int_cpy with valid inputs\n");
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
char res[4] = { 'a', 'b', 'c', 'd' };
|
int res[4] = { 10, 20, 30, 40 };
|
||||||
_VecCharInternal vec = _vec_char_cpy(res, 4, &err);
|
_VecIntInternal vec = _vec_int_cpy(res, 4, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_size == 4);
|
assert(vec._internal_size == 4);
|
||||||
assert(vec._internal_capacity == 4);
|
assert(vec._internal_capacity == 4);
|
||||||
assert(memcmp(vec._internal_arr, res, 4) == 0);
|
assert(memcmp(vec._internal_arr, res, sizeof(int) * 4) == 0);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,151 +197,151 @@ test_cpy(void)
|
|||||||
static void
|
static void
|
||||||
test_push_back(void)
|
test_push_back(void)
|
||||||
{
|
{
|
||||||
printf("[14] Testing _vec_char_push_back null vec\n");
|
printf("[14] Testing _vec_int_push_back null vec\n");
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
_vec_char_push_back(nullptr, 'a', &err);
|
_vec_int_push_back(nullptr, 1, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[15] Testing _vec_char_push_back null err\n");
|
printf("[15] Testing _vec_int_push_back null err\n");
|
||||||
_VecCharInternal vec1 = VEC_INIT;
|
_VecIntInternal vec1 = VEC_INIT;
|
||||||
_vec_char_push_back(&vec1, 'a', nullptr);
|
_vec_int_push_back(&vec1, 1, nullptr);
|
||||||
assert(vec1._internal_size == 1);
|
assert(vec1._internal_size == 1);
|
||||||
_vec_char_delete(&vec1, &err);
|
_vec_int_delete(&vec1, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[16] Testing _vec_char_push_back size overflow\n");
|
printf("[16] Testing _vec_int_push_back size overflow\n");
|
||||||
_VecCharInternal vec2 = VEC_INIT;
|
_VecIntInternal vec2 = VEC_INIT;
|
||||||
err_t err2 = ERR_T_INIT;
|
err_t err2 = ERR_T_INIT;
|
||||||
vec2._internal_size = vec2._internal_max_size;
|
vec2._internal_size = vec2._internal_max_size;
|
||||||
_vec_char_push_back(&vec2, 'a', &err2);
|
_vec_int_push_back(&vec2, 1, &err2);
|
||||||
assert((err2.flags & ERR_SIZE_OVERFLOW) != 0);
|
assert((err2.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[17] Testing push_back capacity growth realloc\n");
|
printf("[17] Testing push_back capacity growth realloc\n");
|
||||||
err_t err3 = ERR_T_INIT;
|
err_t err3 = ERR_T_INIT;
|
||||||
_VecCharInternal vec3 = VEC_INIT;
|
_VecIntInternal vec3 = VEC_INIT;
|
||||||
for (char c = '0'; c <= '9'; c++)
|
for (int val = 0; val < 10; val++)
|
||||||
{
|
{
|
||||||
_vec_char_push_back(&vec3, c, &err3);
|
_vec_int_push_back(&vec3, val, &err3);
|
||||||
assert(err3.flags == 0);
|
assert(err3.flags == 0);
|
||||||
}
|
}
|
||||||
assert(vec3._internal_size == 10);
|
assert(vec3._internal_size == 10);
|
||||||
assert(vec3._internal_capacity >= 10);
|
assert(vec3._internal_capacity >= 10);
|
||||||
_vec_char_delete(&vec3, &err3);
|
_vec_int_delete(&vec3, &err3);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_pop_back(void)
|
test_pop_back(void)
|
||||||
{
|
{
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
printf("[18] Testing _vec_char_pop_back null vector\n");
|
printf("[18] Testing _vec_int_pop_back null vector\n");
|
||||||
_vec_char_pop_back(nullptr, &err);
|
_vec_int_pop_back(nullptr, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[19] Testing _vec_char_pop_back size 0\n");
|
printf("[19] Testing _vec_int_pop_back size 0\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'x', &err);
|
_vec_int_push_back(&vec, 42, &err);
|
||||||
_vec_char_pop_back(&vec,
|
_vec_int_pop_back(&vec,
|
||||||
&err); // size is now 0, but buffer is allocated
|
&err); // size is now 0, but buffer is allocated
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_pop_back(&vec, &err);
|
_vec_int_pop_back(&vec, &err);
|
||||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[20] Testing _vec_char_pop_back valid pop\n");
|
printf("[20] Testing _vec_int_pop_back valid pop\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'a', &err);
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
_vec_char_push_back(&vec, 'b', &err);
|
_vec_int_push_back(&vec, 2, &err);
|
||||||
assert(vec._internal_size == 2);
|
assert(vec._internal_size == 2);
|
||||||
_vec_char_pop_back(&vec, &err);
|
_vec_int_pop_back(&vec, &err);
|
||||||
assert(vec._internal_size == 1);
|
assert(vec._internal_size == 1);
|
||||||
assert(vec._internal_arr[0] == 'a');
|
assert(vec._internal_arr[0] == 1);
|
||||||
assert(vec._internal_arr[1] == 0);
|
assert(vec._internal_arr[1] == 0);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_reserve(void)
|
test_reserve(void)
|
||||||
{
|
{
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
printf("[21] Testing _vec_char_reserve null vector\n");
|
printf("[21] Testing _vec_int_reserve null vector\n");
|
||||||
_vec_char_reserve(nullptr, 1, &err);
|
_vec_int_reserve(nullptr, 1, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[22] Testing _vec_char_reserve capacity 0\n");
|
printf("[22] Testing _vec_int_reserve capacity 0\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_reserve(&vec, 0, &err);
|
_vec_int_reserve(&vec, 0, &err);
|
||||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[23] Testing _vec_char_reserve calloc on unallocated buffer\n");
|
printf("[23] Testing _vec_int_reserve calloc on unallocated buffer\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_reserve(&vec, 32, &err);
|
_vec_int_reserve(&vec, 32, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_capacity == 32);
|
assert(vec._internal_capacity == 32);
|
||||||
assert(vec._internal_arr != nullptr);
|
assert(vec._internal_arr != nullptr);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[24] Testing _vec_char_reserve realloc to larger capacity\n");
|
printf("[24] Testing _vec_int_reserve realloc to larger capacity\n");
|
||||||
_vec_char_reserve(&vec, 64, &err);
|
_vec_int_reserve(&vec, 64, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_capacity == 64);
|
assert(vec._internal_capacity == 64);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[25] Testing _vec_char_reserve truncating size\n");
|
printf("[25] Testing _vec_int_reserve truncating size\n");
|
||||||
vec._internal_size = 50;
|
vec._internal_size = 50;
|
||||||
_vec_char_reserve(&vec, 20, &err);
|
_vec_int_reserve(&vec, 20, &err);
|
||||||
assert(vec._internal_size == 20);
|
assert(vec._internal_size == 20);
|
||||||
assert(vec._internal_capacity == 20);
|
assert(vec._internal_capacity == 20);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_shrink_to_fit(void)
|
test_shrink_to_fit(void)
|
||||||
{
|
{
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
printf("[26] Testing _vec_char_shrink_to_fit null vector\n");
|
printf("[26] Testing _vec_int_shrink_to_fit null vector\n");
|
||||||
_vec_char_shrink_to_fit(nullptr, &err);
|
_vec_int_shrink_to_fit(nullptr, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"[27] Testing _vec_char_shrink_to_fit size 0 with allocated "
|
"[27] Testing _vec_int_shrink_to_fit size 0 with allocated "
|
||||||
"buffer\n");
|
"buffer\n");
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'a', &err);
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
_vec_char_pop_back(&vec, &err);
|
_vec_int_pop_back(&vec, &err);
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_shrink_to_fit(&vec, &err);
|
_vec_int_shrink_to_fit(&vec, &err);
|
||||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
|
|
||||||
printf("[28] Testing _vec_char_shrink_to_fit normal shrinkage\n");
|
printf("[28] Testing _vec_int_shrink_to_fit normal shrinkage\n");
|
||||||
_vec_char_reserve(&vec, 128, &err);
|
_vec_int_reserve(&vec, 128, &err);
|
||||||
for (char c = '0'; c < '5'; c++)
|
for (int val = 0; val < 5; val++)
|
||||||
{
|
{
|
||||||
_vec_char_push_back(&vec, c, &err);
|
_vec_int_push_back(&vec, val, &err);
|
||||||
}
|
}
|
||||||
assert(vec._internal_capacity == 128);
|
assert(vec._internal_capacity == 128);
|
||||||
assert(vec._internal_size == 5);
|
assert(vec._internal_size == 5);
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_shrink_to_fit(&vec, &err);
|
_vec_int_shrink_to_fit(&vec, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_capacity == 5);
|
assert(vec._internal_capacity == 5);
|
||||||
assert(vec._internal_size == 5);
|
assert(vec._internal_size == 5);
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,75 +353,75 @@ static void
|
|||||||
test_getters_and_access(void)
|
test_getters_and_access(void)
|
||||||
{
|
{
|
||||||
printf("[29] Testing getters, clear, and boundary element access...\n");
|
printf("[29] Testing getters, clear, and boundary element access...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
// 1. Null pointer check
|
// 1. Null pointer check
|
||||||
assert(_vec_char_data(nullptr, &err) == nullptr);
|
assert(_vec_int_data(nullptr, &err) == nullptr);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_size(nullptr, &err) == 0);
|
assert(_vec_int_size(nullptr, &err) == 0);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_capacity(nullptr, &err) == 0);
|
assert(_vec_int_capacity(nullptr, &err) == 0);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_max_size(nullptr, &err) == 0);
|
assert(_vec_int_max_size(nullptr, &err) == 0);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
// 2. Unallocated buffer check for empty()
|
// 2. Unallocated buffer check for empty()
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
size_t unalloc_empty = _vec_char_empty(&vec, &err);
|
size_t unalloc_empty = _vec_int_empty(&vec, &err);
|
||||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
assert(unalloc_empty != 0);
|
assert(unalloc_empty != 0);
|
||||||
|
|
||||||
// 3. Allocate the buffer and pop so size is 0 with valid arr
|
// 3. Allocate the buffer and pop so size is 0 with valid arr
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'x', &err);
|
_vec_int_push_back(&vec, 100, &err);
|
||||||
_vec_char_pop_back(&vec, &err);
|
_vec_int_pop_back(&vec, &err);
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
|
|
||||||
// Now _internal_arr is non-null and size is 0:
|
// Now _internal_arr is non-null and size is 0:
|
||||||
assert(_vec_char_empty(&vec, &err) == 0);
|
assert(_vec_int_empty(&vec, &err) == 0);
|
||||||
|
|
||||||
// Boundary element access on size 0
|
// Boundary element access on size 0
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_front(&vec, &err) == 0 ||
|
assert(_vec_int_front(&vec, &err) == 0 ||
|
||||||
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_back(&vec, &err) == 0 ||
|
assert(_vec_int_back(&vec, &err) == 0 ||
|
||||||
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// 4. Populate container
|
// 4. Populate container
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&vec, 'x', &err);
|
_vec_int_push_back(&vec, 10, &err);
|
||||||
_vec_char_push_back(&vec, 'y', &err);
|
_vec_int_push_back(&vec, 20, &err);
|
||||||
_vec_char_push_back(&vec, 'z', &err);
|
_vec_int_push_back(&vec, 30, &err);
|
||||||
|
|
||||||
assert(_vec_char_size(&vec, &err) == 3);
|
assert(_vec_int_size(&vec, &err) == 3);
|
||||||
assert(_vec_char_capacity(&vec, &err) >= 3);
|
assert(_vec_int_capacity(&vec, &err) >= 3);
|
||||||
assert(_vec_char_data(&vec, &err) == vec._internal_arr);
|
assert(_vec_int_data(&vec, &err) == vec._internal_arr);
|
||||||
assert(_vec_char_front(&vec, &err) == 'x');
|
assert(_vec_int_front(&vec, &err) == 10);
|
||||||
assert(_vec_char_back(&vec, &err) == 'z');
|
assert(_vec_int_back(&vec, &err) == 30);
|
||||||
assert(_vec_char_begin(&vec, &err) == 0);
|
assert(_vec_int_begin(&vec, &err) == 0);
|
||||||
assert(_vec_char_end(&vec, &err) == 2);
|
assert(_vec_int_end(&vec, &err) == 2);
|
||||||
|
|
||||||
// Out of bounds at()
|
// Out of bounds at()
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
assert(_vec_char_at(&vec, 10, &err) == nullptr);
|
assert(_vec_int_at(&vec, 10, &err) == nullptr);
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// Clear container
|
// Clear container
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_clear(&vec, &err);
|
_vec_int_clear(&vec, &err);
|
||||||
assert(vec._internal_size == 0);
|
assert(vec._internal_size == 0);
|
||||||
assert(vec._internal_arr[0] == 0);
|
assert(vec._internal_arr[0] == 0);
|
||||||
|
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
assert(vec._internal_arr == nullptr);
|
assert(vec._internal_arr == nullptr);
|
||||||
assert(vec._internal_size == 0);
|
assert(vec._internal_size == 0);
|
||||||
assert(vec._internal_capacity == 0);
|
assert(vec._internal_capacity == 0);
|
||||||
@@ -435,220 +436,222 @@ test_getters_and_access(void)
|
|||||||
static void
|
static void
|
||||||
test_swap(void)
|
test_swap(void)
|
||||||
{
|
{
|
||||||
printf("[30] Testing _vec_char_swap...\n");
|
printf("[30] Testing _vec_int_swap...\n");
|
||||||
_VecCharInternal a = VEC_INIT;
|
_VecIntInternal a = VEC_INIT;
|
||||||
_VecCharInternal b = VEC_INIT;
|
_VecIntInternal b = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
// Null vector checks
|
// Null vector checks
|
||||||
_vec_char_swap(nullptr, &b, &err);
|
_vec_int_swap(nullptr, &b, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_swap(&a, nullptr, &err);
|
_vec_int_swap(&a, nullptr, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
// Normal swap
|
// Normal swap
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_push_back(&a, 'A', &err);
|
_vec_int_push_back(&a, 100, &err);
|
||||||
_vec_char_push_back(&b, 'B', &err);
|
_vec_int_push_back(&b, 200, &err);
|
||||||
_vec_char_push_back(&b, 'C', &err);
|
_vec_int_push_back(&b, 300, &err);
|
||||||
|
|
||||||
_vec_char_swap(&a, &b, &err);
|
_vec_int_swap(&a, &b, &err);
|
||||||
assert(a._internal_size == 2);
|
assert(a._internal_size == 2);
|
||||||
assert(a._internal_arr[0] == 'B');
|
assert(a._internal_arr[0] == 200);
|
||||||
assert(b._internal_size == 1);
|
assert(b._internal_size == 1);
|
||||||
assert(b._internal_arr[0] == 'A');
|
assert(b._internal_arr[0] == 100);
|
||||||
|
|
||||||
_vec_char_delete(&a, &err);
|
_vec_int_delete(&a, &err);
|
||||||
_vec_char_delete(&b, &err);
|
_vec_int_delete(&b, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_erase_variants(void)
|
test_erase_variants(void)
|
||||||
{
|
{
|
||||||
printf("[31] Testing _vec_char_erase single & range overloads...\n");
|
printf("[31] Testing _vec_int_erase single & range overloads...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
for (char c = '0'; c <= '5'; c++)
|
for (int val = 0; val <= 5; val++)
|
||||||
{
|
{
|
||||||
_vec_char_push_back(&vec, c, &err);
|
_vec_int_push_back(&vec, val, &err);
|
||||||
} // "012345"
|
} // {0, 1, 2, 3, 4, 5}
|
||||||
|
|
||||||
// Single element erase out of bounds (noop)
|
// Single element erase out of bounds (noop)
|
||||||
_vec_char_erase(&vec, 10, &err);
|
_vec_int_erase(&vec, 10, &err);
|
||||||
assert(vec._internal_size == 6);
|
assert(vec._internal_size == 6);
|
||||||
|
|
||||||
// Erase index 2 ('2') -> "01345"
|
// Erase index 2 (value 2) -> {0, 1, 3, 4, 5}
|
||||||
_vec_char_erase(&vec, 2, &err);
|
_vec_int_erase(&vec, 2, &err);
|
||||||
assert(vec._internal_size == 5);
|
assert(vec._internal_size == 5);
|
||||||
assert(vec._internal_arr[2] == '3');
|
assert(vec._internal_arr[2] == 3);
|
||||||
|
|
||||||
// Range erase invalid bounds
|
// Range erase invalid bounds
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_erase(&vec, 4, 2, &err); // iter_end <= iter_start
|
_vec_int_erase(&vec, 4, 2, &err); // iter_end <= iter_start
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_erase(&vec, 0, 10, &err); // iter_end > size
|
_vec_int_erase(&vec, 0, 10, &err); // iter_end > size
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// Range erase middle: index 1 through 3 ("0[13]45" -> "045")
|
// Range erase middle: index 1 through 3 ({0, [1, 3], 4, 5} -> {0, 4,
|
||||||
|
// 5})
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_erase(&vec, 1, 3, &err);
|
_vec_int_erase(&vec, 1, 3, &err);
|
||||||
assert(vec._internal_size == 3);
|
assert(vec._internal_size == 3);
|
||||||
assert(vec._internal_arr[0] == '0');
|
assert(vec._internal_arr[0] == 0);
|
||||||
assert(vec._internal_arr[1] == '4');
|
assert(vec._internal_arr[1] == 4);
|
||||||
assert(vec._internal_arr[2] == '5');
|
assert(vec._internal_arr[2] == 5);
|
||||||
|
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_resize(void)
|
test_resize(void)
|
||||||
{
|
{
|
||||||
printf("[32] Testing _vec_char_resize (zero-fill & value-fill)...\n");
|
printf("[32] Testing _vec_int_resize (zero-fill & value-fill)...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
// Null vector
|
// Null vector
|
||||||
_vec_char_resize((_VecCharInternal*)nullptr, 10, &err);
|
_vec_int_resize((_VecIntInternal*)nullptr, 10, &err);
|
||||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
// Resize unallocated buffer to size 5
|
// Resize unallocated buffer to size 5
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_resize(&vec, 5, &err);
|
_vec_int_resize(&vec, 5, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(vec._internal_size == 5);
|
assert(vec._internal_size == 5);
|
||||||
assert(vec._internal_arr[0] == 0);
|
assert(vec._internal_arr[0] == 0);
|
||||||
|
|
||||||
// Same size requested
|
// Same size requested
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_resize(&vec, 5, &err);
|
_vec_int_resize(&vec, 5, &err);
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// Exceeds max size
|
// Exceeds max size
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_resize(&vec, vec._internal_max_size + 1, &err);
|
_vec_int_resize(&vec, vec._internal_max_size + 1, &err);
|
||||||
assert((err.flags & ERR_SIZE_OVERFLOW) != 0);
|
assert((err.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
|
|
||||||
// Grow with value fill
|
// Grow with value fill
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_resize(&vec, 8, 'Z', &err);
|
_vec_int_resize(&vec, 8, 5, &err);
|
||||||
assert(vec._internal_size == 8);
|
assert(vec._internal_size == 8);
|
||||||
assert(vec._internal_arr[5] == 'Z');
|
assert(vec._internal_arr[5] == 5);
|
||||||
assert(vec._internal_arr[7] == 'Z');
|
assert(vec._internal_arr[7] == 5);
|
||||||
|
|
||||||
// Shrink with value fill
|
// Shrink with value fill
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_resize(&vec, 3, 'A', &err);
|
_vec_int_resize(&vec, 3, 10, &err);
|
||||||
assert(vec._internal_size == 3);
|
assert(vec._internal_size == 3);
|
||||||
|
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_assign(void)
|
test_assign(void)
|
||||||
{
|
{
|
||||||
printf("[33] Testing _vec_char_assign overloads...\n");
|
printf("[33] Testing _vec_int_assign overloads...\n");
|
||||||
_VecCharInternal dst = VEC_INIT;
|
_VecIntInternal dst = VEC_INIT;
|
||||||
_VecCharInternal src = VEC_INIT;
|
_VecIntInternal src = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
// Populate src: 'A', 'B', 'C', 'D', 'E'
|
// Populate src: 1, 2, 3, 4, 5
|
||||||
for (char c = 'A'; c <= 'E'; c++)
|
for (int val = 1; val <= 5; val++)
|
||||||
{
|
{
|
||||||
_vec_char_push_back(&src, c, &err);
|
_vec_int_push_back(&src, val, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate dst buffer first so it is not unallocated
|
// Allocate dst buffer first so it is not unallocated
|
||||||
_vec_char_push_back(&dst, 'z', &err);
|
_vec_int_push_back(&dst, 999, &err);
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
|
|
||||||
// 1. Fill assign: 4 'X's
|
// 1. Fill assign: 4 42's
|
||||||
_vec_char_assign(&dst, 4, 'X', &err);
|
_vec_int_assign(&dst, 4, 42, &err);
|
||||||
assert(err.flags == 0);
|
assert(err.flags == 0);
|
||||||
assert(dst._internal_size == 4);
|
assert(dst._internal_size == 4);
|
||||||
assert(dst._internal_arr[0] == 'X');
|
assert(dst._internal_arr[0] == 42);
|
||||||
assert(dst._internal_arr[3] == 'X');
|
assert(dst._internal_arr[3] == 42);
|
||||||
|
|
||||||
// 2. Fill assign with 0 amount
|
// 2. Fill assign with 0 amount
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_assign(&dst, 0, 'Y', &err);
|
_vec_int_assign(&dst, 0, 50, &err);
|
||||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
|
||||||
// 3. Range assign self-buffer check
|
// 3. Range assign self-buffer check
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_assign(&dst, &dst, 0, 2, &err);
|
_vec_int_assign(&dst, &dst, 0, 2, &err);
|
||||||
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||||
|
|
||||||
// 4. Range assign invalid sub-range (start >= end)
|
// 4. Range assign invalid sub-range (start >= end)
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_assign(&dst, &src, 3, 2, &err);
|
_vec_int_assign(&dst, &src, 3, 2, &err);
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// 5. Range assign out of bounds end
|
// 5. Range assign out of bounds end
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_assign(&dst, &src, 0, 10, &err);
|
_vec_int_assign(&dst, &src, 0, 10, &err);
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
_vec_char_delete(&dst, &err);
|
_vec_int_delete(&dst, &err);
|
||||||
_vec_char_delete(&src, &err);
|
_vec_int_delete(&src, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_insert(void)
|
test_insert(void)
|
||||||
{
|
{
|
||||||
printf("[34] Testing _vec_char_insert overloads...\n");
|
printf("[34] Testing _vec_int_insert overloads...\n");
|
||||||
_VecCharInternal vec = VEC_INIT;
|
_VecIntInternal vec = VEC_INIT;
|
||||||
_VecCharInternal other = VEC_INIT;
|
_VecIntInternal other = VEC_INIT;
|
||||||
err_t err = ERR_T_INIT;
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
// Single insert on unallocated buffer
|
// Single insert on unallocated buffer
|
||||||
_vec_char_insert(&vec, 0, 'M', &err);
|
_vec_int_insert(&vec, 0, 500, &err);
|
||||||
assert(vec._internal_size == 1);
|
assert(vec._internal_size == 1);
|
||||||
assert(vec._internal_arr[0] == 'M');
|
assert(vec._internal_arr[0] == 500);
|
||||||
|
|
||||||
// Single insert out of bounds
|
// Single insert out of bounds
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_insert(&vec, 5, 'O', &err);
|
_vec_int_insert(&vec, 5, 999, &err);
|
||||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
// Single insert at middle: index 0 ('A', then 'M' shifts to 1)
|
// Single insert at middle: index 0 (100, then 500 shifts to 1)
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_insert(&vec, 0, 'A', &err);
|
_vec_int_insert(&vec, 0, 100, &err);
|
||||||
assert(vec._internal_size == 2);
|
assert(vec._internal_size == 2);
|
||||||
assert(vec._internal_arr[0] == 'A');
|
assert(vec._internal_arr[0] == 100);
|
||||||
assert(vec._internal_arr[1] == 'M');
|
assert(vec._internal_arr[1] == 500);
|
||||||
|
|
||||||
// Repeated insert: insert 3 'B's at index 1 -> 'A', 'B', 'B', 'B', 'M'
|
// Repeated insert: insert 3 200s at index 1 -> {100, 200, 200, 200,
|
||||||
_vec_char_insert(&vec, 1, 3, 'B', &err);
|
// 500}
|
||||||
|
_vec_int_insert(&vec, 1, 3, 200, &err);
|
||||||
assert(vec._internal_size == 5);
|
assert(vec._internal_size == 5);
|
||||||
assert(vec._internal_arr[1] == 'B');
|
assert(vec._internal_arr[1] == 200);
|
||||||
assert(vec._internal_arr[3] == 'B');
|
assert(vec._internal_arr[3] == 200);
|
||||||
assert(vec._internal_arr[4] == 'M');
|
assert(vec._internal_arr[4] == 500);
|
||||||
|
|
||||||
// Repeated insert amount 0
|
// Repeated insert amount 0
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_insert(&vec, 0, 0, 'Z', &err);
|
_vec_int_insert(&vec, 0, 0, 300, &err);
|
||||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
|
||||||
// Vector-from-vector range insert
|
// Vector-from-vector range insert
|
||||||
_vec_char_push_back(&other, '1', &err);
|
_vec_int_push_back(&other, 1, &err);
|
||||||
_vec_char_push_back(&other, '2', &err);
|
_vec_int_push_back(&other, 2, &err);
|
||||||
|
|
||||||
// Double buffer check
|
// Double buffer check
|
||||||
err = (err_t)ERR_T_INIT;
|
err = (err_t)ERR_T_INIT;
|
||||||
_vec_char_insert(&vec, &vec, 0, 0, 1, &err);
|
_vec_int_insert(&vec, &vec, 0, 0, 1, &err);
|
||||||
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||||
|
|
||||||
_vec_char_delete(&vec, &err);
|
_vec_int_delete(&vec, &err);
|
||||||
_vec_char_delete(&other, &err);
|
_vec_int_delete(&other, &err);
|
||||||
printf("Passed\n");
|
printf("Passed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user