summaryrefslogtreecommitdiff
path: root/README.md
blob: 100d9ebc5bb4421c72f184d91aef4bc9f6dac9b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
**nonstd** is a single-header C library providing a collection of "non-standard" but highly useful utilities, data structures, and type definitions that are often missing from the C standard library. It aims to make C programming more ergonomic and productive without the overhead of large frameworks.

## Features

- **Shorthand Types**: Concise integer types (`i8`, `u32`, `usize`, etc.) for better readability.
- **Utility Macros**: Common helpers like `countof`, `MIN`, `MAX`, `CLAMP`, and `static_foreach`.
- **String View (`stringv`)**: Efficient, non-owning, read-only string references to avoid unnecessary copies.
- **String Builder (`stringb`)**: Growable, mutable string buffer for efficient string construction.
- **Dynamic Array (`array`)**: Type-safe, generic growable arrays implemented via macros (similar to `std::vector` in C++).
- **Slices (`slice`)**: Generic non-owning views into arrays.
- **Memory Arena**: Simple and efficient block-based arena allocator for bulk memory management.
- **File I/O**: Helper functions to read and write entire files with a single call.

## Installation

`nonstd` is a single-header library. To use it:

1. Copy `nonstd.h` into your project's include directory.
2. In **one** C source file, define `NONSTD_IMPLEMENTATION` before including the header to create the implementation:

```c
#define NONSTD_IMPLEMENTATION
#include "nonstd.h"
```

3. In other files, just include it normally:

```c
#include "nonstd.h"
```

## Usage

### 1. Basic Types & Macros

```c
#include "nonstd.h"

void example() {
    i32 x = 10;
    u64 y = 2000;
    usize size = 1024;
    
    int numbers[] = {1, 2, 3, 4, 5};
    printf("Count: %zu\n", countof(numbers)); // 5
    
    int val = CLAMP(100, 0, 10); // 10
    
    // Static foreach loop
    int n;
    static_foreach(int, n, numbers) {
        printf("%d ", n);
    }
}
```

### 2. Dynamic Arrays

Create type-safe growable arrays for any type.

```c
// Define an array of integers
array(int) numbers;
array_init(numbers);

// Push values
array_push(numbers, 10);
array_push(numbers, 20);
array_push(numbers, 30);

// Iterate (index basic loop or helper macro)
int val;
array_foreach(numbers, val) {
    printf("%d\n", val);
}

// Access by index
if (numbers.length > 0) {
    printf("First: %d\n", numbers.data[0]);
    // or
    printf("First: %d\n", array_get(numbers, 0));
}

// Clean up
array_free(numbers);
```

### 3. String Views & Builders

**String View (`stringv`)**:
Ideal for parsing and passing strings around without allocation.

```c
const char* raw = "Hello World";
stringv sv = sv_from_cstr(raw);
stringv word = sv_slice(sv, 0, 5); // "Hello" (no allocation)

if (sv_starts_with(sv, sv_from_cstr("Hello"))) {
    // ...
}
```

**String Builder (`stringb`)**:
Efficiently construct strings.

```c
stringb sb;
sb_init(&sb, 0); // 0 = default capacity

sb_append_cstr(&sb, "Hello");
sb_append_char(&sb, ' ');
sb_append_cstr(&sb, "World");

printf("%s\n", sb.data); // "Hello World"

sb_free(&sb);
```

### 4. Memory Arena

Efficiently allocate many small objects and free them all at once.

```c
Arena arena = arena_make();

// Allocations are fast and contiguous within blocks
void* obj1 = arena_alloc(&arena, 64);
void* obj2 = arena_alloc(&arena, 128);

// growth is automatic if a block is full

// Free everything at once
arena_free(&arena);
```

### 5. File I/O Helpers

Read or write files with a single functional call.

```c
size_t size;
char* content = read_entire_file("data.txt", &size);

if (content) {
    printf("Read %zu bytes:\n%s\n", size, content);
    FREE(content); // Standard free (unless using arena)
}

// Or read directly into a string view or builder
stringv file_sv = read_entire_file_sv("config.ini");
// ... use file_sv ...
FREE((void*)file_sv.data); // Note: read_entire_file_sv allocates the data
```

## Testing

The project includes a comprehensive test suite using `minunit`.

To build and run the tests:

```bash
make test
```