summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Esteves <contact@robertoesteves.dev>2025-07-28 09:05:23 -0300
committerRoberto Esteves <contact@robertoesteves.dev>2025-07-28 09:05:23 -0300
commit72163dc50dde4e07d9d4a17e872a302190fab0bc (patch)
tree9e550af0a411fdfe2badac6b7c7edbb7a767d9f1
init commitHEADmaster
-rw-r--r--.gitignore2
-rw-r--r--include/ui_utils.h151
-rw-r--r--library/base_components.c21
-rw-r--r--library/meson.build7
-rw-r--r--library/renderer.c19
-rw-r--r--library/tree.c16
-rw-r--r--library/ui.c3
-rw-r--r--meson.build23
-rw-r--r--uicc/main.c9
-rw-r--r--uicc/meson.build8
-rw-r--r--uicc/reader.c37
-rw-r--r--uicc/tokenizer.c15
12 files changed, 311 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bc95448
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.cache/
+build/
diff --git a/include/ui_utils.h b/include/ui_utils.h
new file mode 100644
index 0000000..5510433
--- /dev/null
+++ b/include/ui_utils.h
@@ -0,0 +1,151 @@
+#ifndef UI_UTILS
+#define UI_UTILS
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifdef _GNU_SOURCE
+#include <stdalign.h>
+#endif
+
+#define UI_INTERNAL static
+#define UI_GLOBAL
+
+typedef signed char i8;
+typedef unsigned char u8;
+typedef signed short int i16;
+typedef unsigned short int u16;
+typedef signed int i32;
+typedef unsigned int u32;
+typedef signed long int i64;
+typedef unsigned long int u64;
+
+UI_INTERNAL void __crash_error(const char *message, const char *file,
+ u32 line) {
+ fprintf(stderr, "(%s:%d): %s\n", file, line, message);
+ exit(1);
+}
+
+#define crash_error(message) __crash_error(message, __FILE__, __LINE__)
+#define crash_errno() __crash_error(strerror(errno), __FILE__, __LINE__)
+
+#define assert_mmap(expr) \
+ if ((expr) == MAP_FAILED) \
+ crash_errno()
+
+#define assert_errno(expr) \
+ if (errno != 0) \
+ crash_errno()
+
+#define assert_success(actual, expected) \
+ if ((actual) != expected) \
+ crash_error("assertion failed")
+
+#define assert_failure(actual, expected) \
+ if ((actual) == expected) \
+ crash_error("assertion failed")
+
+typedef struct {
+ uint64_t size;
+ const char *buf;
+} String;
+
+String string_slice(const char *cStr) {
+ String str = {0};
+ str.size = strlen(cStr);
+ str.buf = cStr;
+
+ return str;
+}
+
+typedef struct {
+ u64 size;
+ u64 capacity;
+ u8 *buffer;
+} Arena;
+
+Arena *arena_init(void) {
+ Arena *arena = malloc(sizeof(Arena));
+ size_t page_size = sysconf(_SC_PAGE_SIZE);
+ arena->capacity = page_size * 4;
+
+ assert_mmap(arena->buffer = mmap(0, arena->capacity, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0));
+
+ return arena;
+}
+
+void *arena_alloc(Arena *arena, u64 size, u8 align) {
+ void *mem;
+ u8 offset;
+
+ u64 available = arena->capacity - arena->size;
+ if (size > available) {
+ assert_mmap(arena->buffer = mremap(arena->buffer, arena->size,
+ arena->size + (available * 2), 0));
+ }
+
+ mem = &(arena->buffer[arena->size]);
+ offset = (u64)mem % align;
+ mem = (void *)((u64)mem + offset);
+ arena->size += size + offset;
+ return mem;
+}
+
+void arena_zero(Arena *arena) {
+ arena->size = 0;
+ memset(arena->buffer, 0, arena->size);
+}
+
+void arena_free(Arena *arena) {
+ if (munmap(arena->buffer, arena->capacity) == -1) {
+ crash_error("can't unmap arena");
+ }
+
+ arena->buffer = 0;
+ arena->size = 0;
+ arena->capacity = 0;
+}
+
+typedef struct {
+ Arena *arena;
+ u64 initial;
+} ArenaTemp;
+
+ArenaTemp *arena_temp(Arena *arena) {
+ ArenaTemp *temp = malloc(sizeof(ArenaTemp));
+ temp->arena = arena;
+ temp->initial = arena->size;
+
+ return temp;
+}
+
+void arena_temp_free(ArenaTemp *temp) {
+ temp->arena->size = temp->initial;
+ free(temp);
+}
+
+#if __STDC_VERSION__ >= 202311L
+#define arena_type(arena, type) \
+ (type *)(arena_alloc(arena, sizeof(type), alignof(type)))
+#define arena_array(arena, type, size) \
+ (type *)(arena_alloc(arena, sizeof(type) * size, alignof(type)))
+#elif __STDC_VERSION__ >= 201112L
+(type *)(arena_alloc(arena, sizeof(type), _Alignof(type)))
+#define arena_array(arena, type, size) \
+ (type *)(arena_alloc(arena, sizeof(type) * size, _Alignof(type)))
+#else
+#define arena_type(arena, type) \
+ (type *)(arena_alloc(arena, sizeof(type), __alignof__(type)))
+#define arena_array(arena, type, size) \
+ (type *)(arena_alloc(arena, sizeof(type) * size, __alignof__(type)))
+#endif
+
+#endif
diff --git a/library/base_components.c b/library/base_components.c
new file mode 100644
index 0000000..fb49d2b
--- /dev/null
+++ b/library/base_components.c
@@ -0,0 +1,21 @@
+#include <utils.h>
+
+typedef struct {
+ String label;
+} Button;
+
+typedef struct {
+ String value;
+} Text;
+
+typedef struct {
+ String value;
+} TextInput;
+
+typedef struct {
+ Node *children
+} ListBox;
+
+typedef struct {
+ Node *children
+} Stack;
diff --git a/library/meson.build b/library/meson.build
new file mode 100644
index 0000000..deae140
--- /dev/null
+++ b/library/meson.build
@@ -0,0 +1,7 @@
+uil_include = include_directories('include')
+
+sources = files(
+ 'layout.c',
+)
+
+uil = library('ui', sources)
diff --git a/library/renderer.c b/library/renderer.c
new file mode 100644
index 0000000..55bedb7
--- /dev/null
+++ b/library/renderer.c
@@ -0,0 +1,19 @@
+#include <utils.h>
+
+// TODO(roberto): support more pixel formats, for now we're assuming BGRA
+typedef struct {
+ u16 width;
+ u16 height;
+ u16 stride;
+ u16 bpp;
+ u8 *bytes;
+} PixelBuffer;
+
+typedef enum {
+ SOFTWARE,
+} RendererType;
+
+typedef struct {
+ RenderType type;
+ void *renderer;
+} Renderer;
diff --git a/library/tree.c b/library/tree.c
new file mode 100644
index 0000000..0519767
--- /dev/null
+++ b/library/tree.c
@@ -0,0 +1,16 @@
+#include <utils.h>
+
+typedef struct {
+ Node *parent;
+ u64 nodeType;
+ void *value;
+} Node;
+
+typedef struct {
+ void *page;
+} TreeAllocator;
+
+typedef struct {
+ TreeAllocator allocactor;
+ Node *root;
+} Tree;
diff --git a/library/ui.c b/library/ui.c
new file mode 100644
index 0000000..213fb57
--- /dev/null
+++ b/library/ui.c
@@ -0,0 +1,3 @@
+typedef struct {
+ Tree tree;
+} UIContext;
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..69b23a7
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,23 @@
+project(
+ 'ui',
+ 'c',
+ meson_version: '>= 1.3.0',
+ version: '0.1',
+ default_options: ['warning_level=3', 'c_std=c89'],
+)
+
+compile_args = []
+if host_machine.system() == 'linux'
+ compile_args += ['-D_GNU_SOURCE']
+elif host_machine.system() == 'darwin'
+ compile_args += ['-D_DARWIN_C_SOURCE']
+elif host_machine.system() == 'windows'
+ compile_args += ['-D_WIN32_WINNT=0x0601']
+endif
+
+add_global_arguments(compile_args, language: ['c'])
+
+ui_include = include_directories('include')
+
+subdir('library')
+subdir('uicc')
diff --git a/uicc/main.c b/uicc/main.c
new file mode 100644
index 0000000..6f0d276
--- /dev/null
+++ b/uicc/main.c
@@ -0,0 +1,9 @@
+#include "arena.c"
+#include "reader.c"
+#include "tokenizer.c"
+#include "utils.c"
+
+int main(int argc, char **argv) {
+ printf("teste: %s\n", argv[0]);
+ return 0;
+}
diff --git a/uicc/meson.build b/uicc/meson.build
new file mode 100644
index 0000000..9696dba
--- /dev/null
+++ b/uicc/meson.build
@@ -0,0 +1,8 @@
+preprocessorSources = files('main.c', 'reader.c', 'tokenizer.c')
+
+executable(
+ 'uicc',
+ preprocessorSources,
+ include_directories: ui_include,
+ install: true,
+)
diff --git a/uicc/reader.c b/uicc/reader.c
new file mode 100644
index 0000000..ea21b82
--- /dev/null
+++ b/uicc/reader.c
@@ -0,0 +1,37 @@
+#include <ui_utils.h>
+
+typedef struct {
+ int fd;
+ uint64_t buffer_size;
+ char *buffer;
+} Reader;
+
+Reader *reader_open(Arena *arena, const char *path, uint64_t buffer_size) {
+ Reader *reader = {0};
+ int fd;
+
+ assert_failure(fd = open(path, O_RDONLY, O_NOFOLLOW), -1);
+
+ reader = arena_type(arena, Reader);
+ reader->fd = fd;
+ reader->buffer_size = buffer_size;
+ reader->buffer = arena_array(arena, char, reader->buffer_size);
+
+ return reader;
+}
+
+void reader_advance(Reader *self, uint32_t *start, uint32_t *end) {
+ if (*end > self->buffer_size) {
+ if (*start == 0) {
+ /* TODO(roberto): maybe reallocate the buffer instead of crashing */
+ crash_error("ERROR: token is too long\n");
+ }
+
+ assert_errno(lseek(self->fd, *start * -1, SEEK_CUR));
+ assert_errno(read(self->fd, self->buffer, self->buffer_size));
+ *end -= *start;
+ *start = 0;
+ }
+}
+
+void reader_close(Reader *self) { close(self->fd); }
diff --git a/uicc/tokenizer.c b/uicc/tokenizer.c
new file mode 100644
index 0000000..90ac274
--- /dev/null
+++ b/uicc/tokenizer.c
@@ -0,0 +1,15 @@
+/**
+ * Definição de elemento
+ * Elemento {
+ * propriedade: valor
+ * }
+ *
+ * Definição do layout
+ * <ContainerList>
+ * <Button label="Olá">
+ * </ContainerList>
+ */
+
+#include "reader.c"
+
+void tokenizeElement(int fd) {}