1
0
Fork
You've already forked undr
0
C library with multiple utilities
  • C 97.3%
  • Makefile 2.7%
Find a file
2026年06月20日 20:30:12 -03:00
include/undr LST improved, Jwt dates 2026年05月22日 13:38:06 -03:00
src date 2026年05月22日 14:12:35 -03:00
tests jwt date format 2026年05月22日 14:04:28 -03:00
.clang-format format 2026年03月11日 13:10:59 -03:00
.clangd format 2026年03月11日 13:10:59 -03:00
.gitignore jwt decoder validation 2026年03月15日 13:29:46 -03:00
LICENSE codeberg 2026年04月11日 13:29:14 -03:00
Makefile LST improved, Jwt dates 2026年05月22日 13:38:06 -03:00
README.md readme 2026年06月20日 20:30:12 -03:00

undr

Personal C library with multiple utilities. The name undr provides from a short story by Jorge Luis Borges

Caveats

  • This library has been developed on and for Linux following open source philosophy.
  • Dependencies: openssl
  • This library is available in AUR repositories (Arch Linux)

Utilities

  • Format and prettify JSON, XML and HTML strings
  • Arena allocator
  • JWT decoder
  • Minimal String data structure
  • Minimal List data structure

Usage

Format JSON, XML or HTML

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <undr/format.h>
int main() {
 const char* json_input = "{\"a\":1,\"b\":[1,2]}";
 char* json = format_json(json_input, 2, 5);
 printf("formatted json:\n %s\n", json);
 const char* xml_input = "<?xml version=\"1.0\"?><root><user><name>John</name><id>1</id></user></root>";
 char* xml = format_xml(xml_input, 2, 5);
 printf("formatted xml:\n %s\n", xml);
 free(xml_input);
 return 0;
}

Arena

#include <string.h>#include <stdlib.h>#include <undr/arena.h>
int main() {
 Arena *arena = arena_init(1024);
 int *numbers = arena_alloc(arena, 5 * sizeof(int));
 for (int i = 0; i < 5; i++) numbers[i] = i * 10;
 char *msg = arena_alloc(arena, 20);
 strcpy(msg, "Hello Arena!");
 arena_free(arena);
 return 0;
}

JWT decoder

#include <string.h>#include <stdlib.h>#include <undr/jwt.h>
int main() {
 Arena *arena = arena_init(1024);
 const char *raw_jwt =
 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
 "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MD"
 "IyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
 Jwt token = decode_jwt(arena, raw_jwt);
 if (token.header && token.payload) {
 printf("Header:\n %s\n", token.header);
 printf("Payload:\n %s\n", token.payload);
 printf("Created:\n %s\n", token.created_at ? token.created_at : "unknown");
 printf("Expires:\n %s\n", token.expires_at ? token.expires_at : "unknown");
 }
 arena_free(arena);
 return 0;
}

String

#include <undr/str.h>#include <stdio.h>
int main() {
 String s = {0};
 char str[] = " hi";
 if (string_push(&s, str)) puts("err");
 string_push(&s, ", world ");
 printf("init len %lu\n", s.len);
 printf("init cap %lu\n", s.cap);
 printf("data %s\n", s.data);
 printf("contains %b\n", string_contains(s, "world"));
 printf("find %lu\n", string_find(s, "hi"));
 string_trim(&s);
 printf("trimmed %s\n", s.data);
 printf("final len %lu\n", s.len);
 printf("final cap %lu\n", s.cap);
 string_free(&s);
 return 0;
}

List

#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <undr/lst.h>
typedef struct {
 int value;
} Obj;
LST_DEF_TYPE(ObjList, Obj)
void lst_free_fn(void *o) { free(o); }
int main() {
 StringList xs = {0};
 const size_t adder = 4; // How much the list grows if needed
 LST_INIT(xs, 30);
 LST_ADD(xs, strdup("start"), adder);
 for (int x = 0; x < 10; ++x) {
 char buf[10];
 snprintf(buf, 10, "string %d", x);
 LST_ADD(xs, strdup(buf), adder);
 }
 LST_ADD(xs, strdup("end"), adder);
 for (size_t i = 0; i < xs.len; ++i)
 printf("%s\n", xs.items[i]);
 printf("init len %lu\n", xs.len);
 printf("init cap %lu\n", xs.cap);
 void (*fptr)(void *) = lst_free_fn;
 LST_DEL_VAL_FN(xs, 2, fptr);
 for (int x = 1; x < 10; x++) {
 char **value;
 LST_GET(xs, value, x);
 printf("get string %s\n", *value);
 }
 printf("final len %lu\n", xs.len);
 printf("final cap %lu\n", xs.cap);
 LST_DEL_FN(xs, fptr);
 // --------------------------------

 ObjList os = {0};
 Obj o = {.value = 0};
 LST_ADD(os, o, adder);
 for (int x = 0; x < 10; ++x) {
 Obj o = {.value = x};
 LST_ADD(os, o, adder);
 }
 Obj end = {.value = 100};
 LST_ADD(os, end, adder);
 for (size_t i = 0; i < os.len; ++i)
 printf("Obj %d\n", os.items[i].value);
 printf("Ob init len %lu\n", os.len);
 printf("Ob init cap %lu\n", os.cap);
 LST_DEL_VAL(os, 2);
 for (int x = 1; x < 10; x++) {
 Obj *o;
 LST_GET(os, o, x);
 printf("get obj %d\n", o->value);
 }
 printf("Obj final len %lu\n", os.len);
 printf("Obj final cap %lu\n", os.cap);
 LST_DEL(os);
 return 0;
}