feat: add ListNode
This commit is contained in:
1 parent
c069cdcbe6
commit
fd358f0fa6
2 files changed
+114
No files matched your search
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef FROSTBYTE_KLIB_H
|
||||||
|
#define FROSTBYTE_KLIB_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* klib: freestanding string/number utilities that build on top of the
|
||||||
|
* primitive mem-family and str-family routines in string.h. No libc, no
|
||||||
|
* heap dependency (callers pass their own buffers), safe to use before the
|
||||||
|
* heap is set up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---- character classification -------------------------------------- */
|
||||||
|
|
||||||
|
bool isDigit(int c);
|
||||||
|
bool isAlpha(int c);
|
||||||
|
bool isAlnum(int c);
|
||||||
|
bool isSpace(int c);
|
||||||
|
bool isUpper(int c);
|
||||||
|
bool isLower(int c);
|
||||||
|
bool isHexDigit(int c);
|
||||||
|
int toUpper(int c);
|
||||||
|
int toLower(int c);
|
||||||
|
|
||||||
|
/* ---- string manipulation --------------------------------------------
|
||||||
|
Semantics match the C standard library equivalents (including the
|
||||||
|
footguns: strcpy/strcat assume a big-enough destination). */
|
||||||
|
|
||||||
|
char* strcpy(char* dest, const char* src);
|
||||||
|
char* strncpy(char* dest, const char* src, usize count);
|
||||||
|
char* strcat(char* dest, const char* src);
|
||||||
|
char* strncat(char* dest, const char* src, usize count);
|
||||||
|
char* strchr(const char* str, int c);
|
||||||
|
char* strrchr(const char* str, int c);
|
||||||
|
char* strstr(const char* haystack, const char* needle);
|
||||||
|
usize strspn(const char* str, const char* accept);
|
||||||
|
usize strcspn(const char* str, const char* reject);
|
||||||
|
|
||||||
|
/* Reentrant tokenizer (no hidden static state, safe across threads).
|
||||||
|
Pass str on the first call, nullptr on subsequent calls; *savePtr
|
||||||
|
carries the position between calls (caller owns the storage). */
|
||||||
|
char* strTokR(char* str, const char* delim, char** savePtr);
|
||||||
|
|
||||||
|
/* ---- number parsing --------------------------------------------------- */
|
||||||
|
|
||||||
|
int32 atoi(const char* str);
|
||||||
|
int64 atol(const char* str);
|
||||||
|
|
||||||
|
/* base 0 means auto-detect: "0x"/"0X" prefix -> 16, leading "0" -> 8,
|
||||||
|
otherwise 10. base must be 0 or in [2, 36] otherwise. If endPtr is
|
||||||
|
non-null, *endPtr is set to the first unconsumed character. */
|
||||||
|
int64 strtol(const char* str, char** endPtr, int base);
|
||||||
|
uint64 strtoul(const char* str, char** endPtr, int base);
|
||||||
|
|
||||||
|
/* ---- formatted output into a caller-owned buffer ----------------------
|
||||||
|
Same contract as C99 snprintf: writes at most size-1 characters plus a
|
||||||
|
terminating nul (unless size == 0), and returns the number of characters
|
||||||
|
that *would* have been written given an unbounded buffer. Supports
|
||||||
|
%c %s %d %i %u %x %X %p %%, an 'l' length modifier for 64-bit args, and
|
||||||
|
a zero-padded/space-padded minimum field width. */
|
||||||
|
int snprintf(char* buf, usize size, const char* format, ...);
|
||||||
|
int vsnprintf(char* buf, usize size, const char* format, va_list args);
|
||||||
|
|
||||||
|
/* ---- generic sorting / searching --------------------------------------
|
||||||
|
Same contract as C's qsort/bsearch: cmp returns <0, 0, >0. */
|
||||||
|
void qsort(void* base, usize count, usize size, int (*cmp)(const void*, const void*));
|
||||||
|
void* bsearch(const void* key, const void* base, usize count, usize size,
|
||||||
|
int (*cmp)(const void*, const void*));
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef FROSTBYTE_LIST_H
|
||||||
|
#define FROSTBYTE_LIST_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List: an intrusive circular doubly-linked list, Linux-kernel style. The
|
||||||
|
* list head and every node share the same ListNode type; a sentinel node
|
||||||
|
* (passed to listInit) acts as both head and tail so insert/remove never
|
||||||
|
* need a null check. Embed a ListNode in your own struct and use
|
||||||
|
* listEntry() to recover the containing struct pointer -- no allocation,
|
||||||
|
* no element copying, just pointer relinking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct ListNode {
|
||||||
|
struct ListNode* next;
|
||||||
|
struct ListNode* prev;
|
||||||
|
} ListNode;
|
||||||
|
|
||||||
|
#define listEntry(ptr, type, member) \
|
||||||
|
((type*)((uint8*)(ptr) - offsetof(type, member)))
|
||||||
|
|
||||||
|
#define listForEach(cursor, head) \
|
||||||
|
for ((cursor) = (head)->next; (cursor) != (head); (cursor) = (cursor)->next)
|
||||||
|
|
||||||
|
void listInit(ListNode* head);
|
||||||
|
bool listEmpty(const ListNode* head);
|
||||||
|
|
||||||
|
void listInsertAfter(ListNode* pos, ListNode* newNode);
|
||||||
|
void listInsertBefore(ListNode* pos, ListNode* newNode);
|
||||||
|
void listPushBack(ListNode* head, ListNode* newNode);
|
||||||
|
void listPushFront(ListNode* head, ListNode* newNode);
|
||||||
|
|
||||||
|
/* Unlinks node from whatever list it is in. Safe to call again on an
|
||||||
|
already-removed node (it becomes its own trivial one-element list). */
|
||||||
|
void listRemove(ListNode* node);
|
||||||
|
|
||||||
|
usize listLen(const ListNode* head);
|
||||||
|
ListNode* listFront(const ListNode* head);
|
||||||
|
ListNode* listBack(const ListNode* head);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in new issue
Block a user