# queue **Repository Path**: Lamdonn/queue ## Basic Information - **Project Name**: queue - **Description**: Very small and convenient general-purpose queue in C language version. C语言版本的非常小且方便的通用队列。 - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 4 - **Created**: 2023-08-02 - **Last Updated**: 2025-08-07 ## Categories & Tags **Categories**: message-server **Tags**: None ## README # queue [中文版](README_zh.md) #### Description This is a general-purpose queue in C language, which is simple, compact, general-purpose, reliable and efficient. It supports any data type and is very simple to use. This queue is very reliable in standard usage. This queue has two entrances and exits at the front and back, and data can be pushed and popped at both ends, and the queue form of `FIFO` (first in first out) and the stack form of `FILO` (first in last out) can be realized. #### Software Architecture It does not depend on any third-party library, not even on the C language standard library, and has an independent single-file structure. #### Installation Just download queue.c and queue.h directly to participate in the compilation. #### Instructions * Define the queue ```c #define queue(type, capacity) ``` This queue does not involve the allocation of memory space, so there is no need to release space after use. When defining, it is as simple as `int a = 5;`. | Parameter | Description | |-----|------| | type | Data type, such as int, char, float, struct, etc. | | capacity | Queue capacity, that is, how many queue data the queue can hold at most | | Return value | Description | |-----|------| | queue | Queue handle | Example: ```c queue c = queue(char, 1024); // Define a queue of type char and capacity 1024 queue i = queue(int, 10); // Define a queue of type int and capacity 10 queue s = queue(struct STUDENT, 10); // Define a queue of type structure and capacity 10 ``` * Enqueue ```c int queue_push(queue queue, void* data); int queue_push2(queue queue, void* data); ``` These two methods are used in the same way, `queue_push2` will overwrite the old data to force push. | Parameter | Description | |-----|------| | queue | Queue handle | | data | Address of the data to be queued (the data type must be consistent with the type defined at the time of definition). You can pass in `0` (NULL) to push in an empty data (whatever is stored at the original address) | | Return value | Description | |-----|------| | 1 | Successful operation | | 0 | Failed operation | Example: ```c queue q = queue(int, 6); // Define a queue of type int and capacity 6 int i = 10; queue_push(q, &i); // Push data of i according to the address of i queue_push2(q, literal(int, 3)); // Push data 3 ``` In this `literal(type, value)` macro is used to facilitate pushing literal data, which is similar to getting the address of the literal `3` and passing this address to the `push` method. * Dequeue ```c int queue_pop(queue queue, void* data); ``` This method will pop the data. | Parameter | Description | |-----|------| | queue | Queue handle | | data | Address to receive dequeued data (data type must be consistent with the type defined), `0` (NULL) can be passed in to not receive dequeued data | | Return value | Description | |-----|------| | 1 | Operation successful | | 0 | Operation failed | Example: ```c queue q = queue(int, 6); // Define a queue of type int and capacity 6 int i = 10; queue_push(q, &i); queue_push(q, literal(int, 3)); queue_push(q, literal(int, 4)); queue_pop(q, &i); // Pop up data and save it in i queue_pop(q, 0); // Pop up data and do not save popped data ``` * Insert ```c int queue_insert(queue queue, int index, void* data); ``` Insert data into the specified queue and the specified position. | Parameter | Description | |-----|------| | queue | Queue handle | | index | Queue index (starting from index 0, from the head to the tail) | | data | The address of the data to be added to the queue (the data type must be consistent with the type when it is defined). You can pass in `0` (NULL) to push an empty data (what is stored in the original address is what it is) | | Return value | Description | |-----|------| | 1 | Operation successful | | 0 | Operation failed | Example: ```c queue q = queue(int, 6); // Define a queue of type int and capacity 6 int i = 10; queue_insert(q, 0, literal(int, 3)); // Insert data 3 at index 0 queue_insert(q, 1, literal(int, 4)); // Insert data 4 at index 1 queue_insert(q, 2, literal(int, 5)); // Insert data 5 at index 2 ``` * Erase ```c int queue_erase(queue queue, int index, void* data); ``` Erase the specified index data from the queue. | Parameter | Description | |-----|------| | queue | Queue handle | | index | Queue index (starting from index 0, from the head to the tail) | | data | Address to receive dequeued data (the data type must be consistent with the type defined at the time of definition). You can pass in `0` (NULL) to not receive dequeued data | | Return value | Description | |-----|------| | 1 | Operation successful | | 0 | Operation failed | Example: ```c queue q = queue(int, 6); // Define a queue of type int and capacity 6 int i = 10; queue_push(q, &i); queue_push(q, literal(int, 3)); queue_push(q, literal(int, 4)); queue_erase(q, 0, NULL); queue_erase(q, 1, &i); ``` * Double-ended operation ```c #define queue_push_front(queue, data) #define queue_push_back(queue, data) #define queue_pop_front(queue, data) #define queue_pop_back(queue, data) ``` Usage is the same as above * Clear ```c void queue_clear(queue queue); ``` This function clears all the data in the queue and restores it to the initialized state. It actually adjusts the index pointed to by the head and tail, without actually deleting the data. | Parameter | Description | |-----|------| | queue | Queue handle | | Return value | Description | |-----|------| | void | | Example: ```c queue q = queue(int, 10); int data = 100; queue_push(q, &data); queue_clear(q); // Clear queue data ``` * Get ```c void* queue_data(queue queue, int index); ``` This function gets the address of the element in the queue based on the index. | Parameter | Description | |-----|------| | queue | Queue handle | | index | Queue index (starting from index 0, from the head to the tail) | | Return value | Description | |-----|------| | !0 | Queue item address | | 0 | Failed to obtain | Use this function to form the `at` macro definition method: ```c #define queue_at(queue, type, i) ``` The `at` method is similar to the C++ reference in usage, and actually points to this address for operation. | Parameter | Description | |-----|------| | queue | Queue handle | | type | Queue item data type, consistent with the queue definition | | i | Queue index (starting from index 0, from the head to the tail) | | Return value | Description | |-----|------| | Queue item reference | Before using, you must first ensure that the queue is valid, the type is valid, and the index i is valid | Example: ```c queue q = queue(int, 10); int data = 100; void *p; queue_push(q, &data); queue_push(q, &data); p = queue_data(q, 0); // Get the address of the queue item if (p) printf("%d\r\n", *(int *)p); // Determine if the address is valid queue_at(q, int, 1) = 100; // Modify the element with index 1 to 100 printf("q[0] = %d\n", queue_at(q, int, 0)); // Print the element with index 0 ``` * Empty and full ```c #define queue_empty(queue) #define queue_full(queue) ``` These two methods are used to determine whether the queue is empty or full, respectively, and the usage is the same. Actually, it is to determine the size of the queue. If it is equal to 0, it is empty, and if it is equal to the capacity, it is full. | Parameter | Description | |-----|------| | queue | Queue handle | | Return value | Description | |-----|------| | 0 | Inconsistent | | !0 | Consistent | * Queue structure member ```c /* queue type define */ typedef struct QUEUE { void* base; /* Protected: base address of data */ int dsize; /* Protected: size of queue data */ int capacity; /* Protected: capacity of queue */ int size; /* Protected: size of queue */ int head; /* Protected: index of queue head */ int tail; /* Protected: index of queue tail */ } *queue; ``` In the `queue` structure member, **please do not modify any of the members directly**. You can read the `size` member, which is the queue size (the number of queue items). You can read the `dsize` member, which is the size of the queue data item, such as `sizeof(int)`. You can read the `capacity` member, which is the capacity of the queue, corresponding to `capacity` in the `queue(type, capacity)` definition method. * Example ```c int main(int argc, char *argv[]) { queue q = queue(int, 6); // Define a queue of int type with a capacity of 6 int i = 0; // Push to fill the entire queue according to the capacity for (i = 0; i < q->capacity; i++) { queue_push(q, literal(int, 100 + i)); // Pass parameters through literals } // Traverse the queue for (i = 0; i < q->size; i++) { printf("q[%d] = %d\r\n", i, queue_at(q, int, i)); } queue_pop(q, 0); queue_pop(q, 0); queue_push(q, literal(int, 1024)); // Push 1024 printf("------------- modify -------------\r\n"); // Traverse the queue for (i = 0; i < q->size; i++) { printf("q[%d] = %d\r\n", i, queue_at(q, int, i)); } return 0; } ``` Result: ``` q[0] = 100 q[1] = 101 q[2] = 102 q[3] = 103 q[4] = 104 q[5] = 105 ------------- modify ------------- q[0] = 102 q[1] = 103 q[2] = 104 q[3] = 105 q[4] = 1024 ``` #### Contact information Lamdonn@163.com