Merge pull request 'chore: update README to enhance clarity and detail on dynamic array features' (#2) from chore/better-readme into main
All checks were successful
CI / build (push) Successful in 35s
All checks were successful
CI / build (push) Successful in 35s
Reviewed-on: http://gitea.hideyoshi.com.br/HideyoshiNakazone/dynamic_array/pulls/2
This commit was merged in pull request #2.
This commit is contained in:
116
README.md
116
README.md
@@ -9,21 +9,22 @@ A simple, educational C implementation of a dynamic array (vector-like) data str
|
|||||||
This library provides a basic dynamic array implementation in C, similar to C++'s `std::vector` or Python's lists. It demonstrates fundamental concepts in systems programming:
|
This library provides a basic dynamic array implementation in C, similar to C++'s `std::vector` or Python's lists. It demonstrates fundamental concepts in systems programming:
|
||||||
|
|
||||||
- **Memory management** — allocation, reallocation, deallocation
|
- **Memory management** — allocation, reallocation, deallocation
|
||||||
- **Generic programming** — using `void*` pointers
|
- **Generic programming** — type-agnostic macros that work with any pointer type
|
||||||
- **Type-safe macros** — for type casting and operations
|
|
||||||
- **Unit testing** — with the Unity C testing framework
|
- **Unit testing** — with the Unity C testing framework
|
||||||
|
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
||||||
- **Dynamic resizing** — Automatically grows as elements are added
|
- **Header-only** — just include `dynamic_array.h`, no compilation step needed
|
||||||
- **Type-safe operations** — Macros for working with typed elements
|
- **Dynamic resizing** — automatically grows as elements are added
|
||||||
- **Simple API** — Easy-to-use functions for common operations
|
- **Type-safe** — macros operate on typed pointers; direct indexing is fully typed
|
||||||
|
- **Simple API** — a small set of macros for common operations
|
||||||
|
|
||||||
## 📁 Project Structure
|
## 📁 Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
test-meson/
|
dynamic_array/
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── dynamic_array.c # Implementation
|
│ ├── dynamic_array.h # Header-only implementation (public API)
|
||||||
│ ├── dynamic_array.h # Public API header
|
|
||||||
│ ├── test_dynamic_array.c # Unit tests
|
│ ├── test_dynamic_array.c # Unit tests
|
||||||
│ └── CMakeLists.txt # Build configuration
|
│ └── CMakeLists.txt # Build configuration
|
||||||
├── submodules/
|
├── submodules/
|
||||||
@@ -33,6 +34,7 @@ test-meson/
|
|||||||
├── Makefile # Build automation
|
├── Makefile # Build automation
|
||||||
└── README.md # This file
|
└── README.md # This file
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔧 Prerequisites
|
## 🔧 Prerequisites
|
||||||
|
|
||||||
**Linux-only project**
|
**Linux-only project**
|
||||||
@@ -41,6 +43,7 @@ test-meson/
|
|||||||
- **C compiler** (GCC recommended, Clang supported)
|
- **C compiler** (GCC recommended, Clang supported)
|
||||||
- **Make** (optional, but recommended)
|
- **Make** (optional, but recommended)
|
||||||
- **build-essential** (on Ubuntu/Debian): `sudo apt-get install build-essential`
|
- **build-essential** (on Ubuntu/Debian): `sudo apt-get install build-essential`
|
||||||
|
|
||||||
## 🔨 Building
|
## 🔨 Building
|
||||||
|
|
||||||
### Using the Makefile (Recommended)
|
### Using the Makefile (Recommended)
|
||||||
@@ -63,6 +66,7 @@ ctest --output-on-failure
|
|||||||
cmake --install .
|
cmake --install .
|
||||||
cd .. && rm -rf build
|
cd .. && rm -rf build
|
||||||
```
|
```
|
||||||
|
|
||||||
## 💡 Usage
|
## 💡 Usage
|
||||||
|
|
||||||
### Including the Library
|
### Including the Library
|
||||||
@@ -70,72 +74,70 @@ cd .. && rm -rf build
|
|||||||
```c
|
```c
|
||||||
#include "dynamic_array.h"
|
#include "dynamic_array.h"
|
||||||
|
|
||||||
// Create an array of integers
|
// Create a typed array (works with any pointer type)
|
||||||
ArrayCreateOptions opts = {
|
int *arr = NULL;
|
||||||
.initial_size = 10,
|
array_create(arr);
|
||||||
.element_size = sizeof(int)
|
|
||||||
};
|
|
||||||
Array *my_array = array_create(&opts);
|
|
||||||
|
|
||||||
// Add elements
|
// Add elements
|
||||||
int value = 42;
|
array_push_value(arr, 10);
|
||||||
array_set_value(my_array, 0, &value);
|
array_push_value(arr, 20);
|
||||||
|
array_push_value(arr, 30);
|
||||||
|
|
||||||
// Retrieve elements
|
// Access elements directly via indexing
|
||||||
int *retrieved = (int*)array_get_value(my_array, 0);
|
int first = arr[0]; // 10
|
||||||
|
|
||||||
// Using type-safe macros
|
// Remove the last element
|
||||||
int result = array_set_value_as(int, my_array, 1, 100);
|
array_pop(arr);
|
||||||
|
|
||||||
// Get size and capacity
|
// Inspect size and capacity via the header
|
||||||
size_t size = array_get_size(my_array);
|
const ArrayHeader *header = array_get_header(arr);
|
||||||
size_t capacity = array_get_capacity(my_array);
|
size_t size = header->size; // current number of elements
|
||||||
|
size_t capacity = header->capacity; // allocated capacity
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
array_deconstructor(&my_array);
|
array_destroy(arr); // frees memory and sets arr to NULL
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📖 API Reference
|
## 📖 API Reference
|
||||||
|
|
||||||
### Structures
|
### Structures
|
||||||
|
|
||||||
#### `Array`
|
#### `ArrayHeader`
|
||||||
|
|
||||||
|
Stored immediately before the array data in memory. Retrieve it with `array_get_header`.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *value; // Pointer to element data
|
size_t size; // Current number of elements
|
||||||
size_t element_size; // Size of each element
|
size_t capacity; // Allocated capacity
|
||||||
size_t size; // Current number of elements
|
} ArrayHeader;
|
||||||
size_t capacity; // Allocated capacity
|
|
||||||
} Array;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `ArrayCreateOptions`
|
Memory layout:
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct {
|
|
||||||
int initial_size; // Initial capacity
|
|
||||||
size_t element_size; // Size of each element type
|
|
||||||
} ArrayCreateOptions;
|
|
||||||
```
|
```
|
||||||
|
[ ArrayHeader | elem 0 | elem 1 | ... ]
|
||||||
### Functions
|
↑
|
||||||
|
pointer returned by array_create (and all macros)
|
||||||
| Function | Description |
|
```
|
||||||
|----------|-------------|
|
|
||||||
| `Array *array_create(const ArrayCreateOptions *options)` | Creates a new dynamic array |
|
|
||||||
| `void array_deconstructor(Array **pp_array)` | Frees allocated memory and sets pointer to NULL |
|
|
||||||
| `void array_resize(Array *p_array, size_t new_size)` | Resizes the array's capacity |
|
|
||||||
| `void *array_get_value(const Array *p_array, size_t index)` | Retrieves a pointer to the element at index |
|
|
||||||
| `void array_set_value(Array *p_array, size_t index, const void *value)` | Sets the element at index |
|
|
||||||
| `size_t array_get_size(const Array *p_array)` | Returns the current number of elements |
|
|
||||||
| `size_t array_get_capacity(const Array *p_array)` | Returns the allocated capacity |
|
|
||||||
|
|
||||||
### Macros
|
### Macros
|
||||||
|
|
||||||
| Macro | Description |
|
| Macro | Description |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
| `array_get_value_as(type, arr, idx)` | Type-safe retrieval of elements |
|
| `array_create(arr)` | Allocates a new array; sets `arr` to point to the first element |
|
||||||
| `array_set_value_as(type, arr, idx, value)` | Type-safe setting of elements (with type checking) |
|
| `array_destroy(arr)` | Frees the array and sets `arr` to `NULL` |
|
||||||
|
| `array_get_header(arr)` | Returns a pointer to the `ArrayHeader` for `arr` |
|
||||||
|
| `array_push_value(arr, value)` | Appends `value`; grows the array automatically if needed |
|
||||||
|
| `array_pop(arr)` | Removes the last element by decrementing `size` |
|
||||||
|
|
||||||
|
### Constants
|
||||||
|
|
||||||
|
| Constant | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE` | `10` | Initial capacity allocated by `array_create` |
|
||||||
|
| `DYNAMIC_ARRAY_CAPACITY_FACTOR` | `2` | Growth multiplier applied on resize |
|
||||||
|
|
||||||
## ✅ Testing
|
## ✅ Testing
|
||||||
|
|
||||||
Tests are written using the [Unity](http://www.throwtheswitch.org/unity) C testing framework.
|
Tests are written using the [Unity](http://www.throwtheswitch.org/unity) C testing framework.
|
||||||
@@ -149,6 +151,7 @@ Or directly with ctest:
|
|||||||
```bash
|
```bash
|
||||||
cd build && ctest --output-on-failure
|
cd build && ctest --output-on-failure
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📦 Installation
|
## 📦 Installation
|
||||||
|
|
||||||
### Default Installation
|
### Default Installation
|
||||||
@@ -158,7 +161,6 @@ make install
|
|||||||
```
|
```
|
||||||
|
|
||||||
This installs to `~/.local/bin/dynamic_array/`:
|
This installs to `~/.local/bin/dynamic_array/`:
|
||||||
- **Library:** `lib/libdynamic_array.a`
|
|
||||||
- **Header:** `include/dynamic_array.h`
|
- **Header:** `include/dynamic_array.h`
|
||||||
|
|
||||||
### Custom Installation Directory
|
### Custom Installation Directory
|
||||||
@@ -173,20 +175,26 @@ Or set it as an environment variable:
|
|||||||
export INSTALL_PREFIX=$HOME/.local
|
export INSTALL_PREFIX=$HOME/.local
|
||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
## ⚠️ Known Issues & Limitations
|
## ⚠️ Known Issues & Limitations
|
||||||
|
|
||||||
- ⚠️ No bounds checking in release builds
|
- ⚠️ No bounds checking
|
||||||
|
- ⚠️ `array_pop` does not return the removed element (use `arr[header->size - 1]` before popping)
|
||||||
- ⚠️ Simple reallocation strategy (not optimized for performance)
|
- ⚠️ Simple reallocation strategy (not optimized for performance)
|
||||||
- ⚠️ Not thread-safe
|
- ⚠️ Not thread-safe
|
||||||
- ⚠️ Limited error handling
|
- ⚠️ `realloc` failure is not propagated to the caller
|
||||||
- ⚠️ Educational purpose only — use established libraries for production
|
- ⚠️ Educational purpose only — use established libraries for production
|
||||||
|
|
||||||
## 🚀 Future Improvements
|
## 🚀 Future Improvements
|
||||||
|
|
||||||
|
- [ ] Return value from `array_pop`
|
||||||
|
- [ ] Propagate allocation failures
|
||||||
- [ ] Add more comprehensive error handling
|
- [ ] Add more comprehensive error handling
|
||||||
- [ ] Implement shrinking functionality
|
- [ ] Implement shrinking / `array_reserve`
|
||||||
- [ ] Add iterator support
|
- [ ] Add iterator support
|
||||||
- [ ] Optimize memory allocation strategy
|
- [ ] Optimize memory allocation strategy
|
||||||
- [ ] Add more test coverage
|
- [ ] Add more test coverage
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
This project is for educational purposes.
|
This project is for educational purposes.
|
||||||
|
|||||||
Reference in New Issue
Block a user