char *test_tst_search_exact() { // tst returns the last one inserted void *res = tst_search(node, bdata(test1), blength(test1)); mu_assert(res == valueA, "Got the wrong value back, should get A not B."); // tst does not find if not exact res = tst_search(node, "TESTNO", strlen("TESTNO")); mu_assert(res == NULL, "Should not find anything."); return NULL; }
/** * call-seq: * uc.resolve("/someuri") -> "/someuri", "", handler * uc.resolve("/someuri/pathinfo") -> "/someuri", "/pathinfo", handler * uc.resolve("/notfound/orhere") -> nil, nil, nil * uc.resolve("/") -> "/", "/", handler # if uc.register("/", handler) * uc.resolve("/path/from/root") -> "/", "/path/from/root", handler # if uc.register("/", handler) * * Attempts to resolve either the whole URI or at the longest prefix, returning * the prefix (as script_info), path (as path_info), and registered handler * (usually an HttpHandler). If it doesn't find a handler registered at the longest * match then it returns nil,nil,nil. * * Because the resolver uses a trie you are able to register a handler at *any* character * in the URI and it will be handled as long as it's the longest prefix. So, if you * registered handler #1 at "/something/lik", and #2 at "/something/like/that", then a * a search for "/something/like" would give you #1. A search for "/something/like/that/too" * would give you #2. * * This is very powerful since it means you can also attach handlers to parts of the ; * (semi-colon) separated path params, any part of the path, use off chars, anything really. * It also means that it's very efficient to do this only taking as long as the URI has * characters. * * A slight modification to the CGI 1.2 standard is given for handlers registered to "/". * CGI expects all CGI scripts to be at some script path, so it doesn't really say anything * about a script that handles the root. To make this work, the resolver will detect that * the requested handler is at "/", and return that for script_name, and then simply return * the full URI back as path_info. * * It expects strings with no embedded '\0' characters. Don't try other string-like stuff yet. */ VALUE URIClassifier_resolve(VALUE self, VALUE uri) { void *handler = NULL; int pref_len = 0; struct tst *tst = NULL; VALUE result; unsigned char *uri_str = NULL; DATA_GET(self, struct tst, tst); uri_str = (unsigned char *)StringValueCStr(uri); handler = tst_search(uri_str, tst, &pref_len); result = rb_ary_new(); if(handler) { rb_ary_push(result, rb_str_substr (uri, 0, pref_len)); if(pref_len == 1 && uri_str[0] == '/') { rb_ary_push(result, uri); } else { rb_ary_push(result, rb_str_substr(uri, pref_len, RSTRING(uri)->len)); } rb_ary_push(result, (VALUE)handler); } else { rb_ary_push(result, Qnil); rb_ary_push(result, Qnil); rb_ary_push(result, Qnil); } return result; }
void import(Module *state, array_t *params) { size_t length = 0; CORD input = NULL; Module *target = NULL; char in_file[MAX_LIB_NAME]; ARITY(import, 2); REQUIRES(import, 0, STR); REQUIRES(import, 1, STR); if(tst_search(state->imports, ARG(1)->data)) { // already loaded so just skip it return; } if(Token_copy(ARG(0), in_file, MAX_LIB_NAME, TK_STR) == -1) { die(state, "requested module name %s is too long, must be less than %d.", in_file, MAX_LIB_NAME); } input = mmap_file(in_file, &length); assert(input && "Failed to open the file you requested."); // compile the other file using the code size specified by the parent target = Module_create(in_file, state->max_code_size); // have to add it here to prevent recursive loads from going in a loop state->imports = tst_insert(state->imports, ARG(1)->start, ARG(1)->len, target); assert(state->imports && "Error importing into the parent namespace."); if(!Module_compile(target, input, length)) { die(target, "error parsing imported module %s.", in_file); } }
int Handler_load(tst_t *settings, tst_t *params) { const char *send_spec = AST_str(settings, params, "send_spec", VAL_QSTRING); char *sql = NULL; sql = sqlite3_mprintf(bdata(&HANDLER_SQL), send_spec, AST_str(settings, params, "send_ident", VAL_QSTRING), AST_str(settings, params, "recv_spec", VAL_QSTRING), AST_str(settings, params, "recv_ident", VAL_QSTRING)); int rc = DB_exec(sql, NULL, NULL); check(rc == 0, "Failed to load Handler: %s", send_spec); if(tst_search(params, bdata(&RAW_PAYLOAD), blength(&RAW_PAYLOAD))) { const char *raw_payload = AST_str(settings, params, "raw_payload", VAL_NUMBER); if(raw_payload && raw_payload[0] == '1') { DB_exec(bdata(&HANDLER_RAW_SQL), NULL, NULL); } } sqlite3_free(sql); return DB_lastid(); error: if(sql) sqlite3_free(sql); return -1; }
int MIME_add_type(const char *ext, const char *type) { if(!MAX_EXT_LEN) { MAX_EXT_LEN = Setting_get_int("limits.mime_ext_len", 128); log_info("MAX limits.mime_ext_len=%d", MAX_EXT_LEN); } bstring ext_rev = bfromcstr(ext); bReverse(ext_rev); bstring type_str = bfromcstr(type); check(blength(ext_rev) > 0, "No zero length MIME extensions allowed: %s:%s", ext, type); check(blength(type_str) > 0, "No zero length MIME types allowed: %s:%s", ext, type); check(ext[0] == '.', "Extensions must start with a . '%s:%s'", ext, type); check(blength(ext_rev) < MAX_EXT_LEN, "MIME extension %s:%s is longer than %d MAX (it's %d)", ext, type, MAX_EXT_LEN, blength(ext_rev)); check(!tst_search(MIME_MAP, bdata(ext_rev), blength(ext_rev)), "MIME extension %s already exists, can't add %s:%s", ext, ext, type); MIME_MAP = tst_insert(MIME_MAP, bdata(ext_rev), blength(ext_rev), type_str); bdestroy(ext_rev); return 0; error: bdestroy(ext_rev); bdestroy(type_str); return -1; }
int AST_walk_hash(tst_t *settings, Value *data, ast_hash_walk_cb cb) { struct ASTScanData scan = {.settings = settings, .cb = cb, .error = 0}; tst_traverse(data->as.hash, ast_hash_traverse_cb, &scan); return scan.error; } Value *AST_get(tst_t *settings, tst_t *fr, bstring name, ValueType type) { Pair *pair = tst_search(fr, bdata(name), blength(name)); check_debug(pair, "Couldn't find variable %s of type %s", bdata(name), Value_type_name(type)); Value *val = Pair_value(pair); if(Value_is(val, REF)) { val = Value_resolve(settings, val); check(val, "Couldn't find variable %s of type %s", bdata(name), Value_type_name(type)); } check(val->type == type, "Invalid type for %s, should be %s not %s", bdata(name), Value_type_name(type), Value_type_name(val->type)); return val; error: return NULL; }
void Action_dependency_assign(void *value, void *data) { Action *action = (Action *)value; Action *target = NULL; tst_t *targets = (tst_t *)data; int i = 0; if(!action->depends) return; debug("Processed %s action depending on: %s", bdata(action->name), bdata(action->depends)); if(action->depends) { struct bstrList *dep_list = bsplit(action->depends, ' '); for(i = 0; i < dep_list->qty; i++) { bstring dep = dep_list->entry[i]; target = (Action *)tst_search(targets, bdata(dep), blength(dep)); if(target) { Action_depends(action, target); } else { log_err("Could not find dependency %s has on %s.", bdata(action->name), bdata(dep)); } } bstrListDestroy(dep_list); } }
char *co_cmd_description(char *name, int mask) { co_cmd_t *cmd = tst_search(commands, name, strlen(name)); CHECK((cmd != NULL), "No such command!"); CHECK((cmd->mask & mask) == mask, "Permissions denied for command %s from this access type.", name); return cmd->description; error: return 0; }
int Setting_get_int(const char *key, int def) { bstring value = tst_search(SETTINGS_MAP, key, strlen(key)); if(value) { return atoi((const char *)value->data); } else { return def; } }
char *co_cmd_exec(char *name, char *argv[], int argc, int mask) { DEBUG("Command name: %s", name); co_cmd_t *cmd = tst_search(commands, name, strlen(name)); CHECK((cmd != NULL), "No such command!"); CHECK((cmd->mask & mask) == mask, "Permissions denied for command %s from this access type.", name); DEBUG("Executing command %s", name); return cmd->exec((void *)cmd, argv, argc); error: return NULL; }
Value *Value_resolve(tst_t *settings, Value *val) { if(Value_is(val, REF)) { Pair *pair = tst_search(settings, bdata(val->as.ref->data), blength(val->as.ref->data)); check(pair != NULL, "Couldn't find variable named: %s", bdata(val->as.ref->data)); return Pair_value(pair); } else { return val; } error: return NULL; }
int AST_walk(tst_t *settings, ast_walk_cb cb) { Pair *n = tst_search(settings, bdata(&DEFAULT_ROOT), blength(&DEFAULT_ROOT)); check(n, "You didn't set a %s variable to say what servers you want.", bdata(&DEFAULT_ROOT)); Value *val = Pair_value(n); check(val->type == VAL_LIST, "servers variable should be a list of server configs to load."); return AST_walk_list(settings, val->as.list, cb); error: return -1; }
int Server_load(tst_t *settings, Value *val) { CONFIRM_TYPE("Server"); Class *cls = val->as.cls; int rc = 0; char *sql = NULL; struct tagbstring HOSTS_VAR = bsStatic("hosts"); const char *bind_addr = NULL; if(tst_search(cls->params, bdata(&BIND_ADDR), blength(&BIND_ADDR))) { bind_addr = AST_str(settings, cls->params, "bind_addr", VAL_QSTRING); } else { bind_addr = "0.0.0.0"; } sql = sqlite3_mprintf(bdata(&SERVER_SQL), AST_str(settings, cls->params, "uuid", VAL_QSTRING), AST_str(settings, cls->params, "access_log", VAL_QSTRING), AST_str(settings, cls->params, "error_log", VAL_QSTRING), AST_str(settings, cls->params, "pid_file", VAL_QSTRING), AST_str(settings, cls->params, "chroot", VAL_QSTRING), AST_str(settings, cls->params, "default_host", VAL_QSTRING), AST_str(settings, cls->params, "name", VAL_QSTRING), bind_addr, AST_str(settings, cls->params, "port", VAL_NUMBER)); rc = DB_exec(sql, NULL, NULL); check(rc == 0, "Failed to exec SQL: %s", sql); cls->id = SERVER_ID = DB_lastid(); Value *hosts = AST_get(settings, cls->params, &HOSTS_VAR, VAL_LIST); check(hosts != NULL, "Could not find Server.hosts setting in host %s:%s", AST_str(settings, cls->params, "uuid", VAL_QSTRING), AST_str(settings, cls->params, "name", VAL_QSTRING)); AST_walk_list(settings, hosts->as.list, Host_load); sqlite3_free(sql); return 0; error: if(sql) sqlite3_free(sql); return -1; }
void* dict_get(dict* d, char *key) { #ifdef TSTC dict_entry *e = 0; int r = tstc_find(d->dict, key, (void*)&e); if (r) { return e->v; } return e; #elif defined (HASHMAP) return hash_map_find(d->dict, key, strlen(key)); #else return (void*) tst_search(d->dict, key); #endif }
void run_function(Module *state, const char *named) { Function *func = NULL; func = tst_search(state->functions, named, strlen(named)); if(!func) { printf("Undefined function: '%s'\n", named); } else { if(list_isempty(func->params)) { printf("Sorry, this function takes parameters so it's not supported to call it yet.\n"); return; } switch(func->type) { case OpType_v: printf(">>\n"); func->fp.vptr(); break; case OpType_c: printf(">> %c\n", func->fp.cptr()); break; case OpType_uc: printf(">> %c\n", func->fp.ucptr()); break; case OpType_s: printf(">> %i\n", func->fp.sptr()); break; case OpType_us: printf(">> %i\n", func->fp.usptr()); break; case OpType_i: printf(">> %d\n", func->fp.iptr()); break; case OpType_ui: printf(">> %u\n", func->fp.uiptr()); break; case OpType_l: printf(">> %ld\n", func->fp.lptr()); break; case OpType_ul: printf(">> %lu\n", func->fp.ulptr()); break; case OpType_p: printf(">> %p\n", func->fp.pptr()); break; case OpType_f: printf(">> %f\n", func->fp.fptr()); break; case OpType_d: printf(">> %f\n", func->fp.dptr()); break; } } }
int Setting_add(const char *key, const char *value) { bstring key_str = bfromcstr(key); bstring value_str = bfromcstr(value); check(!tst_search(SETTINGS_MAP, bdata(key_str), blength(value_str)), "Setting key %s already exists, can't add %s:%s", key, key, value); SETTINGS_MAP = tst_insert(SETTINGS_MAP, bdata(key_str), blength(key_str), value_str); bdestroy(key_str); return 0; error: bdestroy(key_str); bdestroy(value_str); return -1; }
/** Finds a FUNCTION that is in a library which has been loaded. */ void *Library_search(Module *state, Token *module, Token *name) { Library *lib = tst_search(state->libraries, module->start, module->len); if(lib) { // found it try to find the method char fname[MAX_LIB_NAME]; if(Token_copy(name, fname, MAX_LIB_NAME, TK_IDENT) == -1) { die(state, "Library file name %.*s is too long.", name->len, name->start); return NULL; } void *ptr = dlsym(lib->handle, fname); if(ptr) { return ptr; } else { die(state, "module %.*s, error loading library '%.*s': %s.", module->len, module->start, name->len, name->start, dlerror()); return NULL; } } else { // not loaded yet, error return NULL; } }
bstring Setting_get_str(const char *key, bstring def) { bstring value = tst_search(SETTINGS_MAP, key, strlen(key)); return value == NULL ? def : value; }