feat: add stack
This commit is contained in:
@@ -9,6 +9,7 @@ A small, personal C library for learning and experimentation.
|
|||||||
- Thread-safe dynamic strings
|
- Thread-safe dynamic strings
|
||||||
- Thread-safe circular queues
|
- Thread-safe circular queues
|
||||||
- Thread-safe vectors
|
- Thread-safe vectors
|
||||||
|
- Stack
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ src = files(
|
|||||||
'queue/myqueue.c',
|
'queue/myqueue.c',
|
||||||
'string/mystring.c',
|
'string/mystring.c',
|
||||||
'vector/myvector.c',
|
'vector/myvector.c',
|
||||||
|
'stack/mystack.c',
|
||||||
)
|
)
|
||||||
|
|
||||||
testlib = files(
|
testlib = files(
|
||||||
@@ -20,6 +21,7 @@ testlib = files(
|
|||||||
'test/string/str2.c',
|
'test/string/str2.c',
|
||||||
'test/string/str3.c',
|
'test/string/str3.c',
|
||||||
'test/vector/v1.c',
|
'test/vector/v1.c',
|
||||||
|
'test/stack/s1.c',
|
||||||
)
|
)
|
||||||
|
|
||||||
sources = src + testlib
|
sources = src + testlib
|
||||||
|
|||||||
88
stack/mystack.c
Normal file
88
stack/mystack.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include "mystack.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <threads.h>
|
||||||
|
|
||||||
|
stack_s *stack_new(size_t initial_capacity, size_t element_size) {
|
||||||
|
if (element_size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_s *stack = (stack_s *)malloc(sizeof(stack_s));
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtx_init(&stack->lock, mtx_recursive) != thrd_success) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the vec data */
|
||||||
|
stack->data = vec_new(initial_capacity, element_size);
|
||||||
|
if (stack->data == NULL) {
|
||||||
|
free(stack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->elem_size = element_size;
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_pop(stack_s *stack) {
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtx_lock(&stack->lock) != thrd_success) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *elem = vec_pop(stack->data);
|
||||||
|
|
||||||
|
mtx_unlock(&stack->lock);
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stack_push(stack_s *stack, void *elem) {
|
||||||
|
if (stack == NULL || elem == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtx_lock(&stack->lock) != thrd_success) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = vec_push(stack->data, elem);
|
||||||
|
|
||||||
|
mtx_unlock(&stack->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_top(stack_s *stack) {
|
||||||
|
if (stack == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtx_lock(&stack->lock) != thrd_success) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *elem = vec_get(stack->data, stack->data->size - 1);
|
||||||
|
|
||||||
|
mtx_unlock(&stack->lock);
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stack_free(stack_s *stack) {
|
||||||
|
if (stack == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_free(stack->data);
|
||||||
|
free(stack);
|
||||||
|
}
|
||||||
25
stack/mystack.h
Normal file
25
stack/mystack.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef MYCLIB_STACK_H
|
||||||
|
#define MYCLIB_STACK_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <threads.h>
|
||||||
|
|
||||||
|
#include "../vector/myvector.h"
|
||||||
|
|
||||||
|
typedef struct stack {
|
||||||
|
vec_s *data;
|
||||||
|
size_t elem_size;
|
||||||
|
mtx_t lock;
|
||||||
|
} stack_s;
|
||||||
|
|
||||||
|
stack_s *stack_new(size_t initial_capacity, size_t element_size);
|
||||||
|
|
||||||
|
void *stack_pop(stack_s *stack);
|
||||||
|
|
||||||
|
int stack_push(stack_s *stack, void *elem);
|
||||||
|
|
||||||
|
void *stack_top(stack_s *stack);
|
||||||
|
|
||||||
|
void stack_free(stack_s *stack);
|
||||||
|
|
||||||
|
#endif
|
||||||
23
test/stack/s1.c
Normal file
23
test/stack/s1.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../../stack/mystack.h"
|
||||||
|
|
||||||
|
|
||||||
|
void test_s1(void) {
|
||||||
|
stack_s *stack = stack_new(32, sizeof(int));
|
||||||
|
int num = 10;
|
||||||
|
stack_push(stack, &num);
|
||||||
|
|
||||||
|
num = 13;
|
||||||
|
stack_push(stack, &num);
|
||||||
|
|
||||||
|
int *rv = (int *)stack_top(stack);
|
||||||
|
assert(*rv == 13);
|
||||||
|
free(rv);
|
||||||
|
|
||||||
|
rv = (int *)stack_pop(stack);
|
||||||
|
assert(*rv == 13);
|
||||||
|
free(rv);
|
||||||
|
|
||||||
|
stack_free(stack);
|
||||||
19
test/test.c
19
test/test.c
@@ -5,15 +5,17 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void test_hm1();
|
void test_hm1(void);
|
||||||
|
|
||||||
void test_q1();
|
void test_q1(void);
|
||||||
|
|
||||||
void test_str1();
|
void test_str1(void);
|
||||||
void test_str2();
|
void test_str2(void);
|
||||||
void test_str3();
|
void test_str3(void);
|
||||||
|
|
||||||
void test_v1();
|
void test_v1(void);
|
||||||
|
|
||||||
|
void test_s1(void);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
puts("==== [Running Hashmap tests] ====");
|
puts("==== [Running Hashmap tests] ====");
|
||||||
@@ -38,5 +40,10 @@ int main(void) {
|
|||||||
puts("OK!");
|
puts("OK!");
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
|
puts("==== [Running Stack tests] ====");
|
||||||
|
test_s1();
|
||||||
|
puts("OK!");
|
||||||
|
puts("");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "../../vector/myvector.h"
|
#include "../../vector/myvector.h"
|
||||||
@@ -15,11 +14,12 @@ static void multiply(size_t index, void *elem) {
|
|||||||
e->age = e->age * 2;
|
e->age = e->age * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Another way to use foreach */
|
/* Another way to use foreach
|
||||||
static void print(size_t index, void *elem) {
|
static void print(size_t index, void *elem) {
|
||||||
my_elem_s *e = (my_elem_s *)elem;
|
my_elem_s *e = (my_elem_s *)elem;
|
||||||
printf("%s (%d)\n", e->name, e->age);
|
printf("%s (%d)\n", e->name, e->age);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* Compare function used to sort */
|
/* Compare function used to sort */
|
||||||
int my_cmp(const void *a, const void *b) {
|
int my_cmp(const void *a, const void *b) {
|
||||||
@@ -70,13 +70,10 @@ void test_v1() {
|
|||||||
/* Iterate for each element */
|
/* Iterate for each element */
|
||||||
vec_foreach(v, multiply);
|
vec_foreach(v, multiply);
|
||||||
/* Print each element */
|
/* Print each element */
|
||||||
puts("Before sort:");
|
// vec_foreach(v, print);
|
||||||
vec_foreach(v, print);
|
|
||||||
|
|
||||||
/* Sort */
|
/* Sort */
|
||||||
vec_sort(v, my_cmp);
|
vec_sort(v, my_cmp);
|
||||||
puts("After sort:");
|
|
||||||
vec_foreach(v, print);
|
|
||||||
|
|
||||||
/* Deallocate the vector */
|
/* Deallocate the vector */
|
||||||
vec_free(v);
|
vec_free(v);
|
||||||
|
|||||||
@@ -305,7 +305,13 @@ int vec_sort(vec_s *vec, int (*cmp)(const void *a, const void *b)) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mtx_lock(&vec->lock) != thrd_success) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
qsort(vec->data, vec->size, vec->elem_size, cmp);
|
qsort(vec->data, vec->size, vec->elem_size, cmp);
|
||||||
|
|
||||||
|
mtx_unlock(&vec->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user