mirror of
https://github.com/libretro/RetroArch.git
synced 2024-12-04 06:11:17 +00:00
899c21257c
rename them - cleanup strcmp usage in video layout and other code cleanups
335 lines
6.9 KiB
C
335 lines
6.9 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#include <compat/strl.h>
|
|
#include <string/stdstring.h>
|
|
|
|
#include "scope.h"
|
|
|
|
union number
|
|
{
|
|
int val_int;
|
|
float val_dec;
|
|
};
|
|
|
|
typedef struct generator
|
|
{
|
|
bool is_decimal;
|
|
union number value;
|
|
union number increment;
|
|
int shift;
|
|
} generator_t;
|
|
|
|
struct param
|
|
{
|
|
char *name;
|
|
char *value;
|
|
generator_t *generator;
|
|
param_t *prev;
|
|
int level;
|
|
};
|
|
|
|
static void param_deinit(param_t *param)
|
|
{
|
|
free(param->generator);
|
|
free(param->value);
|
|
free(param->name);
|
|
}
|
|
|
|
static param_t *param_find(scope_t *scope, const char *name, int level)
|
|
{
|
|
param_t *param = scope->param;
|
|
|
|
while (param && param->level >= level)
|
|
{
|
|
if (string_is_equal(param->name, name))
|
|
return param;
|
|
param = param->prev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void scope_init(scope_t *scope)
|
|
{
|
|
scope->level = 0;
|
|
|
|
scope->param = NULL;
|
|
scope->elements = NULL;
|
|
scope->elements_count = 0;
|
|
scope->groups = NULL;
|
|
scope->groups_count = 0;
|
|
}
|
|
|
|
void scope_deinit(scope_t *scope)
|
|
{
|
|
int i;
|
|
param_t *param;
|
|
param_t *prev;
|
|
|
|
for (i = 0; i < scope->elements_count; ++i)
|
|
element_deinit(&scope->elements[i]);
|
|
free(scope->elements);
|
|
|
|
for (i = 0; i < scope->groups_count; ++i)
|
|
view_deinit(&scope->groups[i]);
|
|
free(scope->groups);
|
|
|
|
for (param = scope->param; param; param = prev)
|
|
{
|
|
prev = param->prev;
|
|
param_deinit(param);
|
|
free(param);
|
|
}
|
|
}
|
|
|
|
void scope_push(scope_t *scope)
|
|
{
|
|
++scope->level;
|
|
}
|
|
|
|
void scope_pop(scope_t *scope)
|
|
{
|
|
param_t *param;
|
|
|
|
--scope->level;
|
|
|
|
while ((param = scope->param))
|
|
{
|
|
if (param->level <= scope->level)
|
|
break;
|
|
|
|
scope->param = param->prev;
|
|
param_deinit(param);
|
|
free(param);
|
|
}
|
|
}
|
|
|
|
void scope_repeat(scope_t *scope)
|
|
{
|
|
param_t *param;
|
|
|
|
for (
|
|
param = scope->param;
|
|
param && param->level >= scope->level;
|
|
param = param->prev)
|
|
{
|
|
generator_t *gen;
|
|
if ((gen = param->generator))
|
|
{
|
|
char tmp[SCOPE_BUFFER_SIZE];
|
|
tmp[0] = '\0';
|
|
|
|
if (gen->is_decimal)
|
|
{
|
|
gen->value.val_dec += gen->increment.val_dec;
|
|
if (gen->shift > 0)
|
|
gen->value.val_dec = (float)((int)gen->value.val_dec << gen->shift);
|
|
else if (gen->shift < 0)
|
|
gen->value.val_dec = (float)((int)gen->value.val_dec >> -gen->shift);
|
|
sprintf(tmp, "%f", gen->value.val_dec);
|
|
}
|
|
else
|
|
{
|
|
gen->value.val_int += gen->increment.val_int;
|
|
if(gen->shift > 0)
|
|
gen->value.val_int <<= gen->shift;
|
|
else if (gen->shift < 0)
|
|
gen->value.val_int >>= -gen->shift;
|
|
sprintf(tmp, "%d", gen->value.val_int);
|
|
}
|
|
|
|
string_set(¶m->value, tmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void scope_param(scope_t *scope, const char *name, const char *value)
|
|
{
|
|
param_t *param;
|
|
char *eval_name = string_init(scope_eval(scope, name));
|
|
char *eval_value = string_init(scope_eval(scope, value));
|
|
|
|
if ((param = param_find(scope, eval_name, scope->level)))
|
|
{
|
|
free(param->value);
|
|
param->value = eval_value;
|
|
}
|
|
else
|
|
{
|
|
param = (param_t*)malloc(sizeof(param_t));
|
|
param->name = string_init(name);
|
|
param->value = eval_value;
|
|
param->generator = NULL;
|
|
param->level = scope->level;
|
|
param->prev = scope->param;
|
|
scope->param = param;
|
|
}
|
|
|
|
free(eval_name);
|
|
}
|
|
|
|
void scope_generator(scope_t *scope, const char *name,
|
|
const char *start, const char *increment,
|
|
const char *lshift, const char *rshift)
|
|
{
|
|
char *e_val;
|
|
char *e_inc;
|
|
generator_t *gen;
|
|
param_t *param;
|
|
char *e_name = string_init(scope_eval(scope, name));
|
|
|
|
if (param_find(scope, e_name, scope->level))
|
|
{
|
|
free(e_name);
|
|
return;
|
|
}
|
|
|
|
e_val = string_init(scope_eval(scope, start));
|
|
e_inc = string_init(scope_eval(scope, increment));
|
|
|
|
gen = (generator_t*)malloc(sizeof(generator_t));
|
|
|
|
param = (param_t*)malloc(sizeof(param_t));
|
|
param->name = string_init(e_name);
|
|
param->value = string_init(e_val);
|
|
param->generator = gen;
|
|
param->level = scope->level;
|
|
param->prev = scope->param;
|
|
scope->param = param;
|
|
|
|
gen->is_decimal = is_decimal(e_val) | is_decimal(e_inc);
|
|
|
|
if (gen->is_decimal)
|
|
{
|
|
gen->value.val_dec = get_dec(e_val);
|
|
gen->increment.val_dec = get_dec(e_inc);
|
|
}
|
|
else
|
|
{
|
|
gen->value.val_int = get_int(e_val);
|
|
gen->increment.val_int = get_int(e_inc);
|
|
}
|
|
|
|
gen->shift = 0;
|
|
|
|
if (lshift)
|
|
gen->shift += get_int(scope_eval(scope, lshift));
|
|
|
|
if (rshift)
|
|
gen->shift -= get_int(scope_eval(scope, rshift));
|
|
|
|
free(e_inc);
|
|
free(e_val);
|
|
free(e_name);
|
|
}
|
|
|
|
const char *scope_eval(scope_t *scope, const char *src)
|
|
{
|
|
const char* next;
|
|
bool in_var;
|
|
char tmp[SCOPE_BUFFER_SIZE];
|
|
|
|
if (!src)
|
|
return NULL;
|
|
|
|
scope->eval[0] = '\0';
|
|
next = src;
|
|
|
|
while (next[0] != '\0')
|
|
{
|
|
const char *cur = next;
|
|
|
|
if ((in_var = (next[0] == '~')))
|
|
++cur;
|
|
|
|
next = strchr(cur, '~');
|
|
|
|
if (next && next != cur)
|
|
{
|
|
size_t len = next - cur;
|
|
|
|
if (in_var)
|
|
{
|
|
param_t *param;
|
|
|
|
strncpy(tmp, cur, len);
|
|
tmp[len] = '\0';
|
|
|
|
if ((param = param_find(scope, tmp, 0)))
|
|
strlcat(scope->eval, param->value,
|
|
sizeof(scope->eval));
|
|
else
|
|
strlcat(scope->eval, tmp, sizeof(scope->eval));
|
|
|
|
++next;
|
|
}
|
|
else
|
|
strncat(scope->eval, cur, len);
|
|
}
|
|
else
|
|
{
|
|
if (in_var)
|
|
--cur;
|
|
strlcat(scope->eval, cur, sizeof(scope->eval));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return scope->eval;
|
|
}
|
|
|
|
element_t *scope_add_element(scope_t *scope)
|
|
{
|
|
element_t *elem;
|
|
|
|
vec_size((void**)&scope->elements,
|
|
sizeof(element_t), ++scope->elements_count);
|
|
|
|
elem = &scope->elements[scope->elements_count - 1];
|
|
element_init(elem, NULL, 0);
|
|
|
|
return elem;
|
|
}
|
|
|
|
element_t *scope_find_element(scope_t *scope, const char *name)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i = 0; i < scope->elements_count; ++i)
|
|
{
|
|
if (string_is_equal(name, scope->elements[i].name))
|
|
return &scope->elements[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
view_t *scope_add_group(scope_t *scope)
|
|
{
|
|
view_t *group;
|
|
|
|
vec_size((void**)&scope->groups, sizeof(view_t), ++scope->groups_count);
|
|
|
|
group = &scope->groups[scope->groups_count - 1];
|
|
view_init(group, NULL);
|
|
|
|
return group;
|
|
}
|
|
|
|
view_t *scope_find_group(scope_t *scope, const char *name)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i = 0; i < scope->groups_count; ++i)
|
|
{
|
|
if (string_is_equal(name, scope->groups[i].name))
|
|
return &scope->groups[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|