Compare commits
9
Commits
4bc6efd89e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12b560fb37 | ||
|
|
0e7c2cafaa | ||
|
|
1654b86640 | ||
|
|
4d96592a1e | ||
|
|
813390b6ac | ||
|
|
b89579a5e7 | ||
|
|
fbd97f7112 | ||
|
|
6b7a560156 | ||
|
|
b39911f57e |
@@ -0,0 +1,8 @@
|
|||||||
|
Checks: >
|
||||||
|
-*,
|
||||||
|
clang-analyzer-*,
|
||||||
|
bugprone-*,
|
||||||
|
-bugprone-easily-swappable-parameters,
|
||||||
|
-bugprone-reserved-identifier,
|
||||||
|
performance-*,
|
||||||
|
security-*
|
||||||
+7
-1
@@ -1,2 +1,8 @@
|
|||||||
build/
|
build/
|
||||||
.cache/
|
.cache/
|
||||||
|
tests/cache/
|
||||||
|
tests/bin/
|
||||||
|
coverage.html
|
||||||
|
|
||||||
|
tests
|
||||||
|
Makefile
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
# AGENTS.md
|
|
||||||
|
|
||||||
## Identity & Core Philosophy
|
|
||||||
You are an expert bug-hunter agent.
|
|
||||||
Speak and reason in **Caveman style** (why use many token when few token do trick).
|
|
||||||
|
|
||||||
### Caveman Communication Rules
|
|
||||||
- Drop articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries, and greetings.
|
|
||||||
- Short, dense, direct phrases. Fragment sentences okay.
|
|
||||||
- Never summarize files read. Report only findings.
|
|
||||||
- **No tool-call narration:** Fire tools directly. Never explain what you are about to inspect or have just inspected.
|
|
||||||
- **Tokenizer rules:** NEVER invent abbreviations (cfg/impl/req/res/fn) or use arrows (→); tokenizers split them. Keep full words.
|
|
||||||
- **Safety rules:** NEVER drop `not`, `never`, `no`, `only`, `except` (flips meaning).
|
|
||||||
- **Exceptions (Do NOT caveman):** Code snippets, file paths, line numbers, command names, and error traces remain exact and intact.
|
|
||||||
- **Output pattern:** `[thing] [action] [reason]. [next step].`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Strict Permissions & Boundaries
|
|
||||||
1. **Target Task:** Read codebase, hunt bugs, identify security flaws, edge-case failures, or performance bottlenecks.
|
|
||||||
2. **File Mutation Constraint:**
|
|
||||||
- **YOU MAY ONLY CREATE OR EDIT:** `BUGS.md`
|
|
||||||
- **ABSOLUTE BAN:** You are strictly forbidden from modifying, patching, refactoring, deleting, or creating ANY other files in the workspace (no source files, configs, tests, or documentation).
|
|
||||||
- If user asks you to fix code directly, REFUSE in caveman: "No touch code. Rule say only log to BUGS.md."
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Operating Instructions
|
|
||||||
1. Inspect files in read-only mode using available search/read tools. Call them immediately without introductory text.
|
|
||||||
2. Read existing `BUGS.md` first:
|
|
||||||
- Identify existing style, headers, keys, table columns, or list formats.
|
|
||||||
- You MUST mirror existing format, structure, and naming conventions exactly.
|
|
||||||
- If `BUGS.md` is empty or missing, use a minimal markdown list: `File:Line | Severity | Issue | Recommended fix`.
|
|
||||||
3. For every confirmed issue found:
|
|
||||||
- Append or edit entry in `BUGS.md` following matched format.
|
|
||||||
- Keep bug descriptions in `BUGS.md` terse and caveman-style.
|
|
||||||
4. Do not patch or edit source code under any circumstances.
|
|
||||||
@@ -1,325 +0,0 @@
|
|||||||
# libvec bug tracker
|
|
||||||
|
|
||||||
> **Verified** `char.c` @ **2026-09-28 12:48:04**, 3 independent passes.
|
|
||||||
> `char.h` 108 lines, `utils.h` 31, `utils.c` 12, `CMakeLists.txt` 32, `main.c` 55.
|
|
||||||
> Line numbers are the *only* field that drifts. Re-verify before trusting them.
|
|
||||||
>
|
|
||||||
> **Pass 4** @ **2026-09-28**, `push_back` / `pop_back` (char.c:67-157), ASan.
|
|
||||||
> **Pass 5** @ **2026-09-28**, whole file re-read plus 10 harness runs, ASan.
|
|
||||||
> Line count moved 804 to 800 with the `create` rewrite; re-measured per pass.
|
|
||||||
|
|
||||||
**Open 79** — 11 S1, 27 S2, 11 S3, 29 C
|
|
||||||
**1 DECIDE** · **Fixed 12** (listed at the bottom, no rows) · 79 rows
|
|
||||||
|
|
||||||
**Severity** `S1` memory safety · `S2` wrong result / broken contract ·
|
|
||||||
`S3` edge case · `C` cleanup · `DECIDE` open design question
|
|
||||||
|
|
||||||
## How to read this
|
|
||||||
|
|
||||||
Each function is a `###` with one table. Rows are sorted by severity (S1 first),
|
|
||||||
so the worst thing in each function is on top. Fixed findings are **not** rows —
|
|
||||||
they are a flat ID list at the bottom of the file.
|
|
||||||
|
|
||||||
Tracking state is a **column**, not a checkbox: a `State` cell carries more than
|
|
||||||
"done or not done" — `DECIDE` has no checkbox equivalent, and it is load-bearing
|
|
||||||
here. And task-list syntax inside a table cell is renderer-dependent, so a
|
|
||||||
`State` column is the form that survives any markdown preview. If your preview
|
|
||||||
*does* render checkboxes in tables and you want click-to-toggle, a leading `Done`
|
|
||||||
column can be added without disturbing anything else.
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
|
|
||||||
1. **IDs are permanent.** Never reused, never renumbered. An ID leaves the file
|
|
||||||
only when its row is deleted outright, and only under rule 3.
|
|
||||||
2. **Locations drift freely.** The only field updated in place.
|
|
||||||
3. **False findings are deleted, not archived.** If a row turns out to be my own
|
|
||||||
error, the row is removed. A new ID carries the accurate finding if there is
|
|
||||||
one. No `DISPUTED` state, no corrections log — a tracker is not a diary.
|
|
||||||
4. **State** is `OPEN` / `DECIDE`. `FIXED` means the row is gone and its ID is
|
|
||||||
in the bottom list.
|
|
||||||
5. **Fixed findings live in the ID list at the bottom**, nothing else.
|
|
||||||
|
|
||||||
## Triage — the 11 open S1s, in suggested order
|
|
||||||
|
|
||||||
| # | ID | Location | Summary |
|
|
||||||
|----|---|---|---|
|
|
||||||
| 1 | <code><nobr>RS-7</nobr></code> | char.c:175, 200 | `reserve` on a blank vector allocates 1024 but claims 5000. Ordinary `size`, live overflow |
|
|
||||||
| 3 | <code><nobr>PB-8</nobr></code> | char.c:89, 131 | live heap overflow, 2-line repro |
|
|
||||||
| 4 | <code><nobr>PB-14</nobr></code> | char.c:131, 154 | write through the freed buffer after `delete`, 2-line repro |
|
|
||||||
| 5 | <code><nobr>RS-1</nobr></code> | char.c:180-195 | use-after-free in `reserve`'s truncation loop, ASan confirmed |
|
|
||||||
| 6 | <code><nobr>IN-1</nobr></code> | char.c:783 | inverted `iter_end > iter_start` |
|
|
||||||
| 7 | <code><nobr>IN-2</nobr></code> | char.c:783 | dead bounds check sitting behind IN-1 |
|
|
||||||
| 8 | <code><nobr>DL-1</nobr></code> | char.c:293, 297 | `const` delete, double free on second call |
|
|
||||||
| 9 | <code><nobr>DL-2</nobr></code> | char.h:11-17 | no ownership marker, struct copy double-frees |
|
|
||||||
| 8 | <code><nobr>UT-2</nobr></code> | utils.c:3-12 | `error_messages[0]` / `[1]` are `NULL` |
|
|
||||||
| 9 | <code><nobr>PB-3</nobr></code> | char.c:106, 116 | capacity committed before the realloc check |
|
|
||||||
| 10 | <code><nobr>PB-15</nobr></code> | char.c:87, 128-131 | null-buffer path has no `else`, so `arr == NULL && size > 0` writes to NULL. Defensive |
|
|
||||||
|
|
||||||
> **Two of the eleven are the same class.** RS-7 and PB-8 both end in a
|
|
||||||
> write past a small block, and both come from a struct field claiming more
|
|
||||||
> bytes than were allocated: `capacity` set from the request rather than the
|
|
||||||
> block (RS-7, char.c:200), `calloc(1)` with `capacity` untouched (PB-8,
|
|
||||||
> char.c:89). One rule kills both: **never write `_internal_capacity` without
|
|
||||||
> writing the allocation it describes.** Verify with a single postcondition —
|
|
||||||
> after any function that touches capacity, the block size and the field must
|
|
||||||
> agree. CR-8 was a third member of this class; it is fixed as of Pass 5, and
|
|
||||||
> `create` now carries the same postcondition in one place (CR-9, char.c:44).
|
|
||||||
|
|
||||||
> **Fix IN-1 and IN-2 in the same commit.** The raw read in the 3-arg overload
|
|
||||||
> is unreachable *only because* IN-1's inversion empties the loop. Fixing IN-1
|
|
||||||
> alone converts a clean rejection into a live out-of-bounds read, because IN-2's
|
|
||||||
> bound check stays dead behind the short-circuit.
|
|
||||||
|
|
||||||
> **PB-8 and PB-14 are the only two rows in this file with a sanitizer trace
|
|
||||||
> attached.** Both reproduce in three lines from `main`. `delete` should null
|
|
||||||
> the struct's fields (DL-1) and push should size the materialization from
|
|
||||||
> `_internal_capacity` (PB-8); those two fixes close the whole S1 set for this
|
|
||||||
> function pair.
|
|
||||||
|
|
||||||
> **Reproducer harness**: `clang -std=c2x -g -fsanitize=address -Isrc/lib
|
|
||||||
> -Isrc/lib/char t.c src/lib/char/char.c src/lib/utils/utils.c`. `-std=c2x` is
|
|
||||||
> required — `char.c` uses `nullptr`, so the project does not compile as C17.
|
|
||||||
> Reproducers that ask for a multi-exabyte `calloc` additionally need
|
|
||||||
> `ASAN_OPTIONS=allocator_may_return_null=1`, or ASan aborts on the 2^61-byte
|
|
||||||
> `calloc` before the interesting line runs.
|
|
||||||
|
|
||||||
> **Defensive-only rows.** RZ-2, RS-2, PB-15 and PB-18 are not reachable
|
|
||||||
> without an allocation of ~2^61 bytes, or a hand-built struct. Kept as
|
|
||||||
> hardening because the guards are cheap and the invariant is worth stating.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Bugs
|
|
||||||
|
|
||||||
### `_vec_char_push_back` / `_vec_char_pop_back` — char.c:71, 136
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|-----|---|---|---|---|
|
|
||||||
| `PB-8` | S1 | char.c:89, 131 | `calloc(1)` on the null-buffer path leaves `_internal_capacity` at 1024, so the 2nd `push_back` writes `arr[1]` one byte past a 1-byte block. **ASan: `heap-buffer-overflow` WRITE of size 1 at char.c:131**, block allocated at char.c:89 | OPEN |
|
|
||||||
| <code><nobr>PB-14</nobr></code> | S1 | char.c:75, 131, 154 | neither function checks liveness. `_vec_char_delete` frees without clearing the struct (DL-1), so `delete(&v); push_back(&v,'z')` writes through the freed pointer. **ASan: `heap-use-after-free` WRITE of size 1 at char.c:131**, freed at char.c:297. Same for `pop_back`, which writes `'\0'` at char.c:154 | OPEN |
|
|
||||||
| <code><nobr>PB-15</nobr></code> | S1 | char.c:87, 128-131 | the materialize branch is guarded by `status == ERR_BUF_NULL && _internal_size == 0` and has no `else`. Any state with `arr == NULL && _internal_size > 0` falls through to char.c:126, takes `res = ptr->_internal_arr` (NULL) and writes `arr[size]`. No in-file producer, but nothing checks the invariant either | OPEN |
|
|
||||||
| <code><nobr>PB-3</nobr></code> | S1 | char.c:106, 116 | `_internal_capacity` assigned before the `!res` check; on OOM the struct overstates its capacity and the next call writes past the real block. Both branches | OPEN |
|
|
||||||
| <code><nobr>PB-9</nobr></code> | S2 | char.c:85-99| `push_back` materializes a null vector, making it a second path alongside `reserve`; the two disagree on allocation size (1 byte vs 1024) | OPEN |
|
|
||||||
| <code><nobr>PB-16</nobr></code> | S2 | char.c:116, 131 vs 154 | the growth `realloc` leaves the new tail uninitialized and `push_back` never writes a terminator at `_internal_size`, so `_vec_char_data` hands back a non-NUL-terminated buffer — `strlen(data(&v))` runs off the end. **ASan: `heap-buffer-overflow` READ of 2049 bytes past a 2048-byte region** grown at char.c:116. The lone `'\0'` write in either function is `pop_back`'s vacated slot, so termination is accidental | OPEN |
|
|
||||||
| <code><nobr>PB-21</nobr></code> | S2 | char.c:81, 104 | after any `reserve` the vector is permanently full: reserve sets `max_size = capacity`, so char.c:81 fails for good and `push_back` can only return `ERR_MAX_PASSED`. Duplicate view of AS-4, kept so this table stands alone | OPEN |
|
|
||||||
| <code><nobr>PB-17</nobr></code> | S3 | char.c:144-147 vs 87 | `pop_back` refuses to materialize while `push_back` does. A blank vector reports `ERR_BUF_NULL` (21) and logs a spurious "Buffer :- NULL" instead of `ERR_SIZE_ZERO` (22), so a `while (pop_back(&v) == SUCCESS)` drain reports the wrong reason | OPEN |
|
|
||||||
| <code><nobr>PB-18</nobr></code> | S3 | char.c:103, 116, 120-124 | `_internal_capacity == 0` makes `dst_cap` 0, and `realloc(arr, 0)` frees the block. The `!res` check then returns `ERR_ALLOC_FAIL` with `_internal_arr` dangling and capacity already committed as 0; the next push writes to freed memory. Capacity 0 is unreachable from this file today, so defensive | OPEN |
|
|
||||||
| <code><nobr>PB-20</nobr></code> | S3 | char.c:154 | only the vacated slot is zeroed, so bytes past `_internal_size` keep their values and are readable out of band through `data()`. `clear` zeroes the whole range and `erase` zeroes the tail; `pop_back` is the inconsistent one | OPEN |
|
|
||||||
|
|
||||||
> PB-1 and PB-2 were originally described as firing "on the very next call" and
|
|
||||||
> as "the clamp silently does nothing". Both claims were wrong in detail: PB-1
|
|
||||||
> needed `capacity < size+1 <= max_size < 2*capacity`, a band today's `VEC_MAX`
|
|
||||||
> never reaches, and PB-2's cause was `cap` being recomputed from the
|
|
||||||
> already-clobbered `capacity`, not the branch being skipped.
|
|
||||||
|
|
||||||
> **Pass-4 note.** Four pre-existing rows here were my own errors and were
|
|
||||||
> deleted: a "dead else" that is the common path, two `is_valid` double-call
|
|
||||||
> claims in a function that hoists, and an overflow that `VEC_MAX` makes
|
|
||||||
> impossible. Found by diffing the wording against the source, not by testing.
|
|
||||||
> The three new S1/S2 rows *were* tested; the reproducer command is above.
|
|
||||||
|
|
||||||
### `_vec_char_create` — char.c:23
|
|
||||||
|
|
||||||
> **Pass-5 note.** `create`'s growth block was rewritten this pass and the
|
|
||||||
> rewrite is correct. The invariant it now enforces in one place is
|
|
||||||
> `size <= _internal_capacity <= _internal_max_size` on return, held by the
|
|
||||||
> commit-back at char.c:44. Verified under ASan at `size` 0, 1, 1023, 1024,
|
|
||||||
> 1025, 2047, 2048, 2049, 2999, 5000 and `VEC_MAX - 1`: `capacity >= size` on
|
|
||||||
> every call, the `calloc` block matches the reported capacity, no overflow.
|
|
||||||
> One case to know about: `create(NULL, VEC_MAX - 1)` still returns
|
|
||||||
> `capacity=4611686018427387902` over `arr == NULL`, because growth is correct
|
|
||||||
> and the `calloc` then fails. That is CR-3 below, and it is unchanged.
|
|
||||||
> `dst_cap * 2` at char.c:42 cannot wrap, because the loop only doubles while
|
|
||||||
> the product stays under `_internal_max_size`. An intermediate revision of
|
|
||||||
> this fix omitted the commit-back and overflowed every `size > CAPACITY`; it
|
|
||||||
> never reached a build, so no ID was spent on it. Two `create` findings left
|
|
||||||
> the table this pass and their IDs are in the bottom list: **CR-7**, the
|
|
||||||
> second growth branch, which tested the ceiling (`capacity*2 > max_size`)
|
|
||||||
> instead of the loop's own postcondition — a superset that also fired after a
|
|
||||||
> successful grow, overwriting `capacity` with `size` and forcing the next
|
|
||||||
> `push_back` to reallocate for one byte; its `>` test also disagreed with the
|
|
||||||
> loop's `>=` exit on exactly one value, reachable only because `VEC_MAX` is
|
|
||||||
> odd. **CR-8**, the `>=` guard at char.c:32, which left `size == VEC_MAX`
|
|
||||||
> allocating 1024 bytes and copying `VEC_MAX` bytes into it. Both are gone
|
|
||||||
> because the branch they described no longer exists, not because either was
|
|
||||||
> re-filed under a new ID.
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>CR-6</nobr></code> | S2 | char.c:29, 39-45| null vector's `_internal_capacity` is set to `CAPACITY` (1024) while nothing is allocated. Currently **masked** by AC-1: `capacity()` returns `ERR_BUF_NULL` first, so the lie is not observable through the public API. The observable form of this same lie is PB-8, after `push_back` materializes the buffer | OPEN |
|
|
||||||
| <code><nobr>CR-3</nobr></code> | S3 | char.c:48-53 | on `calloc` failure returns a struct with an already-grown `capacity` and `arr == NULL`. Defensive. **Now reachable with an ordinary `size`, not just a huge one**: `create(NULL, 5000)` grows `capacity` to 8192 at char.c:44, then the 8192-byte `calloc` fails and the struct survives claiming 8192 over a null buffer | OPEN |
|
|
||||||
| <code><nobr>CR-4</nobr></code> | DECIDE | char.c:58-65 | no NUL terminator; is a `const char* src, size_t size` pair a byte range or a C string? Affects whether a `from_cstr` helper is needed | DECIDE |
|
|
||||||
|
|
||||||
### `_vec_char_is_valid` — char.c:6
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>IV-1</nobr></code> | S2 | char.c:6 | always returns non-zero, so `if (_vec_char_is_valid(&v))` is true for every input including NULL. Every call site compares codes by luck | OPEN |
|
|
||||||
| <code><nobr>IV-3</nobr></code> | S2 | char.c:6-17| `is_valid` is the only validation primitive in the file and it requires a non-null **buffer**, not just a non-null vector. Every accessor that only needs to validate the vector pointer therefore inherits `ERR_BUF_NULL`. This is the root cause of AC-1, AC-2, SW-1 and ST-2 | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_reserve` — char.c:156
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>RS-7</nobr></code> | S1 | char.c:175, 200 | the `ERR_BUF_NULL` path allocates `ptr->_internal_capacity` bytes, not the requested `capacity`, then line 200 sets `_internal_capacity = capacity` regardless. So `reserve(&v, 5000)` on a blank vector `calloc`s **1024** bytes and the struct claims 5000. **ASan: `heap-buffer-overflow` WRITE at char.c:131, 0 bytes after a 1024-byte region allocated at char.c:175**, reached by 1026 `push_back`s. The `SUCCESS` path at char.c:184 sizes the `realloc` correctly; only the null-buffer path is wrong. Second producer of PB-8, and unlike CR-7 this one needs no huge `size` — 5000 is ordinary | OPEN |
|
|
||||||
| <code><nobr>RS-1</nobr></code> | S1 | char.c:180, 186-193, 195| realloc result held in `res`, but the truncation loop writes `ptr->_internal_arr`, which is still the pre-realloc pointer. Use-after-free when a shrinking `reserve` moves the block. Introduced by the FX-3 fix. **ASan confirmed**: `create("abcdefgh",8)` then `reserve(3)` gives `heap-use-after-free WRITE` at char.c:194 into a block freed at char.c:184 | OPEN |
|
|
||||||
| <code><nobr>RS-2</nobr></code> | S3 | char.c:160-164 | `capacity == 0` checked before the NULL-vector check, so a NULL vector with `capacity == 0` reports `ERR_SIZE_ZERO` instead of `ERR_VECTOR_NULL`. Defensive | OPEN |
|
|
||||||
| <code><nobr>RS-6</nobr></code> | C | char.c:158, 178, 195| clang `-Wsometimes-uninitialized`: `res` used uninitialized at 195 if the `if`/`else if` chain falls through. Not reachable today since `is_valid` returns exactly 3 values, but real fragility | OPEN |
|
|
||||||
| <code><nobr>RS-3</nobr></code> | C | char.c:197 | `max_size = capacity` is correct under the hard-cap semantics but is documented nowhere. **This is also the cause of ST-1 and AS-4** | OPEN |
|
|
||||||
| <code><nobr>RS-4</nobr></code> | C | char.c:188-191 | element-at-a-time loop, should be `memset` | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_shrink_to_fit` — char.c:202
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>ST-1</nobr></code> | S2 | char.c:202, 217 -> 197| calls `reserve(ptr, _internal_size)`, and `reserve` sets `max_size = capacity`. So `max_size` is permanently capped to the current size and **the vector can never grow again** — every later `push_back` trips `size+1 > max_size` and returns `ERR_MAX_PASSED`. Silent brick. No save/restore, unlike `resize` (RZ-3) | OPEN |
|
|
||||||
| <code><nobr>ST-2</nobr></code> | S3 | char.c:204-211| returns `ERR_SIZE_ZERO` on an empty vector; shrinking an empty vector should be a successful no-op. Two unhoisted `is_valid` calls at 204 and 208 | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_swap` — char.c:221
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>SW-1</nobr></code> | S2 | char.c:229-233 | refuses NULL-buffer operands, so a blank vector can never be swapped against a populated one. Blocks the `create(nullptr, 0)` workflow outright | OPEN |
|
|
||||||
| <code><nobr>SW-2</nobr></code> | C | char.c:223 | temp built via `_vec_char_create(nullptr, 0)`; a plain initializer states the intent | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_delete` — char.c:289
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>DL-1</nobr></code> | S1 | char.c:289, 293 | takes `const *` so it cannot reset the vector; a second call is a double free. Only function still taking `const` in a mutable API | OPEN |
|
|
||||||
| <code><nobr>DL-2</nobr></code> | S1 | char.h:11-17 | no ownership marker on the struct, so a by-value copy yields two owners of one buffer and `delete` cannot detect it | OPEN |
|
|
||||||
| <code><nobr>DL-3</nobr></code> | C | char.c:293 | unnecessary `(void*)` cast; `const` on the struct does not propagate to the pointee | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_capacity` / `_vec_char_max_size` / `_vec_char_data` — char.c:261, 275, 252
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>AC-1</nobr></code> | S2 | char.c:254, 267, 281 | all three return `ERR_BUF_NULL` for a null vector, though none of them needs a buffer. `capacity()` should report capacity, not an error | OPEN |
|
|
||||||
| <code><nobr>DA-1</nobr></code> | S2 | char.c:251, 257| `char*` returned from a `const _VecCharInternal*`, laundering the const-correctness the mutable refactor was meant to establish | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_clear` / `_vec_char_print_vec` — char.c:298, 341
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>CL-1</nobr></code> | C | char.c:310-313 | element-at-a-time zeroing loop, should be `memset` | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_at` — char.c:320
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>AT-1</nobr></code> | S2 | char.c:323, 328, 335| returns error codes (23/25, and 21) as a `char`; `assign` at char.c:642 pushes such a value into the vector as data | OPEN |
|
|
||||||
| <code><nobr>AT-2</nobr></code> | C | char.c:332 | raw `fprintf` bypasses `LOGERROR` | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_begin` / `_vec_char_end` — char.c:352, 359
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>BE-1</nobr></code> | S2 | char.c:355, 365, 367, 630, 668 | `FAILURE` (`== 1`) returned as an index, indistinguishable from index 1. Single root cause of the `+ 1` at char.c:630 and char.c:668, of the assign-on-empty failures AS-1, and of the erase-on-empty failure ER-1 | OPEN |
|
|
||||||
| <code><nobr>BE-2</nobr></code> | C | char.c:364 | `(int)` cast on a `size_t` return | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_front` / `_vec_char_back` / `_vec_char_empty` — char.c:371, 379, 387
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>AC-2</nobr></code> | S2 | char.c:392, 393 | inverted: `SUCCESS` (0) when empty, `FAILURE` (1) when not, so `if (empty(v))` is false for an empty vector | OPEN |
|
|
||||||
| <code><nobr>FB-1</nobr></code> | S2 | char.c:373, 374, 381, 382 | returns `FAILURE` (1) as a `char`; `1` is valid data | OPEN |
|
|
||||||
| <code><nobr>FB-2</nobr></code> | C | char.c:373, 381 | validates only `ERR_VECTOR_NULL`, unlike every other accessor | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_erase` (both overloads) — char.c:398, 412
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>ER-1</nobr></code> | S2 | char.c:417, 418 | `iter_start >= iter_end` returns `ERR_OUT_OF_BOUNDS`, so `erase(begin(), end())` on an empty vector always errors. This is what breaks both `assign` overloads. On an empty vector the actual trip is char.c:417 (`iter_end > size`) because `end()` returned 1 and the caller added 1 — see BE-1 | OPEN |
|
|
||||||
| <code><nobr>ER-2</nobr></code> | C | char.c:396, 410, 422-426 | zeroing loop should be `memset`; two stale `// TODO: Fix return value` comments | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_resize` (both overloads) — char.c:432, 518
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>RZ-8</nobr></code> | S2 | char.c:434-444, 520-530 | both overloads reject a null-buffer vector with `ERR_BUF_NULL` before the `_internal_size == 0` branch that would have materialized one, so `resize` cannot be the first call on a blank vector. `push_back` can. **ASan: `create(NULL,0)` then `resize(0,4)` returns 21** and the vector is still empty, where `push_back` four times would have worked. Same shape as PB-17, opposite direction | OPEN |
|
|
||||||
| <code><nobr>RZ-3</nobr></code> | S2 | char.c:456, 471, 478, 497, 540, 557, 569, 579| the `max_size` save/restore is load-bearing (it undoes `reserve`'s cap) but looks removable. Nothing documents that | OPEN |
|
|
||||||
| <code><nobr>RZ-1</nobr></code> | S2 | char.c:442-446, 528-532| `size == _internal_size` returns `ERR_OUT_OF_BOUNDS` for a legitimate no-op; the code is also semantically wrong | OPEN |
|
|
||||||
| <code><nobr>RZ-4</nobr></code> | S3 | char.c:501-504 vs 583-586| 3-arg fills the discarded tail with `val`, 2-arg with `'\0'`. `data()` exposes the difference | OPEN |
|
|
||||||
| <code><nobr>RZ-2</nobr></code> | S3 | char.c:481, 567 | unguarded `tmpcp *= 2` wraps on overflow. Defensive | OPEN |
|
|
||||||
| <code><nobr>RZ-5</nobr></code> | C | char.c:462, 492, 548 | dead post-`reserve` capacity checks; `reserve` always assigns `capacity` to its argument exactly | OPEN |
|
|
||||||
| <code><nobr>RZ-6</nobr></code> | C | char.c:432-515 vs 518-597 | two ~84-line near-identical bodies, with the growth blocks copy-pasted between them | OPEN |
|
|
||||||
| <code><nobr>RZ-7</nobr></code> | C | char.c:444, 467, 501, 508, 530, 553, 583, 590| fill loops should be `memset`; misleading `LOG("ERR :- ...")` on what is now a no-op | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_assign` (both overloads) — char.c:600, 652
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>AS-1</nobr></code> | S2 | char.c:630, 668 | fails on an empty destination, via ER-1. Fatal now because status is propagated; the immutable version discarded it and continued | OPEN |
|
|
||||||
| <code><nobr>AS-2</nobr></code> | S2 | char.c:624-647, 661-687| not atomic: `erase` → `reserve` → `push_back` loop. Reserve failure leaves the destination wiped; a `push_back` failure mid-loop leaves it partially filled | OPEN |
|
|
||||||
| <code><nobr>AS-3</nobr></code> | S2 | char.c:624, 662, 679| no `> _internal_max_size` guard on the assign count | OPEN |
|
|
||||||
| <code><nobr>AS-4</nobr></code> | S2 | char.c:635, 673 | the internal `reserve` caps `max_size` at the assign count with no save/restore, which `resize` does have | OPEN |
|
|
||||||
| <code><nobr>AS-6</nobr></code> | C | char.c:600-649 vs 652-688 | near-duplicate overloads differing only in the value source | OPEN |
|
|
||||||
| <code><nobr>AS-7</nobr></code> | S3 | char.c:642 | no check that `at()` succeeded before pushing its result. Currently correct **only** because the guards at char.c:611-618 and char.c:624 happen to make every index in range and the buffer non-null. Removing or loosening either guard turns this into AT-1's data-corruption case | OPEN |
|
|
||||||
|
|
||||||
### `_vec_char_insert` (all three overloads) — char.c:691, 726, 759
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>IN-1</nobr></code> | S1 | char.c:779 | inverted check: `iter_end > iter_start` should be `iter_end <= iter_start`, so every valid non-empty range is rejected and only an empty range is accepted | OPEN |
|
|
||||||
| <code><nobr>IN-2</nobr></code> | S1 | char.c:779 | that clause short-circuits first, so the `iter_end > iterator->_internal_size` bound never fires | OPEN |
|
|
||||||
| <code><nobr>IN-4</nobr></code> | S2 | char.c:742, 747-754 | no `max_size` pre-check, so an oversized `amount` partially inserts and then fails, leaving the vector half-modified | OPEN |
|
|
||||||
| <code><nobr>IN-6</nobr></code> | S3 | char.c:747 | `iter + amount` can overflow `size_t` | OPEN |
|
|
||||||
| <code><nobr>IN-5</nobr></code> | S3 | char.c:742 | `amount <= 0` on a `size_t` is always just `== 0` | OPEN |
|
|
||||||
| <code><nobr>IN-8</nobr></code> | S2 | char.c:747-754, 793 | the loop copies via the raw `iterator->_internal_arr[i]` rather than a bounds-checked accessor. It is **unreachable today** only because IN-1's inversion makes `iter_end <= iter_start` always true, so the loop never runs. It becomes a live out-of-bounds read the moment IN-1 is fixed, unless IN-2 is fixed in the same change | OPEN |
|
|
||||||
| <code><nobr>IN-9</nobr></code> | C | char.c:747-754 | O(amount²) loop of single inserts where one grow + `memmove` would do | OPEN |
|
|
||||||
|
|
||||||
### `utils.h` / `utils.c`
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>UT-2</nobr></code> | S1 | utils.c:3-12 | indices 0 and 1 are never assigned, so `error_messages[0]` and `[1]` are `NULL`. `LOGERROR(SUCCESS)` prints `%s` of `NULL`, and both are values functions return. Latent only because no caller exists yet | OPEN |
|
|
||||||
| <code><nobr>UT-1</nobr></code> | S2 | utils.h:29 | `SIZE_MAX / sizeof(int)` is what the `char` vector uses, capping it at 1/4 of the usable address space | OPEN |
|
|
||||||
| <code><nobr>UT-3</nobr></code> | S2 | utils.c:3 | `SUCCESS`/`FAILURE` overlap the error-index namespace, so `0` is both "success" and a table slot | OPEN |
|
|
||||||
| <code><nobr>UT-5</nobr></code> | C | utils.h:23 | `DEBUG` prints the literal `DEBUB: `, so char.c:109 — the only `DEBUG` call in the tree, on the clamp path in `push_back` — emits a misspelled prefix | OPEN |
|
|
||||||
| <code><nobr>UT-4</nobr></code> | C | utils.h:7, 17, 20, 22-25, 27, 29 · utils.c:6, 10 | `static const` in a header gives every TU its own copy; `ERR_NULL` is now dead (defined and given a message, never referenced from `char.c`); `ERR_SIZE_ZERO` message mentions `< 0` on a `size_t`; `extern const char*` should be `const char* const[]`; `LOG`/`LOGERROR` are hardwired to stdout and single-arg; `find_len` is UB for pointers; `CAPACITY` is a magic number in a shared header | OPEN |
|
|
||||||
|
|
||||||
### `char.h`
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>CH-9</nobr></code> | S2 | char.h:11-106 (29 identifiers)| every public identifier is reserved by the C standard: `_VecCharInternal` and all 28 `_vec_char_*` functions begin with `_` at file scope, which C11 7.1.3 reserves for the implementation. Undefined behaviour on collision with any libc or third-party name. `clang -Weverything` reports all 28 | OPEN |
|
|
||||||
| <code><nobr>CH-4</nobr></code> | C | char.h:6-8 | `<stdio.h>`/`<stdlib.h>`/`<string.h>` in the header, only needed by the `.c` | OPEN |
|
|
||||||
| <code><nobr>CH-5</nobr></code> | C | char.h | no doc comments on any function, despite the `/**< */` style in utils.h | OPEN |
|
|
||||||
| <code><nobr>CH-7</nobr></code> | C | char.h:22-23 | no `from_cstr` / NUL-termination path for the `char` specialization. See CR-4 | OPEN |
|
|
||||||
| <code><nobr>CH-8</nobr></code> | C | char.h:11-17 | the public struct is named with a `_` prefix and its four fields are named `_internal_*` instead of being `PRIVATE`, so the "internal" contract is expressed only by spelling. Combined with CH-9 this is the whole naming problem | OPEN |
|
|
||||||
| <code><nobr>CH-1</nobr></code> | C | char.h:32 vs char.c:156 | param named `max_size` in the header, `capacity` in the definition | OPEN |
|
|
||||||
| <code><nobr>CH-2</nobr></code> | C | char.h:23-106 | `const` on by-value params throughout (`const size_t size`, `const char val`, `const size_t idx`, …) | OPEN |
|
|
||||||
| <code><nobr>CH-3</nobr></code> | C | char.h | no `size()` accessor, so callers reach into `_internal_size` directly | OPEN |
|
|
||||||
|
|
||||||
### Project
|
|
||||||
|
|
||||||
| ID | Sev | Location | Finding | State |
|
|
||||||
|---|---|---|---|---|
|
|
||||||
| <code><nobr>PR-2</nobr></code> | C | char.c:1-3 | mixed brace style (single-line `if` in `erase`/`front`/`back`/`begin`/`empty` vs expanded blocks); `.clang-format` exists and is not run | OPEN |
|
|
||||||
| <code><nobr>PR-3</nobr></code> | C | char.c:204, 208, 224, 225, 229, 230, 254, 255, 263, 267, 277, 281, 291, 300, 304, 322, 326, 343, 344, 354, 361, 373, 381, 389, 390, 400, 401, 415, 416, 434, 438, 520, 524, 603, 607, 611, 615, 654, 658, 693, 697, 763, 767, 771, 775| `is_valid` called 2-3× per function and logging each time, in every function except `push_back`, `pop_back` and `reserve` — those three hoist | OPEN |
|
|
||||||
| <code><nobr>PR-7</nobr></code> | C | CMakeLists.txt:28, main.c:20-54 | the `test_runner` target exists but `main()` is entirely commented out, so nothing in the tree calls a single function in this tracker. This is the only place a regression in the 10 open S1s could be caught, and it is dead | OPEN |
|
|
||||||
| <code><nobr>PR-4</nobr></code> | C | main.c:23-53 | 100% commented out, references removed API `Vec8_t` and `v1.size` | OPEN |
|
|
||||||
| <code><nobr>PR-5</nobr></code> | C | include/libvec.h:4, CMakeLists.txt:12-14 | empty placeholder; `int`/`float`/`string` are empty dirs already listed as comments in CMakeLists.txt | OPEN |
|
|
||||||
|
|
||||||
## ID map
|
|
||||||
|
|
||||||
`FX-1` … `FX-5` are first-pass IDs. FX-1 was a duplicate of PB-6 and was never
|
|
||||||
given a row.
|
|
||||||
|
|
||||||
| 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 | | `SW-` | swap |
|
|
||||||
| `AC-` | accessors | | `CL-` | clear, print_vec |
|
|
||||||
| `DA-` | data | | `IV-` | is_valid |
|
|
||||||
| `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 | | | |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`PB-1` `PB-2` `PB-4` `PB-6` `PB-7` `FX-2` `FX-3` `FX-4` `FX-5` `PR-1` `CR-7` `CR-8`
|
|
||||||
+17
-8
@@ -5,24 +5,33 @@ 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).
|
||||||
PRIVATE
|
# PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/lib
|
|
||||||
|
|
||||||
# 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
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(libvec_bin src/main.c)
|
add_executable(libvec_bin src/main.c)
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# ==============================================================================
|
||||||
|
# Toolchain & Executables
|
||||||
|
# ==============================================================================
|
||||||
|
LLVM_DIR ?= /opt/homebrew/opt/llvm/bin
|
||||||
|
CC := $(LLVM_DIR)/clang
|
||||||
|
LLVM_PROFDATA := $(LLVM_DIR)/llvm-profdata
|
||||||
|
LLVM_COV := $(LLVM_DIR)/llvm-cov
|
||||||
|
CPPCHECK := cppcheck
|
||||||
|
|
||||||
|
# libstr is populated by CMake's FetchContent (run `cmake -B build` once)
|
||||||
|
LIBSTR_DIR := build/_deps/libstr-src
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Flags & Directories
|
||||||
|
# ==============================================================================
|
||||||
|
CFLAGS := -std=c23 -Wall -Wextra -Wpedantic -Wshadow \
|
||||||
|
-Wconversion -Wsign-conversion \
|
||||||
|
-g -O1 -fno-omit-frame-pointer
|
||||||
|
SAN_FLAGS := -fsanitize=address,undefined
|
||||||
|
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" \
|
||||||
|
UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1"
|
||||||
|
|
||||||
|
CPPCHECK_FLAGS := --enable=all \
|
||||||
|
--inconclusive \
|
||||||
|
--error-exitcode=1 \
|
||||||
|
--check-level=exhaustive \
|
||||||
|
--suppress=missingIncludeSystem \
|
||||||
|
--suppress=unmatchedSuppression \
|
||||||
|
--suppress=unusedFunction \
|
||||||
|
--suppress=staticFunction \
|
||||||
|
--inline-suppr \
|
||||||
|
$(INCLUDES)
|
||||||
|
|
||||||
|
# Sources & Build Directories
|
||||||
|
SRCS := src/lib/int/int.c src/lib/utils/utils.c
|
||||||
|
TEST_SRC := tests/test_learn.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
|
||||||
|
CACHE_DIR := tests/cache
|
||||||
|
|
||||||
|
TEST_BIN := $(BIN_DIR)/test_learn_runner
|
||||||
|
TSAN_BIN := $(BIN_DIR)/test_tsan_runner
|
||||||
|
FUZZ_BIN := $(BIN_DIR)/fuzz_char_runner
|
||||||
|
COV_BIN := $(BIN_DIR)/test_cov_runner
|
||||||
|
TEST_STRING_BIN := $(BIN_DIR)/test_string_runner
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Targets & Workflow Rules
|
||||||
|
# ==============================================================================
|
||||||
|
.PHONY: all test test-string sanitize check check-sources analyze cppcheck fuzz cov-build cov clean
|
||||||
|
|
||||||
|
all: test
|
||||||
|
|
||||||
|
$(BIN_DIR) $(CACHE_DIR):
|
||||||
|
@mkdir -p $@
|
||||||
|
|
||||||
|
# --- Compilation Targets ---
|
||||||
|
|
||||||
|
$(TEST_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||||
|
$(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)
|
||||||
|
$(CC) $(CFLAGS) -fsanitize=thread $(INCLUDES) $^ -o $@
|
||||||
|
|
||||||
|
$(FUZZ_BIN): $(SRCS) $(FUZZ_SRC) | $(BIN_DIR)
|
||||||
|
$(CC) $(CFLAGS) -fsanitize=fuzzer,address,undefined $(INCLUDES) $^ -o $@
|
||||||
|
|
||||||
|
# --- Testing & Sanitizer Suites ---
|
||||||
|
|
||||||
|
test: $(TEST_BIN)
|
||||||
|
@echo "=== Running Unit Tests (ASan + UBSan) ==="
|
||||||
|
@$(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)
|
||||||
|
@echo "\n=== [1/2] Running Address + UndefinedBehavior Sanitizers ==="
|
||||||
|
@$(ASAN_ENV) ./$(TEST_BIN)
|
||||||
|
@echo "\n=== [2/2] Running ThreadSanitizer ==="
|
||||||
|
@./$(TSAN_BIN)
|
||||||
|
@echo "\n>>> Sanitizers passed with zero defects."
|
||||||
|
|
||||||
|
# Unified master check: runtime sanitizers, static analyzer, and cppcheck
|
||||||
|
check: sanitize analyze cppcheck
|
||||||
|
@echo "\n=============================================="
|
||||||
|
@echo " ALL TESTS, SANITIZERS & STATIC CHECKS PASSED "
|
||||||
|
@echo "=============================================="
|
||||||
|
|
||||||
|
fuzz: $(FUZZ_BIN)
|
||||||
|
@echo "=== Starting Fuzzer (Press Ctrl+C to stop) ==="
|
||||||
|
@$(ASAN_ENV) ./$(FUZZ_BIN) -max_total_time=60
|
||||||
|
|
||||||
|
# --- Coverage Profiling ---
|
||||||
|
|
||||||
|
cov-build: $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||||
|
$(CC) $(CFLAGS) $(SAN_FLAGS) -fprofile-instr-generate -fcoverage-mapping $(INCLUDES) $^ -o $(COV_BIN)
|
||||||
|
|
||||||
|
cov: cov-build | $(CACHE_DIR)
|
||||||
|
@echo "=== Recording Coverage Profile Data ==="
|
||||||
|
@$(ASAN_ENV) LLVM_PROFILE_FILE="$(CACHE_DIR)/test_char.profdata_raw" ./$(COV_BIN)
|
||||||
|
@$(LLVM_PROFDATA) merge -sparse $(CACHE_DIR)/test_char.profdata_raw -o $(CACHE_DIR)/test_char.profdata
|
||||||
|
@echo "\n=== Line & Branch Coverage Report: src/lib/char/char.c ==="
|
||||||
|
@$(LLVM_COV) report $(COV_BIN) -instr-profile=$(CACHE_DIR)/test_char.profdata src/lib/char/char.c
|
||||||
|
@$(LLVM_COV) show $(COV_BIN) -instr-profile=$(CACHE_DIR)/test_char.profdata src/lib/char/char.c --format=html > coverage.html
|
||||||
|
@echo "\nDetailed HTML report written to coverage.html."
|
||||||
|
|
||||||
|
# --- Static Analysis & Object Checking ---
|
||||||
|
|
||||||
|
check-sources: | $(BIN_DIR)
|
||||||
|
@echo "=== Compiling Sources to Object Files (ASan + UBSan) ==="
|
||||||
|
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -c src/lib/char/char.c -o $(BIN_DIR)/char.o
|
||||||
|
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -c src/lib/utils/utils.c -o $(BIN_DIR)/utils.o
|
||||||
|
@echo "Library sources compiled cleanly."
|
||||||
|
|
||||||
|
analyze:
|
||||||
|
@echo "=== Running Clang Static Analyzer ==="
|
||||||
|
@$(CC) $(CFLAGS) $(INCLUDES) \
|
||||||
|
--analyze \
|
||||||
|
-Xanalyzer -analyzer-output=text \
|
||||||
|
-Xanalyzer -analyzer-checker=core,unix,deadcode,security \
|
||||||
|
$(SRCS)
|
||||||
|
@echo "Clang Static Analyzer complete: zero defects."
|
||||||
|
|
||||||
|
cppcheck:
|
||||||
|
@echo "=== Running Cppcheck Static Analysis ==="
|
||||||
|
@$(CPPCHECK) $(CPPCHECK_FLAGS) include/ src/
|
||||||
|
@echo "Cppcheck passed with zero defects."
|
||||||
|
|
||||||
|
# --- Housekeeping ---
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BIN_DIR)/* $(CACHE_DIR)/* coverage.html
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
||||||
|
|
||||||
|
#define ERROR_LIST(X) \
|
||||||
|
X(SUCCESS, 0, "No Errors Found") \
|
||||||
|
X(ERR_ALLOC_FAIL, (1u << 0), "Alloc :- Failed to allocate") \
|
||||||
|
X(ERR_VEC_NULL, (1u << 1), "Vector :- Given vector is null") \
|
||||||
|
X(ERR_BUF_NULL, (1u << 2), "Buffer :- NULL") \
|
||||||
|
X(ERR_SIZE_ZERO, (1u << 3), \
|
||||||
|
"Size :- Size is or is less than 0 or invalid") \
|
||||||
|
X(ERR_OUT_OF_BOUNDS, (1u << 4), "Bounds:- Value is out of bounds") \
|
||||||
|
X(ERR_DOUBLE_BUF, (1u << 5), \
|
||||||
|
"Buffer :- Both buffers are copies of each other") \
|
||||||
|
X(ERR_SIZE_OVERFLOW, (1u << 6), \
|
||||||
|
"Max :- Vector Max value is overloaded") \
|
||||||
|
X(ERR_ORIGIN_UNALTERABLE, (1u << 7), \
|
||||||
|
"Origin :- Origin is non-null and cannot be overridden") \
|
||||||
|
X(ERR_STR_NULL, (1u << 8), "String :- String is null value") \
|
||||||
|
X(ERR_ERR_T_NULL, (1u << 9), "ERR_T :- Passed error is null")
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
#define X(name, val, desc) name = (val),
|
||||||
|
ERROR_LIST(X)
|
||||||
|
#undef X
|
||||||
|
} ERROR_CODES;
|
||||||
|
|
||||||
|
/* NOTE
|
||||||
|
* Value is the return value for functions like _vec_char_capacity
|
||||||
|
* Err is the unsigned bit range for all the errors tracked
|
||||||
|
* origin is a string for where the bug started and IS CHANGED ONLY WHEN NULL
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int flags;
|
||||||
|
char* origin; // Where the main bug started
|
||||||
|
} err_t;
|
||||||
|
|
||||||
|
#define ERR_T_INIT { .flags = 0, .origin = NULL }
|
||||||
|
#define VEC_INIT \
|
||||||
|
{ .array = NULL, .size = 0, .capacity = 0, .max_size = VEC_MAX }
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_print_errs(const err_t err);
|
||||||
|
|
||||||
|
void
|
||||||
|
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 DEBUG(msg) printf("DEBUG: %s\n", msg) /**< Print debug message*/
|
||||||
|
#define find_len(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
#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,804 +0,0 @@
|
|||||||
#include "char.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "utils/utils.h"
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_vec_char_raise_err(const _VecCharInternal* ptr, unsigned int mask)
|
|
||||||
{
|
|
||||||
unsigned int res = SUCCESS;
|
|
||||||
res |= mask;
|
|
||||||
if (ptr == nullptr) res |= ERR_VEC_NULL;
|
|
||||||
if (ptr->_internal_arr == nullptr) res |= ERR_BUF_NULL;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
_VecCharInternal
|
|
||||||
_vec_char_create(const char* src, const size_t size)
|
|
||||||
{
|
|
||||||
unsigned int err = 0;
|
|
||||||
_VecCharInternal self = {
|
|
||||||
._internal_arr = NULL,
|
|
||||||
._internal_size = 0,
|
|
||||||
._internal_capacity = CAPACITY,
|
|
||||||
._internal_max_size = VEC_MAX,
|
|
||||||
};
|
|
||||||
if (size >= self._internal_max_size)
|
|
||||||
{
|
|
||||||
LOG("If you need more memory to start, create a blank and "
|
|
||||||
"reserve.");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
if (self._internal_capacity < size)
|
|
||||||
{
|
|
||||||
size_t dst_cap = self._internal_capacity;
|
|
||||||
while (dst_cap < size && dst_cap * 2 < self._internal_max_size)
|
|
||||||
dst_cap *= 2;
|
|
||||||
self._internal_capacity = (dst_cap < size) ? size : dst_cap;
|
|
||||||
}
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
self._internal_arr =
|
|
||||||
calloc(self._internal_capacity, sizeof(char));
|
|
||||||
err = _vec_char_raise_err(&self, err);
|
|
||||||
if (!(err & SUCCESS))
|
|
||||||
{
|
|
||||||
self._internal_arr = NULL;
|
|
||||||
vec_print_errs(err);
|
|
||||||
free(self._internal_arr);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!src) err |= ERR_BUF_NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
self._internal_arr[i] = src[i];
|
|
||||||
self._internal_size++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
// size_t
|
|
||||||
// _vec_char_push_back(_VecCharInternal* ptr, const char val)
|
|
||||||
// {
|
|
||||||
// char* res;
|
|
||||||
// size_t _ptr_err = _vec_char_is_valid(ptr);
|
|
||||||
// if (_ptr_err == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (ptr->_internal_size + 1 > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_MAX_PASSED);
|
|
||||||
// return ERR_MAX_PASSED;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (_ptr_err == ERR_BUF_NULL && ptr->_internal_size == 0)
|
|
||||||
// {
|
|
||||||
// res = calloc(1, sizeof(char));
|
|
||||||
// if (!res)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_arr = res;
|
|
||||||
// ptr->_internal_arr[0] = val;
|
|
||||||
// ptr->_internal_size++;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else if (ptr->_internal_size + 1 > ptr->_internal_capacity)
|
|
||||||
// {
|
|
||||||
// size_t dst_cap = ptr->_internal_capacity * 2;
|
|
||||||
// if (dst_cap > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_capacity = ptr->_internal_max_size;
|
|
||||||
// res = realloc(ptr->_internal_arr,
|
|
||||||
// ptr->_internal_capacity * sizeof(char));
|
|
||||||
// DEBUG(
|
|
||||||
// "Capacity cannot be grown any further due "
|
|
||||||
// "to hitting max size");
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// res =
|
|
||||||
// realloc(ptr->_internal_arr, dst_cap * sizeof(char));
|
|
||||||
// ptr->_internal_capacity = dst_cap;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!res)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// res = ptr->_internal_arr;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_arr = res;
|
|
||||||
// ptr->_internal_arr[ptr->_internal_size] = val;
|
|
||||||
// ptr->_internal_size++;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_pop_back(_VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// size_t _ptr_err = _vec_char_is_valid(ptr);
|
|
||||||
// if (_ptr_err == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_ptr_err == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size < 1)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_SIZE_ZERO);
|
|
||||||
// return ERR_SIZE_ZERO;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ptr->_internal_arr[ptr->_internal_size - 1] = '\0';
|
|
||||||
// ptr->_internal_size--;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_reserve(_VecCharInternal* ptr, const size_t capacity)
|
|
||||||
// {
|
|
||||||
// char* res;
|
|
||||||
// size_t _ptr_err = _vec_char_is_valid(ptr);
|
|
||||||
// if (capacity == 0)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_SIZE_ZERO);
|
|
||||||
// return ERR_SIZE_ZERO;
|
|
||||||
// }
|
|
||||||
// if (_ptr_err == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_ptr_err == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// res = calloc(ptr->_internal_capacity, sizeof(char));
|
|
||||||
// if (!res)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if (_ptr_err == SUCCESS)
|
|
||||||
// {
|
|
||||||
// res = realloc(ptr->_internal_arr, capacity * sizeof(char));
|
|
||||||
// if (!res)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size > capacity)
|
|
||||||
// {
|
|
||||||
// for (size_t i = capacity; i < ptr->_internal_size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = '\0';
|
|
||||||
// }
|
|
||||||
// ptr->_internal_size = capacity;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ptr->_internal_arr = res;
|
|
||||||
// ptr->_internal_capacity = capacity;
|
|
||||||
// ptr->_internal_max_size = capacity;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_shrink_to_fit(_VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// size_t _ptr_err = _vec_char_is_valid(ptr);
|
|
||||||
// if (_ptr_err == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_VECTOR_NULL);
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_ptr_err == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_BUF_NULL);
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (_ptr_err == 0)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_SIZE_ZERO);
|
|
||||||
// return ERR_SIZE_ZERO;
|
|
||||||
// }
|
|
||||||
// return _vec_char_reserve(ptr, ptr->_internal_size);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_swap(_VecCharInternal* ptr1, _VecCharInternal* ptr2)
|
|
||||||
// {
|
|
||||||
// _VecCharInternal self = _vec_char_create(nullptr, 0);
|
|
||||||
// size_t _ptr1_err = _vec_char_is_valid(ptr1);
|
|
||||||
// size_t _ptr2_err = _vec_char_is_valid(ptr2);
|
|
||||||
// if (_ptr1_err == ERR_VECTOR_NULL || _ptr2_err == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_VECTOR_NULL);
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_ptr1_err == ERR_BUF_NULL || _ptr2_err == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_BUF_NULL);
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// self._internal_arr = ptr1->_internal_arr;
|
|
||||||
// ptr1->_internal_arr = ptr2->_internal_arr;
|
|
||||||
// ptr2->_internal_arr = self._internal_arr;
|
|
||||||
//
|
|
||||||
// self._internal_capacity = ptr1->_internal_capacity;
|
|
||||||
// self._internal_size = ptr1->_internal_size;
|
|
||||||
// self._internal_max_size = ptr1->_internal_max_size;
|
|
||||||
// ptr1->_internal_capacity = ptr2->_internal_capacity;
|
|
||||||
// ptr1->_internal_size = ptr2->_internal_size;
|
|
||||||
// ptr1->_internal_max_size = ptr2->_internal_max_size;
|
|
||||||
//
|
|
||||||
// ptr2->_internal_capacity = self._internal_capacity;
|
|
||||||
// ptr2->_internal_size = self._internal_size;
|
|
||||||
// ptr2->_internal_max_size = self._internal_max_size;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// char*
|
|
||||||
// _vec_char_data(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL ||
|
|
||||||
// _vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// return nullptr;
|
|
||||||
// return &ptr->_internal_arr[0];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_capacity(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// return ptr->_internal_capacity;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_max_size(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// return ptr->_internal_max_size;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void
|
|
||||||
// _vec_char_delete(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == SUCCESS)
|
|
||||||
// {
|
|
||||||
// free((void*)ptr->_internal_arr);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_clear(_VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size > 0)
|
|
||||||
// {
|
|
||||||
// for (size_t i = 0; i < ptr->_internal_size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = 0;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_size = 0;
|
|
||||||
// }
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// char
|
|
||||||
// _vec_char_at(const _VecCharInternal* ptr, const size_t idx)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (idx >= ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// fprintf(stderr,
|
|
||||||
// "At Index: [%zu] is out of bounds for size: [%zu]\n",
|
|
||||||
// idx, ptr->_internal_size);
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
// return ptr->_internal_arr[idx];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void
|
|
||||||
// _vec_char_print_vec(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL ||
|
|
||||||
// _vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// return;
|
|
||||||
// for (size_t i = 0; i < ptr->_internal_size; i++)
|
|
||||||
// printf("%c ", ptr->_internal_arr[i]);
|
|
||||||
// printf("\n");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_begin(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == SUCCESS) return 0;
|
|
||||||
// return FAILURE;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_end(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == SUCCESS)
|
|
||||||
// {
|
|
||||||
// if (ptr->_internal_size != 0)
|
|
||||||
// return (int)(ptr->_internal_size - 1);
|
|
||||||
// else return FAILURE;
|
|
||||||
// }
|
|
||||||
// return FAILURE;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// char
|
|
||||||
// _vec_char_front(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL) return FAILURE;
|
|
||||||
// if (ptr->_internal_size == 0) return FAILURE;
|
|
||||||
// return _vec_char_at(ptr, 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// char
|
|
||||||
// _vec_char_back(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL) return FAILURE;
|
|
||||||
// if (ptr->_internal_size == 0) return FAILURE;
|
|
||||||
// return _vec_char_at(ptr, ptr->_internal_size - 1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// size_t
|
|
||||||
// _vec_char_empty(const _VecCharInternal* ptr)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL ||
|
|
||||||
// _vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// return FAILURE;
|
|
||||||
// if (ptr->_internal_size == 0) return SUCCESS;
|
|
||||||
// return FAILURE;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // TODO: Fix return value
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_erase(_VecCharInternal* ptr, const size_t iter)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL) return ERR_VECTOR_NULL;
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL) return ERR_BUF_NULL;
|
|
||||||
// if (iter >= ptr->_internal_size) return ERR_OUT_OF_BOUNDS;
|
|
||||||
// memmove(&ptr->_internal_arr[iter], &ptr->_internal_arr[iter + 1],
|
|
||||||
// (ptr->_internal_size - iter - 1) * sizeof(char));
|
|
||||||
// ptr->_internal_arr[ptr->_internal_size - 1] = 0;
|
|
||||||
// ptr->_internal_size--;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // TODO: Fix return value
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_erase(_VecCharInternal* ptr, const size_t iter_start,
|
|
||||||
// const size_t iter_end)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL) return ERR_VECTOR_NULL;
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL) return ERR_BUF_NULL;
|
|
||||||
// if (iter_end > ptr->_internal_size) return ERR_OUT_OF_BOUNDS;
|
|
||||||
// if (iter_start >= iter_end) return ERR_OUT_OF_BOUNDS;
|
|
||||||
// size_t diff = iter_end - iter_start;
|
|
||||||
// memmove(&ptr->_internal_arr[iter_start], &ptr->_internal_arr[iter_end],
|
|
||||||
// (ptr->_internal_size - iter_end) * sizeof(char));
|
|
||||||
// for (size_t i = ptr->_internal_size - diff; i < ptr->_internal_size;
|
|
||||||
// i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = 0;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_size -= diff;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_resize(_VecCharInternal* ptr, const size_t size)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size == size)
|
|
||||||
// {
|
|
||||||
// LOG("ERR :- Ptr size and size are the same");
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else if (size > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_MAX_PASSED);
|
|
||||||
// return ERR_MAX_PASSED;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else if (ptr->_internal_size == 0)
|
|
||||||
// {
|
|
||||||
// size_t max = ptr->_internal_max_size;
|
|
||||||
// size_t res = _vec_char_reserve(ptr, size);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_capacity != size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// for (size_t i = 0; i < size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = '\0';
|
|
||||||
// }
|
|
||||||
// ptr->_internal_max_size = max;
|
|
||||||
// ptr->_internal_size = size;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
// else if (size > ptr->_internal_capacity)
|
|
||||||
// {
|
|
||||||
// size_t tmpcp = ptr->_internal_capacity;
|
|
||||||
// size_t tmpmx = ptr->_internal_max_size;
|
|
||||||
// while (size > tmpcp)
|
|
||||||
// {
|
|
||||||
// tmpcp *= 2;
|
|
||||||
// }
|
|
||||||
// if (tmpcp > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// tmpcp = size;
|
|
||||||
// }
|
|
||||||
// size_t res = _vec_char_reserve(ptr, tmpcp);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_capacity != tmpcp)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_max_size = tmpmx;
|
|
||||||
// }
|
|
||||||
// if (size < ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// for (size_t i = size; i < ptr->_internal_size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = '\0';
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size < size && size <= ptr->_internal_capacity)
|
|
||||||
// {
|
|
||||||
// for (size_t i = ptr->_internal_size; i < size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = '\0';
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ptr->_internal_size = size;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_resize(_VecCharInternal* ptr, const size_t size, const char val)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size == size)
|
|
||||||
// {
|
|
||||||
// LOG("ERR :- Ptr size and size are the same");
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else if (size > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_MAX_PASSED);
|
|
||||||
// return ERR_MAX_PASSED;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else if (ptr->_internal_size == 0)
|
|
||||||
// {
|
|
||||||
// size_t max = ptr->_internal_max_size;
|
|
||||||
// size_t res = _vec_char_reserve(ptr, size);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_capacity != size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// for (size_t i = 0; i < size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = val;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_max_size = max;
|
|
||||||
// ptr->_internal_size = size;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
// else if (size > ptr->_internal_capacity)
|
|
||||||
// {
|
|
||||||
// size_t tmpcp = ptr->_internal_capacity;
|
|
||||||
// size_t tmpmx = ptr->_internal_max_size;
|
|
||||||
// while (size > tmpcp)
|
|
||||||
// {
|
|
||||||
// tmpcp *= 2;
|
|
||||||
// }
|
|
||||||
// if (tmpcp > ptr->_internal_max_size)
|
|
||||||
// {
|
|
||||||
// tmpcp = size;
|
|
||||||
// }
|
|
||||||
// size_t _ptr_err = _vec_char_reserve(ptr, tmpcp);
|
|
||||||
// if (_ptr_err != SUCCESS)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_ALLOC_FAIL);
|
|
||||||
// return ERR_ALLOC_FAIL;
|
|
||||||
// }
|
|
||||||
// ptr->_internal_max_size = tmpmx;
|
|
||||||
// }
|
|
||||||
// if (size < ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// for (size_t i = size; i < ptr->_internal_size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = val;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_size < size && size <= ptr->_internal_capacity)
|
|
||||||
// {
|
|
||||||
// for (size_t i = ptr->_internal_size; i < size; i++)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = val;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ptr->_internal_size = size;
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_assign(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
// const size_t iter_start, const size_t iter_end)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(iterator) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(iterator) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_arr == iterator->_internal_arr)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_DOUBLE_BUF);
|
|
||||||
// return ERR_DOUBLE_BUF;
|
|
||||||
// }
|
|
||||||
// if (iterator->_internal_size < iter_end || iter_end <= iter_start)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_OUT_OF_BOUNDS);
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
// size_t res =
|
|
||||||
// _vec_char_erase(ptr, _vec_char_begin(ptr), _vec_char_end(ptr) + 1);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// res = _vec_char_reserve(ptr, (iter_end - iter_start));
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// for (size_t i = iter_start; i < iter_end; i++)
|
|
||||||
// {
|
|
||||||
// res = _vec_char_push_back(ptr, _vec_char_at(iterator, i));
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_assign(_VecCharInternal* ptr, const size_t amount, const char val)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (amount == 0)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_SIZE_ZERO);
|
|
||||||
// return ERR_SIZE_ZERO;
|
|
||||||
// }
|
|
||||||
// size_t res =
|
|
||||||
// _vec_char_erase(ptr, _vec_char_begin(ptr), _vec_char_end(ptr) + 1);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// res = _vec_char_reserve(ptr, amount);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (size_t i = 0; i < amount; i++)
|
|
||||||
// {
|
|
||||||
// res = _vec_char_push_back(ptr, val);
|
|
||||||
// if (res != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return res;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_insert(_VecCharInternal* ptr, const size_t iter, const char val)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_max_size < ptr->_internal_size + 1)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_MAX_PASSED);
|
|
||||||
// return ERR_MAX_PASSED;
|
|
||||||
// }
|
|
||||||
// if (iter > ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_OUT_OF_BOUNDS);
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
// size_t _ptr_err = _vec_char_push_back(ptr, 0);
|
|
||||||
// if (_ptr_err != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return _ptr_err;
|
|
||||||
// }
|
|
||||||
// for (size_t i = ptr->_internal_size - 1; i > iter; i--)
|
|
||||||
// {
|
|
||||||
// ptr->_internal_arr[i] = ptr->_internal_arr[i - 1];
|
|
||||||
// }
|
|
||||||
// ptr->_internal_arr[iter] = val;
|
|
||||||
//
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_insert(_VecCharInternal* ptr, const size_t iter, const size_t
|
|
||||||
// amount, const char val)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (iter > ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_OUT_OF_BOUNDS);
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
// if (amount <= 0)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_SIZE_ZERO);
|
|
||||||
// return ERR_SIZE_ZERO;
|
|
||||||
// }
|
|
||||||
// for (size_t i = iter; i < iter + amount; i++)
|
|
||||||
// {
|
|
||||||
// size_t _ptr_err = _vec_char_insert(ptr, i, val);
|
|
||||||
// if (_ptr_err != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return _ptr_err;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// __attribute__((overloadable)) size_t
|
|
||||||
// _vec_char_insert(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
// const size_t iter, const size_t iter_start,
|
|
||||||
// const size_t iter_end)
|
|
||||||
// {
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(ptr) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(iterator) == ERR_VECTOR_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_VECTOR_NULL;
|
|
||||||
// }
|
|
||||||
// if (_vec_char_is_valid(iterator) == ERR_BUF_NULL)
|
|
||||||
// {
|
|
||||||
// return ERR_BUF_NULL;
|
|
||||||
// }
|
|
||||||
// if (iter_end > iter_start || iter_end > iterator->_internal_size ||
|
|
||||||
// iter > ptr->_internal_size)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_OUT_OF_BOUNDS);
|
|
||||||
// return ERR_OUT_OF_BOUNDS;
|
|
||||||
// }
|
|
||||||
// if (ptr->_internal_arr == iterator->_internal_arr)
|
|
||||||
// {
|
|
||||||
// LOGERROR(ERR_DOUBLE_BUF);
|
|
||||||
// return ERR_DOUBLE_BUF;
|
|
||||||
// }
|
|
||||||
// for (size_t i = iter_start; i < iter_end; i++)
|
|
||||||
// {
|
|
||||||
// size_t _ptr_err = _vec_char_insert(ptr, iter + (i - iter_start),
|
|
||||||
// iterator->_internal_arr[i]);
|
|
||||||
// if (_ptr_err != SUCCESS)
|
|
||||||
// {
|
|
||||||
// return _ptr_err;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return SUCCESS;
|
|
||||||
// }
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
#ifndef CHAR_H
|
|
||||||
#define CHAR_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <utils/utils.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char* _internal_arr;
|
|
||||||
size_t _internal_size;
|
|
||||||
size_t _internal_capacity;
|
|
||||||
size_t _internal_max_size;
|
|
||||||
} _VecCharInternal;
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_vec_char_raise_err(const _VecCharInternal* ptr, unsigned int mask);
|
|
||||||
|
|
||||||
_VecCharInternal
|
|
||||||
_vec_char_create(const char* src, const size_t size);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_push_back(_VecCharInternal* vec, const char val);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_pop_back(_VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_reserve(_VecCharInternal* ptr, const size_t max_size);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_shrink_to_fit(_VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_swap(_VecCharInternal* ptr, _VecCharInternal* ptr_other);
|
|
||||||
|
|
||||||
char*
|
|
||||||
_vec_char_data(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_capacity(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_max_size(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_delete(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_clear(_VecCharInternal* ptr);
|
|
||||||
|
|
||||||
char
|
|
||||||
_vec_char_at(const _VecCharInternal* ptr, const size_t idx);
|
|
||||||
|
|
||||||
void
|
|
||||||
_vec_char_print_vec(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_begin(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_end(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
char
|
|
||||||
_vec_char_front(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
char
|
|
||||||
_vec_char_back(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
size_t
|
|
||||||
_vec_char_empty(const _VecCharInternal* ptr);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_erase(_VecCharInternal* ptr, const size_t iter);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_erase(_VecCharInternal* ptr, const size_t iter_start,
|
|
||||||
const size_t iter_end);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_resize(_VecCharInternal* ptr, const size_t size);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_resize(_VecCharInternal* ptr, const size_t size, const char val);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_assign(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
const size_t iter_start, const size_t iter_end);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_assign(_VecCharInternal* ptr, const size_t amount, const char val);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const size_t iter, const char val);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const size_t iter, const size_t amount,
|
|
||||||
const char val);
|
|
||||||
|
|
||||||
__attribute__((overloadable)) size_t
|
|
||||||
_vec_char_insert(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
|
||||||
const size_t iter, const size_t iter_start,
|
|
||||||
const size_t iter_end);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +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:
|
|
||||||
"Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
vec_print_errs(const unsigned int err)
|
|
||||||
{
|
|
||||||
if (err == SUCCESS)
|
|
||||||
{
|
|
||||||
printf("%s", vec_get_error_desc(SUCCESS));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
#define X(name, val, desc) \
|
|
||||||
if ((val) != 0 && ((err) & (val))) \
|
|
||||||
{ \
|
|
||||||
printf("%s\n", vec_get_error_desc(name)); \
|
|
||||||
}
|
|
||||||
ERROR_LIST(X)
|
|
||||||
#undef X
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#ifndef UTILS_H
|
|
||||||
#define UTILS_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define CAPACITY 1024
|
|
||||||
#define VEC_FAULT_BITS 32
|
|
||||||
|
|
||||||
#define ERROR_LIST(X) \
|
|
||||||
X(SUCCESS, 0, "No Errors Found") \
|
|
||||||
X(ERR_ALLOC_FAIL, (1u << 1), "Calloc :- Failed to allocate") \
|
|
||||||
X(ERR_VEC_NULL, (1u << 2), "Vector :- Given vector is null") \
|
|
||||||
X(ERR_BUF_NULL, (1u << 3), "Buffer :- NULL") \
|
|
||||||
X(ERR_SIZE_ZERO, (1u << 4), \
|
|
||||||
"Size :- Size is or is less than 0 or invalid") \
|
|
||||||
X(ERR_OUT_OF_BOUNDS, (1u << 5), "Bounds:- Value is out of bounds") \
|
|
||||||
X(ERR_DOUBLE_BUF, (1u << 6), \
|
|
||||||
"Buffer :- Both buffers are copies of each other") \
|
|
||||||
X(ERR_SIZE_OVERFLOW, (1u << 7), "Max :- Vector Max value is overloaded")
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
#define X(name, val, desc) name = (val),
|
|
||||||
ERROR_LIST(X)
|
|
||||||
#undef X
|
|
||||||
} ERROR_CODES;
|
|
||||||
|
|
||||||
const char*
|
|
||||||
vec_get_error_desc(ERROR_CODES err);
|
|
||||||
|
|
||||||
void
|
|
||||||
vec_print_errs(const unsigned int err);
|
|
||||||
|
|
||||||
#define LOG(msg) printf("LOG: %s\n", msg) /**< Print log message*/
|
|
||||||
#define DEBUG(msg) printf("DEBUB: %s\n", msg) /**< Print debug message*/
|
|
||||||
#define LOGERROR(error_code) \
|
|
||||||
printf("ERROR: %s\n", \
|
|
||||||
error_messages[error_code]) /**< Print log error message*/
|
|
||||||
|
|
||||||
#define find_len(arr) sizeof(arr) / sizeof(arr[0])
|
|
||||||
|
|
||||||
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include <libvec.h>
|
|
||||||
+19
-170
@@ -6,191 +6,40 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* 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.h>
|
#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);
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char* _internal_arr;
|
|
||||||
size_t _internal_size;
|
|
||||||
size_t _internal_capacity;
|
|
||||||
size_t _internal_max_size;
|
|
||||||
} _VecCharInternal;
|
|
||||||
|
|
||||||
/* NOTE
|
|
||||||
* Value is the return value for functions like _vec_char_capacity
|
|
||||||
* Err is the unsigned bit range for all the errors tracked
|
|
||||||
* origin is a string for where the bug started and IS CHANGED ONLY WHEN NULL
|
|
||||||
* */
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int err;
|
|
||||||
size_t value;
|
|
||||||
char* origin; // Where the main bug started
|
|
||||||
} _err_t;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_vec_char_raise_err(const _VecCharInternal* ptr, unsigned int mask)
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned int res = SUCCESS;
|
|
||||||
res |= mask;
|
|
||||||
if (ptr == nullptr) res |= ERR_VEC_NULL;
|
|
||||||
if (ptr->_internal_arr == nullptr) res |= ERR_BUF_NULL;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
_VecCharInternal
|
|
||||||
_vec_char_create(const char* src, const size_t size)
|
|
||||||
{
|
|
||||||
unsigned int err = 0;
|
|
||||||
_VecCharInternal self = {
|
|
||||||
._internal_arr = NULL,
|
|
||||||
._internal_size = 0,
|
|
||||||
._internal_capacity = CAPACITY,
|
|
||||||
._internal_max_size = VEC_MAX,
|
|
||||||
};
|
|
||||||
if (size >= self._internal_max_size)
|
|
||||||
{
|
|
||||||
LOG("If you need more memory to start, create a blank and "
|
|
||||||
"reserve.");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
if (self._internal_capacity < size)
|
|
||||||
{
|
|
||||||
size_t dst_cap = self._internal_capacity;
|
|
||||||
while (dst_cap < size && dst_cap * 2 < self._internal_max_size)
|
|
||||||
dst_cap *= 2;
|
|
||||||
self._internal_capacity = (dst_cap < size) ? size : dst_cap;
|
|
||||||
}
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
self._internal_arr =
|
|
||||||
calloc(self._internal_capacity, sizeof(char));
|
|
||||||
err = _vec_char_raise_err(&self, err);
|
|
||||||
if ((err & SUCCESS) == 1)
|
|
||||||
{
|
|
||||||
self._internal_arr = NULL;
|
|
||||||
vec_print_errs(err);
|
|
||||||
free(self._internal_arr);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!src) err |= ERR_BUF_NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
self._internal_arr[i] = src[i];
|
|
||||||
self._internal_size++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vec_print_errs(err);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
char res[4] = { 'a', 'b', 'c', 'd' };
|
// TODO:
|
||||||
_VecCharInternal v1 = _vec_char_create(nullptr, 3);
|
//
|
||||||
unsigned int mark = 1 << 0;
|
// Fix the error checking because you make a status to hold all local
|
||||||
_err_t err = { 0, 0, "Te" };
|
// errors but then in some cases you or them to the main err handler and
|
||||||
_vec_update_origin(&err, "Test");
|
// if the error doesnt need to be there like a good error but one that
|
||||||
printf("%s", err.origin);
|
// exists (i.e push_back getting a blank array), then you will have a
|
||||||
// for (int i = 0; i < VEC_FAULT_BITS; i++)
|
// bloated and broken error handler
|
||||||
// {
|
//
|
||||||
// print_bits(mark);
|
// Your pop back is a great example of how to handle it and is a clean
|
||||||
// mark <<= 1;
|
// if statement as a header to all functions.
|
||||||
// }
|
// char res[4] = { 'a', 'b', 'c', 'd' };
|
||||||
// const char* str = vec_get_error_desc(ERR_ALLOC_FAIL);
|
err_t status = ERR_T_INIT;
|
||||||
// const unsigned int error = ERR_BUF_NULL;
|
status.flags |= ERR_BUF_NULL | ERR_VEC_NULL | ERR_STR_NULL;
|
||||||
// if (!(ERR_ALLOC_FAIL & SUCCESS))
|
|
||||||
// {
|
|
||||||
// printf("Hello\n");
|
|
||||||
// }
|
|
||||||
// printf("%s", str);
|
|
||||||
// char ar1[] = { '1', '2', '3', '4' };
|
|
||||||
// char ar2[] = { 'a', 'b', 'c', 'd' };
|
|
||||||
// Vec8_t v1 = create(ar2, find_len(ar2));
|
|
||||||
// v1 = reserve(&v1, 9);
|
|
||||||
// print_vec(&v1);
|
|
||||||
// v1 = insert(&v1, 1, 'x');
|
|
||||||
// v1 = resize(&v1, 12);
|
|
||||||
// print_vec(&v1);
|
|
||||||
// v2 = resize(&v2, 3);
|
|
||||||
|
|
||||||
// print_vec(&v2);
|
unsigned int mask = 0;
|
||||||
|
mask = ERR_BUF_NULL ^ status.flags;
|
||||||
|
|
||||||
// if (swap(&v1, &v2))
|
vec_print_bits(mask);
|
||||||
// {
|
vec_print_bits(status.flags);
|
||||||
// print_vec(&v1);
|
vec_print_errs(status);
|
||||||
// print_vec(&v2);
|
|
||||||
// }
|
|
||||||
// Vec8_t v1 = create(nullptr, 0);
|
|
||||||
// v1 = reserve(&v1, 10);
|
|
||||||
// v1 = pop_back(&v1);
|
|
||||||
// for (int i = 0; i < 10; i++)
|
|
||||||
// {
|
|
||||||
// v1 = push_back(&v1, 'a');
|
|
||||||
// }
|
|
||||||
// print_vec(&v1);
|
|
||||||
// printf("SIZE: %zu\n", v1.size);
|
|
||||||
// v1 = push_back(&v1, 'a');
|
|
||||||
// print_vec(&v1);
|
|
||||||
// printf("SIZE: %zu\n", v1.size);
|
|
||||||
// delete(&v1);
|
|
||||||
// delete(&v2);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+938
@@ -0,0 +1,938 @@
|
|||||||
|
#include "libstr/string.h"
|
||||||
|
|
||||||
|
#include <libvec/string.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_string* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) size_t
|
||||||
|
__null_check(const String* ptr, err_t* status)
|
||||||
|
{
|
||||||
|
if (status == nullptr)
|
||||||
|
{
|
||||||
|
return ERR_ERR_T_NULL;
|
||||||
|
}
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_STR_NULL;
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
if (ptr->data == nullptr)
|
||||||
|
{
|
||||||
|
status->flags |= ERR_BUF_NULL;
|
||||||
|
}
|
||||||
|
return status->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_print_vec(const vec_string* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
if (__null_check(ptr, err) != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
printf("%s ", ptr->array[i].data);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_string
|
||||||
|
vec_string_cpy(const String* src, const size_t src_size, err_t* err)
|
||||||
|
{
|
||||||
|
vec_string 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(String));
|
||||||
|
if (self.array == nullptr)
|
||||||
|
{
|
||||||
|
__origin_override(err, "CPY");
|
||||||
|
err->flags |= ERR_ALLOC_FAIL;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
memcpy(self.array, src, src_size * sizeof(String));
|
||||||
|
self.size = src_size;
|
||||||
|
self.capacity = src_size;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_push_back(vec_string* ptr, const String val, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
String* 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(String));
|
||||||
|
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(String));
|
||||||
|
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_string_pop_back(vec_string* 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] = (String)STR_INIT;
|
||||||
|
ptr->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_reserve(vec_string* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
String* res = realloc(ptr->array, capacity * sizeof(String));
|
||||||
|
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_string_shrink_to_fit(vec_string* 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_string_reserve(ptr, ptr->size, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vec_string_swap(vec_string* ptr_a, vec_string* 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_string self = *ptr_a;
|
||||||
|
*ptr_a = *ptr_b;
|
||||||
|
*ptr_b = self;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String*
|
||||||
|
vec_string_data(const vec_string* 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_string_size(const vec_string* 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_string_capacity(const vec_string* 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_string_max_size(const vec_string* 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_string_delete(vec_string* 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_string_clear(vec_string* 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(String)));
|
||||||
|
ptr->size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String*
|
||||||
|
vec_string_at(const vec_string* 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_string_begin(const vec_string* 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_string_end(const vec_string* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
vec_string_front(const vec_string* ptr, err_t* err)
|
||||||
|
{
|
||||||
|
err_t status = ERR_T_INIT;
|
||||||
|
String tmp = STR_INIT;
|
||||||
|
if (__null_check(ptr, &status) != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "FRONT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
if (vec_string_at(ptr, 0, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
return *vec_string_at(ptr, 0, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
vec_string_back(const vec_string* 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 (String)STR_INIT;
|
||||||
|
}
|
||||||
|
if (vec_string_at(ptr, ptr->size - 1, err) == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return (String)STR_INIT;
|
||||||
|
}
|
||||||
|
return *vec_string_at(ptr, ptr->size - 1, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
vec_string_empty(const vec_string* 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 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_erase(vec_string* 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)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ERASE");
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||||
|
(ptr->size - iter - 1) * sizeof(String));
|
||||||
|
ptr->array[ptr->size - 1] = (String)STR_INIT;
|
||||||
|
ptr->size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_erase(vec_string* 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(String));
|
||||||
|
memset(&ptr->array[ptr->size - diff], 0, sizeof(String) * diff);
|
||||||
|
ptr->size -= diff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_resize(vec_string* 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_string_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] = (String)STR_INIT;
|
||||||
|
}
|
||||||
|
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_string_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)
|
||||||
|
{
|
||||||
|
for (size_t i = size; i < ptr->size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = (String)STR_INIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr->size < size && size <= ptr->capacity)
|
||||||
|
{
|
||||||
|
for (size_t i = ptr->size; i < size; i++)
|
||||||
|
{
|
||||||
|
ptr->array[i] = (String)STR_INIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr->size = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_resize(vec_string* ptr, const size_t size, const String 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_string_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_string_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] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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_string_assign(vec_string* ptr, const vec_string* 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;
|
||||||
|
}
|
||||||
|
if (ptr->size > 0)
|
||||||
|
{
|
||||||
|
vec_string_erase(ptr, 0, ptr->size, &status);
|
||||||
|
}
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_string_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++)
|
||||||
|
{
|
||||||
|
String* res = vec_string_at(iterator, i, &status);
|
||||||
|
if (res == nullptr)
|
||||||
|
{
|
||||||
|
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_string_push_back(ptr, *res, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_assign(vec_string* ptr, const size_t amount, const String 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;
|
||||||
|
}
|
||||||
|
if (ptr->size > 0)
|
||||||
|
{
|
||||||
|
vec_string_erase(ptr, vec_string_begin(ptr, &status),
|
||||||
|
vec_string_end(ptr, &status) + 1, &status);
|
||||||
|
}
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vec_string_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_string_push_back(ptr, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "ASSIGN");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((overloadable)) void
|
||||||
|
vec_string_insert(vec_string* ptr, const size_t iter, const String 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)
|
||||||
|
{
|
||||||
|
String* res = malloc(1 * sizeof(String));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
String empty = STR_INIT;
|
||||||
|
vec_string_push_back(ptr, empty, &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_string_insert(vec_string* ptr, const size_t iter, const size_t amount,
|
||||||
|
const String 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 (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_string_insert(ptr, i, val, &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__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)
|
||||||
|
{
|
||||||
|
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_string_insert(ptr, iter + (i - iter_start),
|
||||||
|
iterator->array[i], &status);
|
||||||
|
if (status.flags != 0)
|
||||||
|
{
|
||||||
|
__origin_override(err, "INSERT");
|
||||||
|
err->flags |= status.flags;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
+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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "char/char.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||||
|
{
|
||||||
|
if (size < 2) return 0;
|
||||||
|
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_VecCharInternal vec = VEC_INIT;
|
||||||
|
|
||||||
|
// Use input bytes to drive arbitrary vector operations
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
uint8_t op = data[i] % 5;
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
_vec_char_push_back(&vec, (char)data[i], &err);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
_vec_char_pop_back(&vec, &err);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (vec._internal_size > 0)
|
||||||
|
{
|
||||||
|
size_t idx = (size_t)data[i] %
|
||||||
|
vec._internal_size;
|
||||||
|
_vec_char_erase(&vec, idx, &err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
_vec_char_reserve(&vec, (size_t)data[i], &err);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_vec_char_shrink_to_fit(&vec, &err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_vec_char_delete(&vec, &err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "char/char.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_empty_vector_underflows(void)
|
||||||
|
{
|
||||||
|
printf("[RUN] Testing empty vector boundaries & underflows...\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_VecCharInternal vec = VEC_INIT;
|
||||||
|
|
||||||
|
// 1. Pop back on an empty container must not underflow size_t (0 - 1)
|
||||||
|
_vec_char_pop_back(&vec, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0 || err.flags != 0);
|
||||||
|
|
||||||
|
// 2. Reading back/end of an empty container
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_char_back(&vec, &err);
|
||||||
|
assert(err.flags != 0);
|
||||||
|
|
||||||
|
// 3. Reserving 0 capacity
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_char_reserve(&vec, 0, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
|
||||||
|
_vec_char_delete(&vec, &err);
|
||||||
|
printf("[PASS] Empty vector boundaries handled.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_push_growth_and_shrink(void)
|
||||||
|
{
|
||||||
|
printf("[RUN] Testing push, capacity growth, and indexing...\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_VecCharInternal vec = VEC_INIT;
|
||||||
|
|
||||||
|
// Push elements to trigger initial malloc then realloc
|
||||||
|
for (char c = 'a'; c <= 'z'; c++)
|
||||||
|
{
|
||||||
|
_vec_char_push_back(&vec, c, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
}
|
||||||
|
assert(vec._internal_size == 26);
|
||||||
|
assert(vec._internal_capacity >= 26);
|
||||||
|
|
||||||
|
// Verify boundary indexing
|
||||||
|
assert(_vec_char_front(&vec, &err) == 'a');
|
||||||
|
assert(_vec_char_back(&vec, &err) == 'z');
|
||||||
|
|
||||||
|
// Index out of bounds check
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_char_at(&vec, 26, &err);
|
||||||
|
assert(err.flags != 0);
|
||||||
|
|
||||||
|
// Shrink to fit verification
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_char_shrink_to_fit(&vec, &err);
|
||||||
|
assert(vec._internal_capacity == 26);
|
||||||
|
|
||||||
|
_vec_char_delete(&vec, &err);
|
||||||
|
printf("[PASS] Growth and indexing passed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_range_insert_and_erase(void)
|
||||||
|
{
|
||||||
|
printf("[RUN] Testing range insertions and erasures...\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_VecCharInternal vec = VEC_INIT;
|
||||||
|
|
||||||
|
_vec_char_push_back(&vec, 'A', &err);
|
||||||
|
_vec_char_push_back(&vec, 'B', &err);
|
||||||
|
_vec_char_push_back(&vec, 'E', &err);
|
||||||
|
|
||||||
|
// Single insert between 'B' and 'E' at index 2
|
||||||
|
_vec_char_insert(&vec, 2, 'C', &err);
|
||||||
|
assert(vec._internal_size == 4);
|
||||||
|
assert(*_vec_char_at(&vec, 2, &err) == 'C');
|
||||||
|
|
||||||
|
// Erase test
|
||||||
|
_vec_char_erase(&vec, 2, &err);
|
||||||
|
assert(vec._internal_size == 3);
|
||||||
|
assert(*_vec_char_at(&vec, 2, &err) == 'E');
|
||||||
|
|
||||||
|
// Inverted range check: iter_end <= iter_start must report error
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_char_erase(&vec, 2, 1, &err);
|
||||||
|
assert(err.flags != 0);
|
||||||
|
|
||||||
|
_vec_char_delete(&vec, &err);
|
||||||
|
printf("[PASS] Range insert and erase passed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
test_empty_vector_underflows();
|
||||||
|
test_push_growth_and_shrink();
|
||||||
|
test_range_insert_and_erase();
|
||||||
|
printf("\nAll char vector edge-case tests passed cleanly!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,689 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <int/int.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <utils/utils.h>
|
||||||
|
|
||||||
|
#if defined(__has_feature)
|
||||||
|
#if __has_feature(address_sanitizer)
|
||||||
|
const char*
|
||||||
|
__asan_default_options(void)
|
||||||
|
{
|
||||||
|
return "allocator_may_return_null=1";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* 1. BASIC LIFECYCLE & NULL GUARDS
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_push_back_single(void)
|
||||||
|
{
|
||||||
|
printf("[1] Testing push_back with a single integer...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 65, &err);
|
||||||
|
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_size == 1);
|
||||||
|
assert(vec._internal_arr[0] == 65);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_null_guards(void)
|
||||||
|
{
|
||||||
|
printf("[2] Testing null pointer checks in __null_check...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
size_t res1 = __null_check(&vec, nullptr);
|
||||||
|
assert(res1 == ERR_ERR_T_NULL);
|
||||||
|
|
||||||
|
size_t res2 = __null_check((const _VecIntInternal*)nullptr, &err);
|
||||||
|
assert(res2 == ERR_VEC_NULL);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
size_t res3 = __null_check(&vec, &err);
|
||||||
|
assert(res3 == ERR_BUF_NULL);
|
||||||
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
size_t res4 = __null_check(vec._internal_arr, &err);
|
||||||
|
assert(res4 == ERR_BUF_NULL);
|
||||||
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
size_t res5 = __null_check((const int*)nullptr, nullptr);
|
||||||
|
assert(res5 == ERR_ERR_T_NULL);
|
||||||
|
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_origin_override(void)
|
||||||
|
{
|
||||||
|
printf("[3] Testing __origin_override...\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
size_t res_null_status = __origin_override(nullptr, "TEST");
|
||||||
|
assert(res_null_status == ERR_ERR_T_NULL);
|
||||||
|
|
||||||
|
size_t res = __origin_override(&err, nullptr);
|
||||||
|
assert(res == ERR_STR_NULL);
|
||||||
|
assert((err.flags & ERR_STR_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
__origin_override(&err, "INITIAL");
|
||||||
|
assert(strcmp(err.origin, "INITIAL") == 0);
|
||||||
|
|
||||||
|
// Override existing origin -> ERR_ORIGIN_UNALTERABLE
|
||||||
|
__origin_override(&err, "REPLACED");
|
||||||
|
assert((err.flags & ERR_ORIGIN_UNALTERABLE) != 0);
|
||||||
|
assert(strcmp(err.origin, "INITIAL") == 0);
|
||||||
|
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* 2. PRINT & COPY
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_print_vec(void)
|
||||||
|
{
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
printf("[4] Testing print_vec with null vector\n");
|
||||||
|
_vec_int_print_vec(nullptr, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[5] Testing print_vec with null array\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_print_vec(&vec, &err);
|
||||||
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[6] Testing print_vec with null err\n");
|
||||||
|
_vec_int_print_vec(&vec, nullptr);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[7] Testing print_vec with valid parameters\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
|
_vec_int_push_back(&vec, 2, &err);
|
||||||
|
_vec_int_print_vec(&vec, &err);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cpy(void)
|
||||||
|
{
|
||||||
|
int arr[3] = { 1, 2, 3 };
|
||||||
|
_VecIntInternal blank = VEC_INIT;
|
||||||
|
|
||||||
|
printf("[8] Testing _vec_int_cpy with null source arr\n");
|
||||||
|
err_t err1 = ERR_T_INIT;
|
||||||
|
_VecIntInternal tmp = _vec_int_cpy(nullptr, 3, &err1);
|
||||||
|
assert(blank._internal_arr == tmp._internal_arr &&
|
||||||
|
blank._internal_capacity == tmp._internal_capacity &&
|
||||||
|
blank._internal_size == tmp._internal_size &&
|
||||||
|
blank._internal_max_size == tmp._internal_max_size);
|
||||||
|
assert((err1.flags & ERR_BUF_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[9] Testing _vec_int_cpy with null err\n");
|
||||||
|
_VecIntInternal res2 = _vec_int_cpy(arr, 3, nullptr);
|
||||||
|
assert(blank._internal_arr == res2._internal_arr &&
|
||||||
|
blank._internal_capacity == res2._internal_capacity &&
|
||||||
|
blank._internal_size == res2._internal_size &&
|
||||||
|
blank._internal_max_size == res2._internal_max_size);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[10] Testing _vec_int_cpy with size 0\n");
|
||||||
|
err_t err3 = ERR_T_INIT;
|
||||||
|
_VecIntInternal res3 = _vec_int_cpy(arr, 0, &err3);
|
||||||
|
assert(blank._internal_arr == res3._internal_arr &&
|
||||||
|
blank._internal_capacity == res3._internal_capacity &&
|
||||||
|
blank._internal_size == res3._internal_size &&
|
||||||
|
blank._internal_max_size == res3._internal_max_size);
|
||||||
|
assert((err3.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[11] Testing _vec_int_cpy with size exceeding max_size\n");
|
||||||
|
err_t err4 = ERR_T_INIT;
|
||||||
|
_VecIntInternal res4 =
|
||||||
|
_vec_int_cpy(arr, res3._internal_max_size + 1, &err4);
|
||||||
|
assert(blank._internal_arr == res4._internal_arr &&
|
||||||
|
blank._internal_capacity == res4._internal_capacity &&
|
||||||
|
blank._internal_size == res4._internal_size &&
|
||||||
|
blank._internal_max_size == res4._internal_max_size);
|
||||||
|
assert((err4.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[12] Testing _vec_int_cpy allocation failure\n");
|
||||||
|
err_t err5 = ERR_T_INIT;
|
||||||
|
size_t huge_size = ((size_t)1 << 40);
|
||||||
|
_VecIntInternal res5 = _vec_int_cpy(arr, huge_size, &err5);
|
||||||
|
assert(res5._internal_arr == blank._internal_arr);
|
||||||
|
assert((err5.flags & ERR_ALLOC_FAIL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[13] Testing _vec_int_cpy with valid inputs\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
int res[4] = { 10, 20, 30, 40 };
|
||||||
|
_VecIntInternal vec = _vec_int_cpy(res, 4, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_size == 4);
|
||||||
|
assert(vec._internal_capacity == 4);
|
||||||
|
assert(memcmp(vec._internal_arr, res, sizeof(int) * 4) == 0);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* 3. PUSH, POP, CAPACITY & SIZING
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_push_back(void)
|
||||||
|
{
|
||||||
|
printf("[14] Testing _vec_int_push_back null vec\n");
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
_vec_int_push_back(nullptr, 1, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[15] Testing _vec_int_push_back null err\n");
|
||||||
|
_VecIntInternal vec1 = VEC_INIT;
|
||||||
|
_vec_int_push_back(&vec1, 1, nullptr);
|
||||||
|
assert(vec1._internal_size == 1);
|
||||||
|
_vec_int_delete(&vec1, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[16] Testing _vec_int_push_back size overflow\n");
|
||||||
|
_VecIntInternal vec2 = VEC_INIT;
|
||||||
|
err_t err2 = ERR_T_INIT;
|
||||||
|
vec2._internal_size = vec2._internal_max_size;
|
||||||
|
_vec_int_push_back(&vec2, 1, &err2);
|
||||||
|
assert((err2.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[17] Testing push_back capacity growth realloc\n");
|
||||||
|
err_t err3 = ERR_T_INIT;
|
||||||
|
_VecIntInternal vec3 = VEC_INIT;
|
||||||
|
for (int val = 0; val < 10; val++)
|
||||||
|
{
|
||||||
|
_vec_int_push_back(&vec3, val, &err3);
|
||||||
|
assert(err3.flags == 0);
|
||||||
|
}
|
||||||
|
assert(vec3._internal_size == 10);
|
||||||
|
assert(vec3._internal_capacity >= 10);
|
||||||
|
_vec_int_delete(&vec3, &err3);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_pop_back(void)
|
||||||
|
{
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
printf("[18] Testing _vec_int_pop_back null vector\n");
|
||||||
|
_vec_int_pop_back(nullptr, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[19] Testing _vec_int_pop_back size 0\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 42, &err);
|
||||||
|
_vec_int_pop_back(&vec,
|
||||||
|
&err); // size is now 0, but buffer is allocated
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_pop_back(&vec, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[20] Testing _vec_int_pop_back valid pop\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
|
_vec_int_push_back(&vec, 2, &err);
|
||||||
|
assert(vec._internal_size == 2);
|
||||||
|
_vec_int_pop_back(&vec, &err);
|
||||||
|
assert(vec._internal_size == 1);
|
||||||
|
assert(vec._internal_arr[0] == 1);
|
||||||
|
assert(vec._internal_arr[1] == 0);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_reserve(void)
|
||||||
|
{
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
printf("[21] Testing _vec_int_reserve null vector\n");
|
||||||
|
_vec_int_reserve(nullptr, 1, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[22] Testing _vec_int_reserve capacity 0\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_reserve(&vec, 0, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[23] Testing _vec_int_reserve calloc on unallocated buffer\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_reserve(&vec, 32, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_capacity == 32);
|
||||||
|
assert(vec._internal_arr != nullptr);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[24] Testing _vec_int_reserve realloc to larger capacity\n");
|
||||||
|
_vec_int_reserve(&vec, 64, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_capacity == 64);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[25] Testing _vec_int_reserve truncating size\n");
|
||||||
|
vec._internal_size = 50;
|
||||||
|
_vec_int_reserve(&vec, 20, &err);
|
||||||
|
assert(vec._internal_size == 20);
|
||||||
|
assert(vec._internal_capacity == 20);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_shrink_to_fit(void)
|
||||||
|
{
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
printf("[26] Testing _vec_int_shrink_to_fit null vector\n");
|
||||||
|
_vec_int_shrink_to_fit(nullptr, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"[27] Testing _vec_int_shrink_to_fit size 0 with allocated "
|
||||||
|
"buffer\n");
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 1, &err);
|
||||||
|
_vec_int_pop_back(&vec, &err);
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_shrink_to_fit(&vec, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
printf("Passed\n");
|
||||||
|
|
||||||
|
printf("[28] Testing _vec_int_shrink_to_fit normal shrinkage\n");
|
||||||
|
_vec_int_reserve(&vec, 128, &err);
|
||||||
|
for (int val = 0; val < 5; val++)
|
||||||
|
{
|
||||||
|
_vec_int_push_back(&vec, val, &err);
|
||||||
|
}
|
||||||
|
assert(vec._internal_capacity == 128);
|
||||||
|
assert(vec._internal_size == 5);
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_shrink_to_fit(&vec, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_capacity == 5);
|
||||||
|
assert(vec._internal_size == 5);
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* 4. GETTERS, ELEMENT ACCESS & CLEAR
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_getters_and_access(void)
|
||||||
|
{
|
||||||
|
printf("[29] Testing getters, clear, and boundary element access...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
// 1. Null pointer check
|
||||||
|
assert(_vec_int_data(nullptr, &err) == nullptr);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_size(nullptr, &err) == 0);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_capacity(nullptr, &err) == 0);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_max_size(nullptr, &err) == 0);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
// 2. Unallocated buffer check for empty()
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
size_t unalloc_empty = _vec_int_empty(&vec, &err);
|
||||||
|
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||||
|
assert(unalloc_empty != 0);
|
||||||
|
|
||||||
|
// 3. Allocate the buffer and pop so size is 0 with valid arr
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 100, &err);
|
||||||
|
_vec_int_pop_back(&vec, &err);
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
|
||||||
|
// Now _internal_arr is non-null and size is 0:
|
||||||
|
assert(_vec_int_empty(&vec, &err) == 0);
|
||||||
|
|
||||||
|
// Boundary element access on size 0
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_front(&vec, &err) == 0 ||
|
||||||
|
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_back(&vec, &err) == 0 ||
|
||||||
|
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// 4. Populate container
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&vec, 10, &err);
|
||||||
|
_vec_int_push_back(&vec, 20, &err);
|
||||||
|
_vec_int_push_back(&vec, 30, &err);
|
||||||
|
|
||||||
|
assert(_vec_int_size(&vec, &err) == 3);
|
||||||
|
assert(_vec_int_capacity(&vec, &err) >= 3);
|
||||||
|
assert(_vec_int_data(&vec, &err) == vec._internal_arr);
|
||||||
|
assert(_vec_int_front(&vec, &err) == 10);
|
||||||
|
assert(_vec_int_back(&vec, &err) == 30);
|
||||||
|
assert(_vec_int_begin(&vec, &err) == 0);
|
||||||
|
assert(_vec_int_end(&vec, &err) == 2);
|
||||||
|
|
||||||
|
// Out of bounds at()
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
assert(_vec_int_at(&vec, 10, &err) == nullptr);
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// Clear container
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_clear(&vec, &err);
|
||||||
|
assert(vec._internal_size == 0);
|
||||||
|
assert(vec._internal_arr[0] == 0);
|
||||||
|
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
assert(vec._internal_arr == nullptr);
|
||||||
|
assert(vec._internal_size == 0);
|
||||||
|
assert(vec._internal_capacity == 0);
|
||||||
|
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* 5. SWAP, ERASE, RESIZE, ASSIGN & INSERT
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_swap(void)
|
||||||
|
{
|
||||||
|
printf("[30] Testing _vec_int_swap...\n");
|
||||||
|
_VecIntInternal a = VEC_INIT;
|
||||||
|
_VecIntInternal b = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
// Null vector checks
|
||||||
|
_vec_int_swap(nullptr, &b, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_swap(&a, nullptr, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
// Normal swap
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_push_back(&a, 100, &err);
|
||||||
|
_vec_int_push_back(&b, 200, &err);
|
||||||
|
_vec_int_push_back(&b, 300, &err);
|
||||||
|
|
||||||
|
_vec_int_swap(&a, &b, &err);
|
||||||
|
assert(a._internal_size == 2);
|
||||||
|
assert(a._internal_arr[0] == 200);
|
||||||
|
assert(b._internal_size == 1);
|
||||||
|
assert(b._internal_arr[0] == 100);
|
||||||
|
|
||||||
|
_vec_int_delete(&a, &err);
|
||||||
|
_vec_int_delete(&b, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_erase_variants(void)
|
||||||
|
{
|
||||||
|
printf("[31] Testing _vec_int_erase single & range overloads...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
for (int val = 0; val <= 5; val++)
|
||||||
|
{
|
||||||
|
_vec_int_push_back(&vec, val, &err);
|
||||||
|
} // {0, 1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
// Single element erase out of bounds (noop)
|
||||||
|
_vec_int_erase(&vec, 10, &err);
|
||||||
|
assert(vec._internal_size == 6);
|
||||||
|
|
||||||
|
// Erase index 2 (value 2) -> {0, 1, 3, 4, 5}
|
||||||
|
_vec_int_erase(&vec, 2, &err);
|
||||||
|
assert(vec._internal_size == 5);
|
||||||
|
assert(vec._internal_arr[2] == 3);
|
||||||
|
|
||||||
|
// Range erase invalid bounds
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_erase(&vec, 4, 2, &err); // iter_end <= iter_start
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_erase(&vec, 0, 10, &err); // iter_end > size
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// Range erase middle: index 1 through 3 ({0, [1, 3], 4, 5} -> {0, 4,
|
||||||
|
// 5})
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_erase(&vec, 1, 3, &err);
|
||||||
|
assert(vec._internal_size == 3);
|
||||||
|
assert(vec._internal_arr[0] == 0);
|
||||||
|
assert(vec._internal_arr[1] == 4);
|
||||||
|
assert(vec._internal_arr[2] == 5);
|
||||||
|
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_resize(void)
|
||||||
|
{
|
||||||
|
printf("[32] Testing _vec_int_resize (zero-fill & value-fill)...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
// Null vector
|
||||||
|
_vec_int_resize((_VecIntInternal*)nullptr, 10, &err);
|
||||||
|
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||||
|
|
||||||
|
// Resize unallocated buffer to size 5
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_resize(&vec, 5, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(vec._internal_size == 5);
|
||||||
|
assert(vec._internal_arr[0] == 0);
|
||||||
|
|
||||||
|
// Same size requested
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_resize(&vec, 5, &err);
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// Exceeds max size
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_resize(&vec, vec._internal_max_size + 1, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||||
|
|
||||||
|
// Grow with value fill
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_resize(&vec, 8, 5, &err);
|
||||||
|
assert(vec._internal_size == 8);
|
||||||
|
assert(vec._internal_arr[5] == 5);
|
||||||
|
assert(vec._internal_arr[7] == 5);
|
||||||
|
|
||||||
|
// Shrink with value fill
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_resize(&vec, 3, 10, &err);
|
||||||
|
assert(vec._internal_size == 3);
|
||||||
|
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_assign(void)
|
||||||
|
{
|
||||||
|
printf("[33] Testing _vec_int_assign overloads...\n");
|
||||||
|
_VecIntInternal dst = VEC_INIT;
|
||||||
|
_VecIntInternal src = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
// Populate src: 1, 2, 3, 4, 5
|
||||||
|
for (int val = 1; val <= 5; val++)
|
||||||
|
{
|
||||||
|
_vec_int_push_back(&src, val, &err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate dst buffer first so it is not unallocated
|
||||||
|
_vec_int_push_back(&dst, 999, &err);
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
|
||||||
|
// 1. Fill assign: 4 42's
|
||||||
|
_vec_int_assign(&dst, 4, 42, &err);
|
||||||
|
assert(err.flags == 0);
|
||||||
|
assert(dst._internal_size == 4);
|
||||||
|
assert(dst._internal_arr[0] == 42);
|
||||||
|
assert(dst._internal_arr[3] == 42);
|
||||||
|
|
||||||
|
// 2. Fill assign with 0 amount
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_assign(&dst, 0, 50, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
|
||||||
|
// 3. Range assign self-buffer check
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_assign(&dst, &dst, 0, 2, &err);
|
||||||
|
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||||
|
|
||||||
|
// 4. Range assign invalid sub-range (start >= end)
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_assign(&dst, &src, 3, 2, &err);
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// 5. Range assign out of bounds end
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_assign(&dst, &src, 0, 10, &err);
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
_vec_int_delete(&dst, &err);
|
||||||
|
_vec_int_delete(&src, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_insert(void)
|
||||||
|
{
|
||||||
|
printf("[34] Testing _vec_int_insert overloads...\n");
|
||||||
|
_VecIntInternal vec = VEC_INIT;
|
||||||
|
_VecIntInternal other = VEC_INIT;
|
||||||
|
err_t err = ERR_T_INIT;
|
||||||
|
|
||||||
|
// Single insert on unallocated buffer
|
||||||
|
_vec_int_insert(&vec, 0, 500, &err);
|
||||||
|
assert(vec._internal_size == 1);
|
||||||
|
assert(vec._internal_arr[0] == 500);
|
||||||
|
|
||||||
|
// Single insert out of bounds
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_insert(&vec, 5, 999, &err);
|
||||||
|
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||||
|
|
||||||
|
// Single insert at middle: index 0 (100, then 500 shifts to 1)
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_insert(&vec, 0, 100, &err);
|
||||||
|
assert(vec._internal_size == 2);
|
||||||
|
assert(vec._internal_arr[0] == 100);
|
||||||
|
assert(vec._internal_arr[1] == 500);
|
||||||
|
|
||||||
|
// Repeated insert: insert 3 200s at index 1 -> {100, 200, 200, 200,
|
||||||
|
// 500}
|
||||||
|
_vec_int_insert(&vec, 1, 3, 200, &err);
|
||||||
|
assert(vec._internal_size == 5);
|
||||||
|
assert(vec._internal_arr[1] == 200);
|
||||||
|
assert(vec._internal_arr[3] == 200);
|
||||||
|
assert(vec._internal_arr[4] == 500);
|
||||||
|
|
||||||
|
// Repeated insert amount 0
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_insert(&vec, 0, 0, 300, &err);
|
||||||
|
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||||
|
|
||||||
|
// Vector-from-vector range insert
|
||||||
|
_vec_int_push_back(&other, 1, &err);
|
||||||
|
_vec_int_push_back(&other, 2, &err);
|
||||||
|
|
||||||
|
// Double buffer check
|
||||||
|
err = (err_t)ERR_T_INIT;
|
||||||
|
_vec_int_insert(&vec, &vec, 0, 0, 1, &err);
|
||||||
|
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||||
|
|
||||||
|
_vec_int_delete(&vec, &err);
|
||||||
|
_vec_int_delete(&other, &err);
|
||||||
|
printf("Passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* MAIN TEST RUNNER
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
printf("=========================================\n");
|
||||||
|
printf(" Starting Complete libvec Unit Test Suite\n");
|
||||||
|
printf("=========================================\n");
|
||||||
|
|
||||||
|
test_push_back_single();
|
||||||
|
test_null_guards();
|
||||||
|
test_origin_override();
|
||||||
|
test_print_vec();
|
||||||
|
test_cpy();
|
||||||
|
test_push_back();
|
||||||
|
test_pop_back();
|
||||||
|
test_reserve();
|
||||||
|
test_shrink_to_fit();
|
||||||
|
test_getters_and_access();
|
||||||
|
test_swap();
|
||||||
|
test_erase_variants();
|
||||||
|
test_resize();
|
||||||
|
test_assign();
|
||||||
|
test_insert();
|
||||||
|
|
||||||
|
printf("=========================================\n");
|
||||||
|
printf(" All 34 Test Suites Executed Successfully!\n");
|
||||||
|
printf("=========================================\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user