undar-lang/test/plex.c

153 lines
3.3 KiB
C

#include <stdio.h>
#include <string.h>
typedef struct arena_s Arena;
struct arena_s {
unsigned char *tape;
unsigned int count;
unsigned int capacity;
};
void *aalloc(Arena *arena, unsigned int size){
unsigned int pos;
if(arena == NULL) return NULL;
if(arena->count + size > arena->capacity) return NULL;
pos = arena->count;
arena->count += size;
return (void *)&arena->tape[pos];
}
unsigned int
scpy(char *to, const char *from, unsigned int length)
{
unsigned int i;
if(to == NULL || from == NULL) return -1;
if(length == 0) return 0;
for(i = 0; i < length - 1 && from[i] != '\0'; i++) to[i] = from[i];
to[i] = '\0';
return 0;
}
char *
ascpy(Arena *arena, const char *start, unsigned int length)
{
char *str;
if(!start) return NULL;
str = (char *)aalloc(arena, length + 1);
if(!str) return NULL;
scpy(str, start, length);
return str;
}
void *
areturn(Arena *arena, unsigned int checkpoint, const void *src, unsigned int size)
{
void *dest;
if(arena == NULL || src == NULL) return NULL;
dest = (void *)&arena->tape[checkpoint];
if (src == dest) return dest;
memmove(dest, src, size);
arena->count = checkpoint + size;
return dest;
}
#define ARENA_RETURN(arena, ckpt, src_ptr, type) \
return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type))
#define ARENA_RETURN_ARRAY(arena, ckpt, src_ptr, type, count) \
return (type *)areturn((arena), (ckpt), (src_ptr), sizeof(type) * (count))
typedef struct Point Point;
struct Point {
unsigned int x;
unsigned int y;
};
Point *
Point_new(Arena *a, unsigned int x, unsigned int y)
{
Point *this = (Point *)aalloc(a, sizeof(Point));
this->x = x;
this->y = y;
return this;
}
char*
Point_toS(Arena *a, Point *this)
{
unsigned int ckpt = a->count;
char *s = (char*)&a->tape[a->count];
int len = sprintf(s, "[x:%d, y:%d]",
this->x,
this->y);
s[len] = '\0';
a->count += len + 1;
ARENA_RETURN_ARRAY(a, ckpt, s, char, len + 1);
}
typedef struct Rect Rect;
struct Rect {
Point top_left;
Point bottom_right;
unsigned int width;
unsigned int height;
};
Rect *
Rect_new(Arena *a, Point *tl, Point *br, unsigned int width, unsigned int height)
{
Rect *this = (Rect *)aalloc(a, sizeof(Rect));
memcpy(&this->top_left, tl, sizeof(Point));
memcpy(&this->bottom_right, br, sizeof(Point));
this->width = width;
this->height = height;
return this;
}
char*
Rect_toS(Arena *a, Rect *this)
{
unsigned int ckpt = a->count;
char *s1 = Point_toS(a, &this->top_left);
char *s2 = Point_toS(a, &this->bottom_right);
char *s = (char*)&a->tape[a->count];
int len = sprintf(s, "[top_left: %s, bottom_right: %s, width:%d, height:%d]",
s1,
s2,
this->width,
this->height);
s[len] = '\0';
a->count += len + 1;
ARENA_RETURN_ARRAY(a, ckpt, s, char, len + 1);
}
Rect *
create_geometry(Arena *a)
{
unsigned int ckpt = a->count;
Rect *final_rect;
Point *temp_tl;
Point *temp_br;
temp_tl = Point_new(a, 10, 20);
temp_br = Point_new(a, 100, 200);
final_rect = Rect_new(a, temp_tl, temp_br, 90, 180);
ARENA_RETURN(a, ckpt, final_rect, Rect);
}
int main() {
unsigned char tape[64000];
Arena a = {tape, 0, 64000};
Rect *r = create_geometry(&a);
printf("%s\n", Rect_toS(&a, r));
return 0;
}