Mirai's Miscellaneous Misadventures
M19 / core / behaviors.c
#include <mimimi/behaviors.h>
#include <mimimi/compound-behaviors.h>
#include <mimimi/chapters.h>
#include <mimimi/allocators.h>
struct mimimi_compound_behavior
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
int count;
struct mimimi_behavior **behaviors;
};
static void mimimi_compound_behave(void *data)
{
struct mimimi_compound_behavior *compound = data;
for (int i = 0 ; i < compound->count ; i++)
{
struct mimimi_behavior *behavior = compound->behaviors[i];
(*behavior->behave)(behavior->data);
}
}
static void mimimi_compound_finish(void *data)
{
struct mimimi_compound_behavior *compound = data;
for (int i = 0 ; i < compound->count ; i++)
{
struct mimimi_behavior *behavior = compound->behaviors[i];
(*behavior->finish)(behavior->data);
}
(*compound->allocator->deallocate)(compound->behaviors);
(*compound->allocator->deallocate)(compound->behavior);
(*compound->allocator->deallocate)(compound);
}
struct mimimi_behavior *mimimi_compound_behavior(struct mimimi_allocator *allocator)
{
struct mimimi_compound_behavior *data = (*allocator->allocate)(sizeof *data);
data->allocator = allocator;
data->behavior = (*allocator->allocate)(sizeof *data->behavior);
data->behavior->behave = &mimimi_compound_behave;
data->behavior->finish = &mimimi_compound_behave;
data->behavior->data = data;
data->count = 0;
data->behaviors = allocator->null;
return data->behavior;
}
void mimimi_compound(struct mimimi_behavior *behavior, struct mimimi_behavior *other)
{
struct mimimi_compound_behavior *compound = behavior->data;
compound->count++;
compound->behaviors = (*compound->allocator->reallocate)(compound->behaviors, compound->count * sizeof *compound->behaviors);
compound->behaviors[compound->count - 1] = other;
}
void mimimi_ignore(void *data) { }
static struct mimimi_behavior mimimi_noop_value = {&mimimi_ignore, &mimimi_ignore};
struct mimimi_behavior *mimimi_noop = &mimimi_noop_value;
struct mimimi_function
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_behavior *other;
};
static void mimimi_function_behave(void *data)
{
struct mimimi_function *function = data;
(*function->other->behave)(function->other->data);
}
static void mimimi_function_finish(void *data)
{
struct mimimi_function *function = data;
(*function->other->finish)(function->other->data);
(*function->allocator->deallocate)(function->other);
(*function->allocator->deallocate)(function->behavior);
(*function->allocator->deallocate)(function);
}
struct mimimi_behavior *mimimi_function(void *data, void (*behave)(void *data), struct mimimi_allocator *allocator)
{
struct mimimi_function *function = (*allocator->allocate)(sizeof *function);
function->allocator = allocator;
function->other = (*allocator->allocate)(sizeof *function->other);
function->other->behave = behave;
function->other->finish = &mimimi_ignore;
function->other->data = data;
function->behavior = (*allocator->allocate)(sizeof *function->behavior);
function->behavior->behave = &mimimi_function_behave;
function->behavior->finish = &mimimi_function_finish;
function->behavior->data = function;
return function->behavior;
}
struct mimimi_behavior *mimimi_finalizer(void *data, void (*finish)(void *data), struct mimimi_allocator *allocator)
{
struct mimimi_function *function = (*allocator->allocate)(sizeof *function);
function->allocator = allocator;
function->other = (*allocator->allocate)(sizeof *function->other);
function->other->behave = &mimimi_ignore;
function->other->finish = finish;
function->other->data = data;
function->behavior = (*allocator->allocate)(sizeof *function->behavior);
function->behavior->behave = &mimimi_function_behave;
function->behavior->finish = &mimimi_function_finish;
function->behavior->data = function;
return function->behavior;
}
struct mimimi_behavior *mimimi_allocator_behavior(void **data, unsigned int size, struct mimimi_allocator *allocator)
{
*data = (*allocator->allocate)(size);
return mimimi_finalizer(*data, allocator->deallocate, allocator);
}
void *mimimi_compound_allocate(struct mimimi_behavior *compound, unsigned int size, struct mimimi_allocator *allocator)
{
void *data;
mimimi_compound(compound, mimimi_allocator_behavior(&data, size, allocator));
return data;
}