forked from github/server
find_function is one of our more frequently called functions, and it can probably do with a little more performance. Let's see if this helps.
This commit is contained in:
parent
2d2f566634
commit
77110158f9
|
@ -12,8 +12,10 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
#include "log.h"
|
|
||||||
#include "bsdstring.h"
|
#include "bsdstring.h"
|
||||||
|
#include "critbit.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/* libc includes */
|
/* libc includes */
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -146,43 +148,33 @@ static variable *find_variable(const char *symbol)
|
||||||
** constant values
|
** constant values
|
||||||
**/
|
**/
|
||||||
|
|
||||||
typedef struct function {
|
static struct critbit_tree functions = { 0 };
|
||||||
struct function *next;
|
|
||||||
const char *symbol;
|
|
||||||
evalfun parse;
|
|
||||||
} function;
|
|
||||||
|
|
||||||
static function *functions;
|
|
||||||
|
|
||||||
static void free_functions(void)
|
static void free_functions(void)
|
||||||
{
|
{
|
||||||
while (functions) {
|
cb_clear(&functions);
|
||||||
function *fun = functions;
|
functions.root = 0;
|
||||||
functions = fun->next;
|
|
||||||
free(fun);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_function(const char *symbol, evalfun parse)
|
void add_function(const char *symbol, evalfun parse)
|
||||||
{
|
{
|
||||||
function *fun = (function *) malloc(sizeof(function));
|
char buffer[64];
|
||||||
|
size_t len = strlen(symbol);
|
||||||
fun->parse = parse;
|
|
||||||
fun->symbol = symbol;
|
assert(len+1+sizeof(parse)<=sizeof(buffer));
|
||||||
|
cb_new_kv(symbol, &parse, sizeof(parse), buffer);
|
||||||
fun->next = functions;
|
cb_insert(&functions, buffer, len+1+sizeof(parse));
|
||||||
functions = fun;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function *find_function(const char *symbol)
|
static evalfun find_function(const char *symbol)
|
||||||
{
|
{
|
||||||
function *fun = functions;
|
void * matches;
|
||||||
while (fun) {
|
if (cb_find_prefix(&functions, symbol, strlen(symbol)+1, &matches, 1, 0)) {
|
||||||
if (!strcmp(fun->symbol, symbol))
|
evalfun result;
|
||||||
break;
|
cb_get_kv(matches, &result, sizeof(result));
|
||||||
fun = fun->next;
|
return result;
|
||||||
}
|
}
|
||||||
return fun;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *parse(opstack **, const char *in, const void *);
|
static const char *parse(opstack **, const char *in, const void *);
|
||||||
|
@ -208,7 +200,8 @@ static const char *parse_symbol(opstack ** stack, const char *in,
|
||||||
/* symbol will now contain the symbol name */
|
/* symbol will now contain the symbol name */
|
||||||
if (*in == '(') {
|
if (*in == '(') {
|
||||||
/* it's a function we need to parse, start by reading the parameters */
|
/* it's a function we need to parse, start by reading the parameters */
|
||||||
function *foo;
|
evalfun foo;
|
||||||
|
|
||||||
while (*in != ')') {
|
while (*in != ')') {
|
||||||
in = parse(stack, ++in, userdata); /* will push the result on the stack */
|
in = parse(stack, ++in, userdata); /* will push the result on the stack */
|
||||||
if (in == NULL)
|
if (in == NULL)
|
||||||
|
@ -220,7 +213,7 @@ static const char *parse_symbol(opstack ** stack, const char *in,
|
||||||
log_error(("parser does not know about \"%s\" function.\n", symbol));
|
log_error(("parser does not know about \"%s\" function.\n", symbol));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
foo->parse(stack, userdata); /* will pop parameters from stack (reverse order!) and push the result */
|
foo(stack, userdata); /* will pop parameters from stack (reverse order!) and push the result */
|
||||||
} else {
|
} else {
|
||||||
variable *var = find_variable(symbol);
|
variable *var = find_variable(symbol);
|
||||||
if (braces && *in == '}') {
|
if (braces && *in == '}') {
|
||||||
|
|
Loading…
Reference in New Issue