diff --git a/brightness.c b/brightness.c new file mode 100644 index 0000000..819225f --- /dev/null +++ b/brightness.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include + +// #define SET_BIT(BF, N) BF |= ((uint64_t)0x1 << N) +// #define CLEAR_BIT(BF, N) BF &= ~((uint64_t)0x1 << N) +// #define IS_BIT_SET(BF, N) ((BF >> N) & 0x1) +// #define SET_BIT(BF, N) ((BF) |= ((typeof(BF))1 << (N))) +// #define CLEAR_BIT(BF, N) ((BF) &= ~((typeof(BF))1 << (N))) +// #define IS_BIT_SET(BF, N) (((BF) >> (N)) & (typeof(BF))1) + +#define UINT_CAST(x) \ + _Generic((x), \ + uint8_t: (uint8_t)1, \ + uint16_t: (uint16_t)1, \ + uint32_t: (uint32_t)1, \ + uint64_t: (uint64_t)1, \ + default: (x) /* fallback */ \ + ) + +#define SET_BIT(BF, N) ((BF) |= (UINT_CAST(BF) << (N))) +#define CLEAR_BIT(BF, N) ((BF) &= ~(UINT_CAST(BF) << (N))) +#define IS_BIT_SET(BF, N) (((BF) >> (N)) & UINT_CAST(BF)) + +typedef enum : char { + BRIGHTNESS_SET_INSTANT, //!< Set instantly with no delay + BRIGHTNESS_CMD_TRY_SET, //!< Set brightness, ignored if setpoint already exists + BRIGHTNESS_CMD_QUEUE, //!< Set brightness, queued if setpoint already exists + BRIGHTNESS_CMD_FORCE, //!< Force set brightness target + BRIGHTNESS_CMD_HOLD, //!< Force set brightness target to current brightness +} brightness_cmd_t; + +typedef struct { + uint8_t type : 8; + uint32_t value : 24; +} brightness_cmd; + +int main(void) { + assert(sizeof(brightness_cmd) == 4); + assert(sizeof(brightness_cmd_t) == 1); + + // Examples + brightness_cmd cmd1 = {.type = BRIGHTNESS_CMD_FORCE, .value = 100}; + brightness_cmd cmd2 = {.type = BRIGHTNESS_CMD_TRY_SET, .value = 50}; + brightness_cmd cmd3 = {.type = BRIGHTNESS_CMD_QUEUE, .value = (1 << 23)}; + + // For readout comparisons later + brightness_cmd read1 = cmd1; + brightness_cmd read2 = cmd2; + brightness_cmd read3 = cmd3; + + SET_BIT(*(int *)&read1, 10); + + // In this case, our command structure fits neatly into a 32 bit integer + // so we can simply cast it directly: + uint32_t int_cmd = *(uint32_t *)&cmd1; + assert(memcmp(&int_cmd, &cmd1, 4) == 0); + + // To buffer + char buf[12]; + + *(uint32_t *)&buf[0] = *(uint32_t *)&cmd1; + *(uint32_t *)&buf[4] = *(uint32_t *)&cmd2; + *(uint32_t *)&buf[8] = *(uint32_t *)&cmd3; + + // Wipe these so we can read them back from the buffer + memset(&cmd1, 0, 4); + memset(&cmd2, 0, 4); + memset(&cmd3, 0, 4); + + // Note that these are neq's + assert(memcmp(&cmd1, &read1, 4) != 0); + assert(memcmp(&cmd2, &read2, 4) != 0); + assert(memcmp(&cmd3, &read3, 4) != 0); + + cmd1 = *(brightness_cmd *)&buf[0]; + cmd2 = *(brightness_cmd *)&buf[4]; + cmd3 = *(brightness_cmd *)&buf[8]; + + assert(memcmp(&cmd1, &read1, 4) == 0); + assert(memcmp(&cmd2, &read2, 4) == 0); + assert(memcmp(&cmd3, &read3, 4) == 0); + + brightness_cmd casted = *(brightness_cmd *)&read1; + assert(memcmp(&read1, &casted, 4) == 0); + + printf("Sizeof(brightness_cmd) = %ld\n", sizeof(brightness_cmd)); + printf("Sizeof(brightness_cmd_t) = %ld\n", sizeof(brightness_cmd)); + printf("All is well!\n"); +} diff --git a/cjson/Makefile b/cjson/Makefile new file mode 100644 index 0000000..ff5f5ab --- /dev/null +++ b/cjson/Makefile @@ -0,0 +1,12 @@ +CC ?= gcc +CFLAGS ?= -Wall -O2 -lcjson + +TARGET = main.elf +SRC = main.c + +$(TARGET): $(SRC) + @echo CC $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(TARGET) diff --git a/cjson/cjson.c b/cjson/main.c similarity index 70% rename from cjson/cjson.c rename to cjson/main.c index cd5f205..30c5d87 100644 --- a/cjson/cjson.c +++ b/cjson/main.c @@ -6,9 +6,10 @@ char *build_set_level_command(int level) { cJSON_AddStringToObject(root, "cmd", "set_level"); cJSON_AddNumberToObject(root, "level", level); - char *message = cJSON_PrintUnformatted(root); + // char *message = cJSON_PrintUnformatted(root); + char *msg2 = cJSON_Print(root); cJSON_Delete(root); - return message; // Remember to free this when done! + return msg2; // Remember to free this when done! } int main(void) { diff --git a/murmur3.c b/murmur3.c index af9d1df..e35ebdb 100644 --- a/murmur3.c +++ b/murmur3.c @@ -23,7 +23,9 @@ uint32_t murmur3_32(const uint8_t* key, size_t len, uint32_t seed) { k = 0; switch (len & 3) { case 3: k ^= key[i + 2] << 16; + /* fall through */ case 2: k ^= key[i + 1] << 8; + /* fall through */ case 1: k ^= key[i + 0]; k *= c1; k = (k << 15) | (k >> (32 - 15)); k *= c2; h ^= k; } diff --git a/poolsclosed/.clang-format b/poolsclosed/.clang-format new file mode 100644 index 0000000..5364839 --- /dev/null +++ b/poolsclosed/.clang-format @@ -0,0 +1,7 @@ +# Language: C +BasedOnStyle: LLVM +IndentWidth: 4 # Use 4 spaces for indentation +TabWidth: 4 # Tab width is also 4 spaces +UseTab: Never # Always use spaces instead of tabs +ColumnLimit: 80 # Wrap lines after 80 characters +AllowShortLoopsOnASingleLine: true diff --git a/poolsclosed/pool.c b/poolsclosed/pool.c new file mode 100644 index 0000000..181ea3a --- /dev/null +++ b/poolsclosed/pool.c @@ -0,0 +1,126 @@ +#include +#include +#include + +/* See: https://8dcc.github.io/programming/pool-allocator.html */ +/* See: https://github.com/8dcc/libpool */ + +#define CHUNK_SIZE 64 + +typedef union Chunk Chunk; +union Chunk { + Chunk *next; // When not null, it is used + char arr[CHUNK_SIZE]; +}; + +typedef struct LinkedPtr LinkedPtr; +struct LinkedPtr { + Chunk *ptr; + LinkedPtr *next; +}; + +typedef struct Pool Pool; +struct Pool { + Chunk *free_chunk; // Pointer to a linked list of free chunks + LinkedPtr *array_starts; +}; + +Pool *pool_new(size_t pool_size) { + Pool *pool = malloc(sizeof(Pool)); + + if (pool == NULL) + return NULL; + + Chunk *arr = pool->free_chunk = malloc(pool_size * sizeof(Chunk)); + if (arr == NULL) { + free(pool); + return NULL; + } + + for (size_t i = 0; i < pool_size - 1; i++) arr[i].next = &arr[i + 1]; + arr[pool_size - 1].next = NULL; + + pool->array_starts = malloc(sizeof(LinkedPtr)); + if (pool->array_starts == NULL) { + /* Allocation failed */ + free(arr); + free(pool); + return NULL; + } + + pool->array_starts->next = NULL; + pool->array_starts->ptr = arr; + + return pool; +} + +void *pool_alloc(Pool *pool) { + if (pool == NULL || pool->free_chunk == NULL) + return NULL; + + // Pop a new one from the free list + Chunk *result = pool->free_chunk; + pool->free_chunk = pool->free_chunk->next; + + return result; +} + +void pool_free(Pool *pool, void *ptr) { + if (pool == NULL || ptr == NULL) + return; + + // This can be done withuot an intermediate ptr + Chunk *freed = ptr; + freed->next = pool->free_chunk; + pool->free_chunk = freed; +} + +void pool_close(Pool *pool) { + if (pool == NULL) + return; + + LinkedPtr *lptr = pool->array_starts; + while (lptr != NULL) { + LinkedPtr *next = lptr->next; + free(lptr->ptr); + free(lptr); + lptr = next; + } + + free(pool); +} + +bool pool_resize(Pool *pool, size_t extra_chunk_num) { + if (pool == NULL || extra_chunk_num == 0) + return false; + + // Allocate the array of extra chunks that we are trying to add to the pool. + Chunk *extra_chunk_arr = malloc(extra_chunk_num * sizeof(Chunk)); + if (extra_chunk_arr == NULL) + return false; + + // Link the new chunks together, just like we did when creating the pool. + for (size_t i = 0; i < extra_chunk_num - 1; i++) + extra_chunk_arr[i].next = &extra_chunk_arr[i + 1]; + + // Prepend the array of extra chunks to the “free chunks” list, just like we + // did when freeing chunks. + extra_chunk_arr[extra_chunk_num - 1].next = pool->free_chunk; + pool->free_chunk = extra_chunk_arr; + + // Allocate a new LinkedPtr structure, and store the start of the new chunk + // array in it. + LinkedPtr *array_start = malloc(sizeof(LinkedPtr)); + if (array_start == NULL) { + free(extra_chunk_arr); + return false; + } + + // Prepend this new LinkedPtr structure to the linked list of “array + // starts”, stored inside the Pool structure. + array_start->ptr = extra_chunk_arr; + array_start->next = pool->array_starts; + pool->array_starts = array_start; + + return true; +} diff --git a/poolsclosed/simpe_pool.c b/poolsclosed/simpe_pool.c new file mode 100644 index 0000000..1f964d0 --- /dev/null +++ b/poolsclosed/simpe_pool.c @@ -0,0 +1,47 @@ +#include +#include + +/* See: https://8dcc.github.io/programming/pool-allocator.html */ + +#define CHUNK_SIZE 64 + +typedef union Chunk Chunk; +union Chunk { + Chunk *next; // When not null, it is used + char arr[CHUNK_SIZE]; +}; + +typedef struct Pool Pool; +struct Pool { + Chunk *free_chunk; // Pointer to a linked list of free chunks + Chunk *chunk_arr; +}; + +void *pool_alloc(Pool *pool) { + if (pool == NULL || pool->free_chunk == NULL) + return NULL; + + // Pop a new one from the free list + Chunk *result = pool->free_chunk; + pool->free_chunk = pool->free_chunk->next; + + return result; +} + +void pool_free(Pool *pool, void *ptr) { + if (pool == NULL || ptr == NULL) + return; + + // This can be done withuot an intermediate ptr + Chunk *freed = ptr; + freed->next = pool->free_chunk; + pool->free_chunk = freed; +} + +void pool_close(Pool *pool) { + if (pool == NULL) + return; + + free(pool->chunk_arr); + free(pool); +} diff --git a/poolsclosed/test.lua b/poolsclosed/test.lua new file mode 100755 index 0000000..60ba9b6 --- /dev/null +++ b/poolsclosed/test.lua @@ -0,0 +1,33 @@ +#!/usr/bin/env lua + +local m = {} + +print("Hello") +os.execute("echo $SHELL") + +m.abc = { + kek = 10, +} + +function m:print() + print(m.abc.kek) +end + +function os.getName() + local osname + -- ask LuaJIT first + if jit then + return jit.os + end + + -- Unix, Linux variants + local fh, _ = assert(io.popen("uname -o 2>/dev/null", "r")) + if fh then + osname = fh:read() + end + + return osname or "Windows" +end + +m:print() +print(os.getName())