add queue
This commit is contained in:
@@ -8,3 +8,4 @@ It is not production-ready. Use at your own risk.
|
|||||||
- Hashmaps - Thread-safe (MT Safe)
|
- Hashmaps - Thread-safe (MT Safe)
|
||||||
- Dynamic strings - Not thread-safe (MT Unsafe)
|
- Dynamic strings - Not thread-safe (MT Unsafe)
|
||||||
> Requires linking with the C math library (`-lm`)
|
> Requires linking with the C math library (`-lm`)
|
||||||
|
- Circular Queue - Not thread-safe (MT Unsafe)
|
||||||
|
|||||||
7
examples/hashmap/hm1.c
Normal file
7
examples/hashmap/hm1.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
puts("TODO: Hashmap");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
53
examples/queue/q1.c
Normal file
53
examples/queue/q1.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../../queue/myqueue.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
mcl_queue *queue = mcl_queue_init(3, sizeof(int));
|
||||||
|
assert(queue != NULL);
|
||||||
|
|
||||||
|
int val, out;
|
||||||
|
|
||||||
|
val = 1;
|
||||||
|
assert(mcl_queue_push(queue, &val) == 0);
|
||||||
|
|
||||||
|
val = 2;
|
||||||
|
assert(mcl_queue_push(queue, &val) == 0);
|
||||||
|
|
||||||
|
int front = *((int *)mcl_queue_get_front(queue));
|
||||||
|
int rear = *((int *)mcl_queue_get_rear(queue));
|
||||||
|
printf("Front: %d, Rear: %d\n", front, rear);
|
||||||
|
assert(front == 1);
|
||||||
|
assert(rear == 2);
|
||||||
|
|
||||||
|
assert(mcl_queue_pop(queue, &out) == 0);
|
||||||
|
printf("Pop: %d\n", out);
|
||||||
|
assert(out == 1);
|
||||||
|
|
||||||
|
front = *((int *)mcl_queue_get_front(queue));
|
||||||
|
printf("Front after pop: %d\n", front);
|
||||||
|
assert(front == 2);
|
||||||
|
|
||||||
|
val = 3;
|
||||||
|
assert(mcl_queue_push(queue, &val) == 0);
|
||||||
|
|
||||||
|
rear = *((int *)mcl_queue_get_rear(queue));
|
||||||
|
printf("Rear after push 3: %d\n", rear);
|
||||||
|
assert(rear == 3);
|
||||||
|
|
||||||
|
val = 4;
|
||||||
|
int res = mcl_queue_push(queue, &val);
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
|
while (mcl_queue_pop(queue, &out) == 0) {
|
||||||
|
printf("Pop: %d\n", out);
|
||||||
|
}
|
||||||
|
printf("Queue is now empty\n");
|
||||||
|
|
||||||
|
assert(mcl_queue_pop(queue, &out) == -1);
|
||||||
|
|
||||||
|
mcl_queue_free(queue);
|
||||||
|
printf("All tests passed successfully.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
24
examples/string/str1.c
Normal file
24
examples/string/str1.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../../string/mystring.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
mcl_string *str = mcl_string_new("Hello, world!", 512);
|
||||||
|
assert(str != NULL);
|
||||||
|
|
||||||
|
printf("%s\nsize: %ld, cap: %ld\n", mcl_string_cstr(str), (long)mcl_string_length(str), (long)mcl_string_capacity(str));
|
||||||
|
assert(mcl_string_length(str) == 13);
|
||||||
|
|
||||||
|
int ret = mcl_string_append(str, " How are you?");
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
printf("After append:\n");
|
||||||
|
printf("%s\nsize: %ld, cap: %ld\n", mcl_string_cstr(str), (long)mcl_string_length(str), (long)mcl_string_capacity(str));
|
||||||
|
assert(mcl_string_length(str) == 26);
|
||||||
|
|
||||||
|
mcl_string_free(str);
|
||||||
|
|
||||||
|
printf("All tests passed successfully.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
89
queue/myqueue.c
Normal file
89
queue/myqueue.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include "myqueue.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
mcl_queue *mcl_queue_init(size_t queue_size, size_t elem_size) {
|
||||||
|
mcl_queue *queue = malloc(sizeof(mcl_queue));
|
||||||
|
if (queue == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue->buffer = malloc(queue_size * elem_size);
|
||||||
|
if (queue->buffer == NULL) {
|
||||||
|
free(queue);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue->front = 0;
|
||||||
|
queue->rear = 0;
|
||||||
|
queue->size = 0;
|
||||||
|
queue->capacity = queue_size;
|
||||||
|
queue->elem_size = elem_size;
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mcl_queue_push(mcl_queue *queue, const void *elem) {
|
||||||
|
if (queue->size == queue->capacity) {
|
||||||
|
/* Queue full */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the elem in the buffer */
|
||||||
|
void *dest = (void *)queue->buffer + (queue->rear * queue->elem_size);
|
||||||
|
memcpy(dest, elem, queue->elem_size);
|
||||||
|
|
||||||
|
queue->size++;
|
||||||
|
queue->rear = (queue->rear + 1) % queue->capacity;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mcl_queue_pop(mcl_queue *queue, void *out_elem) {
|
||||||
|
if (queue->size == 0) {
|
||||||
|
/* Queue empty */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *src = (void *)queue->buffer + (queue->front * queue->elem_size);
|
||||||
|
memcpy(out_elem, src, queue->elem_size);
|
||||||
|
|
||||||
|
queue->front = (queue->front + 1) % queue->capacity;
|
||||||
|
queue->size--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mcl_queue_get_front(mcl_queue *queue) {
|
||||||
|
if (queue->size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)queue->buffer + (queue->front * queue->elem_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mcl_queue_get_rear(mcl_queue *queue) {
|
||||||
|
if (queue->size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rear_index;
|
||||||
|
if (queue->rear == 0) {
|
||||||
|
rear_index = queue->capacity - 1;
|
||||||
|
} else {
|
||||||
|
rear_index = queue->rear - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)queue->buffer + (rear_index * queue->elem_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcl_queue_free(mcl_queue *queue) {
|
||||||
|
if (queue == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(queue->buffer);
|
||||||
|
free(queue);
|
||||||
|
}
|
||||||
68
queue/myqueue.h
Normal file
68
queue/myqueue.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef MYCLIB_QUEUE_H
|
||||||
|
#define MYCLIB_QUEUE_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A generic circular queue (ring buffer).
|
||||||
|
*/
|
||||||
|
typedef struct mcl_queue_t {
|
||||||
|
size_t front; /**< Index of the first element (read position). */
|
||||||
|
size_t rear; /**< Index where the next element will be written (write position). */
|
||||||
|
size_t size; /**< Current number of elements in the queue. */
|
||||||
|
size_t capacity; /**< Maximum number of elements the queue can hold. */
|
||||||
|
size_t elem_size; /**< Size in bytes of each element in the queue. */
|
||||||
|
void *buffer; /**< Pointer to the memory buffer that stores the elements. */
|
||||||
|
} mcl_queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create and initialize a new queue.
|
||||||
|
*
|
||||||
|
* @param queue_size Number of elements the queue can hold.
|
||||||
|
* @param elem_size Size (in bytes) of each element in the queue.
|
||||||
|
* @return Pointer to the new queue, or NULL if allocation fails.
|
||||||
|
*/
|
||||||
|
mcl_queue *mcl_queue_init(size_t queue_size, size_t elem_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add an element to the queue.
|
||||||
|
*
|
||||||
|
* @param queue Pointer to the queue.
|
||||||
|
* @param elem Pointer to the element to insert.
|
||||||
|
* @return 0 on success, -1 if the queue is full.
|
||||||
|
*/
|
||||||
|
int mcl_queue_push(mcl_queue *queue, const void *elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove an element from the queue.
|
||||||
|
*
|
||||||
|
* @param queue Pointer to the queue.
|
||||||
|
* @param out_elem Pointer where the removed element will be copied.
|
||||||
|
* @return 0 on success, -1 if the queue is empty.
|
||||||
|
*/
|
||||||
|
int mcl_queue_pop(mcl_queue *queue, void *out_elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a pointer to the front element of the queue (oldest one).
|
||||||
|
*
|
||||||
|
* @param queue Pointer to the queue.
|
||||||
|
* @return Pointer to the front element, or NULL if the queue is empty.
|
||||||
|
*/
|
||||||
|
void *mcl_queue_get_front(mcl_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a pointer to the rear element of the queue (most recently added).
|
||||||
|
*
|
||||||
|
* @param queue Pointer to the queue.
|
||||||
|
* @return Pointer to the rear element, or NULL if the queue is empty.
|
||||||
|
*/
|
||||||
|
void *mcl_queue_get_rear(mcl_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free all memory used by the queue.
|
||||||
|
*
|
||||||
|
* @param queue Pointer to the queue to free.
|
||||||
|
*/
|
||||||
|
void mcl_queue_free(mcl_queue *queue);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,13 +5,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
mcl_string *mcl_string_new(const char *text, long initial_capacity) {
|
mcl_string *mcl_string_new(const char *text, long initial_capacity) {
|
||||||
if (!text) {
|
if (text == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate string struct */
|
/* Allocate string struct */
|
||||||
mcl_string *str = malloc(sizeof(mcl_string));
|
mcl_string *str = malloc(sizeof(mcl_string));
|
||||||
if (!str) {
|
if (str == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ mcl_string *mcl_string_new(const char *text, long initial_capacity) {
|
|||||||
|
|
||||||
/* Allocate data buffer */
|
/* Allocate data buffer */
|
||||||
str->data = malloc(sizeof(char) * str->capacity);
|
str->data = malloc(sizeof(char) * str->capacity);
|
||||||
if (!str->data) {
|
if (str->data == NULL) {
|
||||||
free(str);
|
free(str);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -46,7 +46,7 @@ mcl_string *mcl_string_new(const char *text, long initial_capacity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mcl_string_append(mcl_string *string, const char *text) {
|
int mcl_string_append(mcl_string *string, const char *text) {
|
||||||
if (!string || !text) {
|
if (string == NULL || text == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ int mcl_string_append(mcl_string *string, const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mcl_string_free(mcl_string *string) {
|
void mcl_string_free(mcl_string *string) {
|
||||||
if (!string) {
|
if (string == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ void mcl_string_free(mcl_string *string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t mcl_string_length(const mcl_string *string) {
|
size_t mcl_string_length(const mcl_string *string) {
|
||||||
if (!string) {
|
if (string == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ size_t mcl_string_length(const mcl_string *string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t mcl_string_capacity(const mcl_string *string) {
|
size_t mcl_string_capacity(const mcl_string *string) {
|
||||||
if (!string) {
|
if (string == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ size_t mcl_string_capacity(const mcl_string *string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *mcl_string_cstr(const mcl_string *string) {
|
const char *mcl_string_cstr(const mcl_string *string) {
|
||||||
if (!string || !string->data) {
|
if (string == NULL || string->data == NULL) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user