Skip to content

Instantly share code, notes, and snippets.

@zkbpkp
Created February 8, 2021 19:51
Show Gist options
  • Save zkbpkp/4aeb0c448e6dae156c7a3a0c29d13383 to your computer and use it in GitHub Desktop.
Save zkbpkp/4aeb0c448e6dae156c7a3a0c29d13383 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
int baz;
} bar;
typedef struct {
bar *bar;
int baz;
} foo;
typedef struct lens {
size_t *offsets;
size_t size;
} lens;
lens idLens() {
lens l = { NULL, 0 };
return l;
}
lens offsetLens(size_t offset) {
size_t *offsets = malloc(sizeof(size_t));
lens l = { offsets, 1 };
return l;
}
lens addOffsetLens(lens *l, size_t o) {
if (l->size == 0) { return offsetLens(o); }
size_t *offsets = malloc(l->size * sizeof(size_t));
for (int i = 0; i < l->size; i++) {
offsets[i] = l->offsets[i];
}
offsets[l->size - 1] += o;
lens l2 = { offsets, l->size };
return l2;
}
lens composeLens(lens *l1, lens *l2) {
size_t *offsets = malloc((l1->size + l2->size) * sizeof(size_t));
if (l1->offsets != NULL) {
for (int i = 0; i < l1->size; i++) {
offsets[i] = l1->offsets[i];
}
}
if (l2->offsets != NULL) {
for (int i = 0; i < l2->size; i++) {
offsets[l1->size + i] = l2->offsets[i];
}
}
lens l = { offsets, l1->size + l2->size };
return l;
}
void* get(void *s, lens *l) {
void* p = s;
for (int i = 0; i < l->size; i++) {
intptr_t f = ((intptr_t*)p)[l->offsets[i]];
p = (void*) f;
}
return p;
}
void set_int(void *s, lens *l, int v) {
if (l->size == 0) *(int*)s = v;
void *p = s;
for (int i = 0; i < l->size - 1; i++) {
intptr_t f = ((intptr_t*)p)[l->offsets[i]];
p = (void*) f;
}
((int*)p)[l->offsets[l->size - 1]] = v;
}
static lens _foo_bar;
static lens _bar_baz;
static lens _foo_bar_baz;
int main() {
_foo_bar = offsetLens(offsetof(foo, bar));
_bar_baz = offsetLens(offsetof(bar, baz));
_foo_bar_baz = composeLens(&_foo_bar, &_bar_baz);
bar b = { 42 };
foo f = { &b, 666 };
printf("f.bar->baz = %d\n", (int)(get(&f, &_foo_bar_baz)));
set_int(&f, &_foo_bar_baz, 666);
printf("f.bar->baz = %d\n", (int)(get(&f, &_foo_bar_baz)));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment