int isalpharune(Rune c) { Rune *p; p = rbsearch(c, __isalphar, nelem(__isalphar)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; p = rbsearch(c, __isalphas, nelem(__isalphas), 1); if(p && c == p[0]) return 1; return 0; }
int main(int argc, char** argv) { ITEM *ptr, *result; struct rbtree *rb; ITEM c; FILE *f; char *dbName = "f_inc.0.u.test"; c.w = atof(argv[1]); c.value = -1; if ((rb=rbinit(compare, NULL))==NULL) { fprintf(stderr, "insufficient memory\n"); exit(1); } f = fopen(dbName, "r"); ptr = (ITEM *)xmalloc(sizeof(ITEM)); while (fscanf(f, "%lf", &ptr->w) != EOF) { fscanf(f, "%lf", &ptr->value); rbsearch(ptr, rb); ptr = (ITEM *)xmalloc(sizeof(ITEM)); } result = (ITEM *)rbsearch(&c, rb); fprintf(stdout, "%.8lf\t%.8lf\n", result->w, result->value); /* for (i = 50000; i > 0; i--) { ptr = (ITEM *)xmalloc(sizeof(ITEM)); ptr->w = i; ptr->value = (double)i/7; val = rbsearch((void *)ptr, rb); if(val == NULL) { fprintf(stderr, "insufficient memory\n"); exit(1); } } rbwalk(rb, walkact, "No"); printf("Minimum branch length: %d\n", minleaf); printf("Maximum branch length: %d\n", maxleaf); */ rbdestroy(rb); return 0; }
int istitlerune(Rune c) { Rune *p; p = rbsearch(c, __istitler, nelem(__istitler)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; p = rbsearch(c, __istitlep, nelem(__istitlep)/2, 2); if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1)) return 1; p = rbsearch(c, __istitles, nelem(__istitles), 1); if(p && c == p[0]) return 1; return 0; }
void stasis_aggregate_min_add(stasis_aggregate_min_t * min, lsn_t * a) { if(min->tree) { const void * ret = rbsearch(a, min->tree); assert(ret == a); } else { if(min->memo) { if(*min->memo > *a) { min->memo = a; } } lsn_t * p = pthread_getspecific(min->key); if(!p) { p = malloc(sizeof(lsn_t)); *p = -1; pthread_setspecific(min->key, p); } if(*p != -1 && min->vals[*p] == 0) { min->vals[*p] = a; return; } for(int i = 0; i < min->num_entries; i++) { if(!min->vals[i]) { min->vals[i] = a; *p = i; return; } } min->num_entries++; min->vals = realloc(min->vals, min->num_entries * sizeof(lsn_t**)); *p = min->num_entries-1; min->vals[*p] = a; return; } }
int main() { int i, *ptr; const void *val; struct rbtree *rb; srand(getpid()); if ((rb=rbinit(compare, NULL))==NULL) { fprintf(stderr, "insufficient memory\n"); exit(1); } for (i = 0; i < 12; i++) { ptr = (int *)xmalloc(sizeof(int)); *ptr = rand()&0xff; val = rbsearch((void *)ptr, rb); if(val == NULL) { fprintf(stderr, "insufficient memory\n"); exit(1); } } for(val=rblookup(RB_LUFIRST, NULL, rb); val!=NULL; val=rblookup(RB_LUNEXT, val, rb)) { printf("%6d\n", *(int *)val); } rbdestroy(rb); return 0; }
Rune totitlerune(Rune c) { Rune *p; p = rbsearch(c, __totitler, nelem(__totitler)/3, 3); if(p && c >= p[0] && c <= p[1]) return c + p[2] - 1048576; p = rbsearch(c, __totitlep, nelem(__totitlep)/3, 3); if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1)) return c + p[2] - 1048576; p = rbsearch(c, __totitles, nelem(__totitles)/2, 2); if(p && c == p[0]) return c + p[1] - 1048576; return c; }
int islowerrune(Rune c) { Rune *p; p = rbsearch(c, __islowerr, nelem(__islowerr)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; p = rbsearch(c, __islowerp, nelem(__islowerp)/2, 2); if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1)) return 1; p = rbsearch(c, __islowers, nelem(__islowers), 1); if(p && c == p[0]) return 1; return 0; }
/* ============ Cmd_AddCommand ============ */ void EXPORT Cmd_AddCommand (const char *cmd_name, xcommand_t function) { void **data; cmd_function_t *cmd; if (!cmd_name) Com_Error (ERR_FATAL, "Cmd_AddCommand: NULL command name"); // fail if the command is a variable name if (Cvar_VariableString(cmd_name)[0]) { Com_Printf ("Cmd_AddCommand: %s already defined as a var\n", LOG_GENERAL, cmd_name); return; } // fail if the command already exists if (rbfind (cmd_name, cmdtree)) { //r1: delete command and replace. unclean ref shutdown for example //will leave dangling pointers. //Com_Printf ("Cmd_AddCommand: %s already defined\n", LOG_GENERAL, cmd_name); //return; Cmd_RemoveCommand (cmd_name); } cmd = Z_TagMalloc (sizeof(cmd_function_t), TAGMALLOC_CMD); cmd->name = cmd_name; cmd->function = function; cmd->next = cmd_functions; cmd_functions = cmd; data = rbsearch (cmd->name, cmdtree); *data = cmd; }
static void upnp_entry_add_child (struct ushare_t *ut, struct upnp_entry_t *entry, struct upnp_entry_t *child) { struct upnp_entry_lookup_t *entry_lookup_ptr = NULL; struct upnp_entry_t **childs; int n; if (!entry || !child) return; for (childs = entry->childs; *childs; childs++) if (*childs == child) return; n = get_list_length ((void *) entry->childs) + 1; entry->childs = (struct upnp_entry_t **) realloc (entry->childs, (n + 1) * sizeof (*(entry->childs))); entry->childs[n] = NULL; entry->childs[n - 1] = child; entry->child_count++; entry_lookup_ptr = (struct upnp_entry_lookup_t *) malloc (sizeof (struct upnp_entry_lookup_t)); entry_lookup_ptr->id = child->id; entry_lookup_ptr->entry_ptr = child; if (rbsearch ((void *) entry_lookup_ptr, ut->rb) == NULL) log_info (_("Failed to add the RB lookup tree\n")); }
int isdigitrune(Rune c) { Rune *p; p = rbsearch(c, __isdigitr, nelem(__isdigitr)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; return 0; }
int isideographicrune(Rune c) { Rune *p; p = rbsearch(c, __isideographicr, nelem(__isideographicr)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; return 0; }
/** * add a mapping from iTunes song index to the mt-daapd song * index. This is so we can add resolve mt-daapd song indexes * when it comes time to build the iTunes playlist * * @param itunes_index the index from the itunes xml file * @param mtd_index the index from db_fetch_path */ void scan_xml_add_lookup(int itunes_index, int mtd_index) { SCAN_XML_RB *pnew; const void *val; pnew=(SCAN_XML_RB*)malloc(sizeof(SCAN_XML_RB)); if(!pnew) DPRINTF(E_FATAL,L_SCAN,"malloc error in scan_xml_add_lookup\n"); pnew->itunes_index = itunes_index; pnew->mtd_index = mtd_index; val = rbsearch((const void*)pnew,scan_xml_db); if(!val) { /* couldn't alloc the rb tree structure -- if we don't * die now, we are going to soon enough*/ DPRINTF(E_FATAL,L_SCAN,"redblack tree insert error\n"); } }
int main() { int i, *ptr; const void *val; struct rbtree *rb; RBLIST *rblist; if ((rb=rbinit(compare, NULL))==NULL) { fprintf(stderr, "insufficient memory from rbinit()\n"); exit(1); } for (i = 200; i > 0; i--) { ptr = (int *)xmalloc(sizeof(int)); *ptr = i; val = rbsearch((void *)ptr, rb); if(val == NULL) { fprintf(stderr, "insufficient memory from rbsearch()\n"); exit(1); } } if ((rblist=rbopenlist(rb))==NULL) { fprintf(stderr, "insufficient memory from rbopenlist()\n"); exit(1); } while((val=rbreadlist(rblist))) { printf("%6d\n", *(int *)val); } rbcloselist(rblist); rbdestroy(rb); return 0; }
int int_dict_set( int_dict_t *dict, intkey_t key, void *value) { int_dict_node_t *node; int retval = -1; assert(dict); assert(dict->tree); WRITE_LOCK(&dict->mutex); if (dict->tnode == NULL) { dict->tnode = (int_dict_node_t*)malloc(offsetof(int_dict_node_t, value) + dict->value_size); if (dict->tnode == NULL) { goto end; } } dict->tnode->key = key; node = (int_dict_node_t *)rbsearch(dict->tnode, dict->tree); if (node == NULL) { goto end; } memcpy(node->value, value, dict->value_size); if (node == dict->tnode) { dict->count++; dict->tnode = NULL; } retval = 0; end: RW_MUTEX_UNLOCK(&dict->mutex); return retval; }
static void FS_AddToCache (const char *path, uint32 filelen, uint32 fileseek, const char *filename, pack_t *pak) { void **newitem; fscache_t *cache; if (!q2_initialized) return; cache = Z_TagMalloc (sizeof(fscache_t), TAGMALLOC_FSCACHE); cache->filelen = filelen; cache->fileseek = fileseek; cache->pak = pak; if (path) strncpy (cache->filepath, path, sizeof(cache->filepath)-1); else cache->filepath[0] = 0; strncpy (cache->filename, filename, sizeof(cache->filename)-1); newitem = rbsearch (cache->filename, rb); *newitem = cache; }
static void FS_AddToCache (char *path, uint32 filelen, uint32 fileseek, char *filename, uint32 hash) { void **newitem; fscache_t *cache; magic_t *magic; cache = Z_TagMalloc (sizeof(fscache_t), TAGMALLOC_FSCACHE); cache->filelen = filelen; cache->fileseek = fileseek; if (path) strncpy (cache->filepath, path, sizeof(cache->filepath)-1); else cache->filepath[0] = 0; strncpy (cache->filename, filename, sizeof(cache->filename)-1); newitem = rbfind ((void *)hash, rb); if (newitem) { magic = *(magic_t **)newitem; while (magic->next) magic = magic->next; magic->next = Z_TagMalloc (sizeof(magic_t), TAGMALLOC_FSCACHE); magic = magic->next; magic->entry = cache; magic->next = NULL; } else { newitem = rbsearch ((void *)hash, rb); magic = Z_TagMalloc (sizeof(magic_t), TAGMALLOC_FSCACHE); magic->entry = cache; magic->next = NULL; *newitem = magic; } }
int c_hash_insert(lv_t *hash, lv_t *key, lv_t *value) { hash_node_t *pnew; hash_node_t *result; assert(hash->type == l_hash); assert(key->type == l_str || key->type == l_sym); pnew=safe_malloc(sizeof(hash_node_t)); pnew->key = s_hash_item(key); pnew->key_item = key; pnew->value = value; result = (hash_node_t *)rbsearch((void*)pnew, L_HASH(hash)); assert(result); result->value = value; result->key_item = key; return(result != NULL); }
static cvar_t *Cvar_Add (const char *var_name, const char *var_value, int flags) { cvar_t *var; const void **data; var = (cvar_t *) Z_TagMalloc (sizeof(cvar_t), TAGMALLOC_CVAR); var->name = CopyString (var_name, TAGMALLOC_CVAR); var->string = CopyString (var_value, TAGMALLOC_CVAR); var->modified = true; var->changed = NULL; var->latched_string = NULL; var->value = (float)atof (var->string); var->intvalue = (int)var->value; var->flags = flags; var->help = NULL; if (var->flags & CVAR_USERINFO) userinfo_modified = true; //r1: fix 0 case if (!var->intvalue && FLOAT_NE_ZERO(var->value)) var->intvalue = 1; // link the variable in var->next = cvar_vars; cvar_vars = var; //r1: insert to btree data = (const void **) rbsearch (var->name, cvartree); *data = var; return var; }
static void GCC_INLINE freecell_solver_cache_stacks( freecell_solver_hard_thread_t * hard_thread, fcs_state_with_locations_t * new_state ) { int a; #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH) SFO_hash_value_t hash_value_int; #endif void * cached_stack; char * new_ptr; freecell_solver_instance_t * instance = hard_thread->instance; int stacks_num = instance->stacks_num; for(a=0 ; a<stacks_num ; a++) { /* * If the stack is not a copy - it is already cached so skip * to the next stack * */ if (! (new_state->stacks_copy_on_write_flags & (1 << a))) { continue; } /* new_state->s.stacks[a] = realloc(new_state->s.stacks[a], fcs_stack_len(new_state->s, a)+1); */ fcs_compact_alloc_typed_ptr_into_var(new_ptr, char, hard_thread->stacks_allocator, (fcs_stack_len(new_state->s, a)+1)); memcpy(new_ptr, new_state->s.stacks[a], (fcs_stack_len(new_state->s, a)+1)); new_state->s.stacks[a] = new_ptr; #if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH /* Calculate the hash value for the stack */ /* This hash function was ripped from the Perl source code. * (It is not derived work however). */ { const char * s_ptr = (char*)(new_state->s.stacks[a]); const char * s_end = s_ptr+fcs_stack_len(new_state->s, a)+1; hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int >> 5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } cached_stack = (void *)freecell_solver_hash_insert( instance->stacks_hash, new_state->s.stacks[a], freecell_solver_lookup2_hash_function( (ub1 *)new_state->s.stacks[a], (fcs_stack_len(new_state->s, a)+1), 24 ), hash_value_int, 1 ); #define replace_with_cached(condition_expr) \ if (cached_stack != NULL) \ { \ fcs_compact_alloc_release(hard_thread->stacks_allocator); \ new_state->s.stacks[a] = cached_stack; \ } replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) || (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) cached_stack = #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) avl_insert( #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) rb_insert( #endif instance->stacks_tree, new_state->s.stacks[a] ); #if 0 ) /* In order to settle gvim and other editors that are keen on parenthesis matching */ #endif replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE) cached_stack = (void *)rbsearch( new_state->s.stacks[a], instance->stacks_tree ); replace_with_cached(cached_stack != new_state->s.stacks[a]); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE) cached_stack = g_tree_lookup( instance->stacks_tree, (gpointer)new_state->s.stacks[a] ); /* replace_with_cached contains an if statement */ replace_with_cached(cached_stack != NULL) else { g_tree_insert( instance->stacks_tree, (gpointer)new_state->s.stacks[a], (gpointer)new_state->s.stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH) cached_stack = g_hash_table_lookup( instance->stacks_hash, (gconstpointer)new_state->s.stacks[a] ); replace_with_cached(cached_stack != NULL) else { g_hash_table_insert( instance->stacks_hash, (gpointer)new_state->s.stacks[a], (gpointer)new_state->s.stacks[a] ); } #endif }
/* =============== Cmd_Alias_f Creates a new command that executes a command string (possibly ; seperated) =============== */ void Cmd_Alias_f (void) { cmdalias_t *a; char cmd[1024]; char *s; void **data; if (Cmd_Argc() == 1) { Com_Printf ("Current alias commands:\n", LOG_GENERAL); Cmd_Aliaslist_f (); return; } s = Cmd_Argv(1); if (strlen(s) >= MAX_ALIAS_NAME) { Com_Printf ("Alias name is too long\n", LOG_GENERAL); return; } // if the alias already exists, reuse it /*for (a = cmd_alias ; a ; a=a->next) { if (!strcmp(s, a->name)) { Z_Free (a->value); break; } }*/ data = rbfind (s, aliastree); if (data) a = *(cmdalias_t **)data; else a = NULL; if (!a) { a = Z_TagMalloc (sizeof(cmdalias_t), TAGMALLOC_ALIAS); a->next = cmd_alias; cmd_alias = a; strcpy (a->name, s); data = rbsearch (a->name, aliastree); *data = a; } else { //strcpy (a->name, s); //memleak fix, thanks Maniac- Z_Free (a->value); } // copy the rest of the command line /*cmd[0] = 0; // start out with a null string c = Cmd_Argc(); for (i=2 ; i< c ; i++) { strcat (cmd, Cmd_Argv(i)); if (i != (c - 1)) strcat (cmd, " "); }*/ Q_strncpy (cmd, Cmd_Args2(2), sizeof(cmd)-2); /*s = strchr (Cmd_Args(), ' '); if (s) s++; else s = Cmd_Args (); Q_strncpy (cmd, s, sizeof(cmd)-2);*/ strcat (cmd, "\n"); a->value = CopyString (cmd, TAGMALLOC_ALIAS); }
/* ================= FS_LoadPackFile Takes an explicit (not game tree related) path to a pak file. Loads the header and directory, adding the files at the beginning of the list so they override previous pack files. ================= */ static pack_t /*@null@*/ *FS_LoadPackFile (const char *packfile, const char *ext) { int i; void **newitem; pack_t *pack = NULL; packfile_t *info; if (!strcmp (ext, "pak")) { unsigned pakLen; int numpackfiles; FILE *packhandle; dpackheader_t header; packhandle = fopen(packfile, "rb"); if (!packhandle) return NULL; fseek (packhandle, 0, SEEK_END); pakLen = ftell (packhandle); rewind (packhandle); if (fread (&header, sizeof(header), 1, packhandle) != 1) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read pak header from %s", packfile); if (LittleLong(header.ident) != IDPAKHEADER) Com_Error (ERR_FATAL, "FS_LoadPackFile: %s is not a valid pak file.", packfile); #if YOU_HAVE_A_BROKEN_COMPUTER header.dirofs = LittleLong (header.dirofs); header.dirlen = LittleLong (header.dirlen); #endif if (header.dirlen % sizeof(packfile_t)) Com_Error (ERR_FATAL, "FS_LoadPackFile: Bad pak file %s (directory length %u is not a multiple of %d)", packfile, header.dirlen, (int)sizeof(packfile_t)); numpackfiles = header.dirlen / sizeof(packfile_t); if (numpackfiles > MAX_FILES_IN_PACK) //Com_Error (ERR_FATAL, "FS_LoadPackFile: packfile %s has %i files (max allowed %d)", packfile, numpackfiles, MAX_FILES_IN_PACK); Com_Printf ("WARNING: Pak file %s has %i files (max allowed %d) - may not be compatible with other clients\n", LOG_GENERAL, packfile, numpackfiles, MAX_FILES_IN_PACK); if (!numpackfiles) { fclose (packhandle); Com_Printf ("WARNING: Empty packfile %s\n", LOG_GENERAL|LOG_WARNING, packfile); return NULL; } //newfiles = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK); info = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK); if (fseek (packhandle, header.dirofs, SEEK_SET)) Com_Error (ERR_FATAL, "FS_LoadPackFile: fseek() to offset %u in %s failed. Pak file is possibly corrupt.", header.dirofs, packfile); if ((int)fread (info, 1, header.dirlen, packhandle) != header.dirlen) Com_Error (ERR_FATAL, "FS_LoadPackFile: Error reading packfile directory from %s (failed to read %u bytes at %u). Pak file is possibly corrupt.", packfile, header.dirofs, header.dirlen); pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK); pack->type = PAK_QUAKE; pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, numpackfiles); //entry = Z_TagMalloc (sizeof(packfile_t) * numpackfiles, TAGMALLOC_FSLOADPAK); for (i=0 ; i<numpackfiles ; i++) { fast_strlwr (info[i].name); #if YOU_HAVE_A_BROKEN_COMPUTER info[i].filepos = LittleLong(info[i].filepos); info[i].filelen = LittleLong(info[i].filelen); #endif if (info[i].filepos + info[i].filelen >= pakLen) Com_Error (ERR_FATAL, "FS_LoadPackFile: File '%.64s' in pak file %s has illegal offset %u past end of file %u. Pak file is possibly corrupt.", MakePrintable (info[i].name, 0), packfile, info[i].filepos, pakLen); newitem = rbsearch (info[i].name, pack->rb); *newitem = &info[i]; } Q_strncpy (pack->filename, packfile, sizeof(pack->filename)-1); pack->h.handle = packhandle; pack->numfiles = numpackfiles; Com_Printf ("Added packfile %s (%i files)\n", LOG_GENERAL, packfile, numpackfiles); } #ifndef NO_ZLIB else if (!strcmp (ext, "pkz")) { unzFile f; unz_global_info zipinfo; char zipFileName[56]; unz_file_info fileInfo; f = unzOpen (packfile); if (!f) return NULL; if (unzGetGlobalInfo (f, &zipinfo) != UNZ_OK) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read .zip info from '%s'", packfile); info = Z_TagMalloc (zipinfo.number_entry * sizeof(*info), TAGMALLOC_FSLOADPAK); pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK); pack->type = PAK_ZIP; pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, zipinfo.number_entry); if (unzGoToFirstFile (f) != UNZ_OK) Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't seek to first .zip file in '%s'", packfile); zipFileName[sizeof(zipFileName)-1] = 0; i = 0; do { if (unzGetCurrentFileInfo (f, &fileInfo, zipFileName, sizeof(zipFileName)-1, NULL, 0, NULL, 0) == UNZ_OK) { //directory, ignored if (fileInfo.external_fa & 16) continue; strcpy (info[i].name, zipFileName); info[i].filepos = unzGetOffset (f); info[i].filelen = fileInfo.uncompressed_size; newitem = rbsearch (info[i].name, pack->rb); *newitem = &info[i]; i++; } } while (unzGoToNextFile (f) == UNZ_OK); pack->h.zhandle = f; Com_Printf ("Added zpackfile %s (%i files)\n", LOG_GENERAL, packfile, i); } #endif else { Com_Error (ERR_FATAL, "FS_LoadPackFile: Unknown type %s", ext); } return pack; }
static void GCC_INLINE fc_solve_cache_stacks( fc_solve_hard_thread_t * hard_thread, fcs_state_t * new_state_key, fcs_state_extra_info_t * new_state_val ) { int a; #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) PWord_t * PValue; #endif void * cached_stack; char * new_ptr; fc_solve_instance_t * instance = hard_thread->instance; #ifndef HARD_CODED_NUM_STACKS int stacks_num = instance->stacks_num; #endif fcs_cards_column_t column; register int col_len; for(a=0 ; a < LOCAL_STACKS_NUM ; a++) { /* * If the stack is not a copy - it is already cached so skip * to the next stack * */ if (! (new_state_val->stacks_copy_on_write_flags & (1 << a))) { continue; } /* new_state_key->stacks[a] = realloc(new_state_key->stacks[a], fcs_stack_len(new_state_key, a)+1); */ column = fcs_state_get_col(*new_state_key, a); col_len = (fcs_col_len(column)+1); fcs_compact_alloc_typed_ptr_into_var(new_ptr, char, hard_thread->stacks_allocator, col_len); memcpy(new_ptr, column, col_len); new_state_key->stacks[a] = new_ptr; #if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE /* Calculate the hash value for the stack */ /* This hash function was ripped from the Perl source code. * (It is not derived work however). */ { const char * s_ptr = (char*)(new_state_key->stacks[a]); const char * s_end = s_ptr+fcs_stack_len(*new_state_key, a)+1; hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int >> 5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * dummy; int verdict; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_hash_insert( instance->stacks_hash, column, column, &cached_stack, &dummy, perl_hash_function( (ub1 *)new_state_key->stacks[a], col_len ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) || (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) #define LIBAVL_INSERT(x,y) avl_insert(x,y) #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE) #define LIBAVL_INSERT(x,y) rb_insert(x,y) #else #error unknown FCS_STACK_STORAGE #endif cached_stack = LIBAVL_INSERT( instance->stacks_tree, new_state_key->stacks[a] ); #undef LIBAVL_INSERT replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE) cached_stack = (void *)rbsearch( new_state_key->stacks[a], instance->stacks_tree ); replace_with_cached(cached_stack != new_state_key->stacks[a]); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE) cached_stack = g_tree_lookup( instance->stacks_tree, (gpointer)new_state_key->stacks[a] ); /* replace_with_cached contains an if statement */ replace_with_cached(cached_stack != NULL) else { g_tree_insert( instance->stacks_tree, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH) cached_stack = g_hash_table_lookup( instance->stacks_hash, (gconstpointer)new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL) else { g_hash_table_insert( instance->stacks_hash, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) JHSI( PValue, instance->stacks_judy_array, new_state_key->stacks[a], (fcs_stack_len(*new_state_key, a)+1) ); /* TODO : Handle out-of-memory. */ if (*PValue == 0) { /* A new stack */ *PValue = (PWord_t)new_state_key->stacks[a]; } else { cached_stack = (void *)(*PValue); replace_with_cached(1); } #else #error FCS_STACK_STORAGE is not set to a good value. #endif } }
GCC_INLINE int fc_solve_check_and_add_state( fc_solve_soft_thread_t * soft_thread, fcs_state_extra_info_t * new_state_val, fcs_state_extra_info_t * * existing_state_val ) { #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #endif #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) fcs_standalone_state_ptrs_t * pos_ptr; int found; #endif fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread; fc_solve_instance_t * instance = hard_thread->instance; fcs_state_t * new_state_key = new_state_val->key; int is_state_new; if (check_if_limits_exceeded()) { return FCS_STATE_BEGIN_SUSPEND_PROCESS; } fc_solve_cache_stacks(hard_thread, new_state_key, new_state_val); fc_solve_canonize_state(new_state_val, INSTANCE_FREECELLS_NUM, INSTANCE_STACKS_NUM ); /* The objective of this part of the code is: 1. To check if new_state_key / new_state_val is already in the prev_states collection. 2. If not, to add it and to set check to true. 3. If so, to set check to false. */ #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE { const char * s_ptr = (char*)new_state_key; const char * s_end = s_ptr+sizeof(*new_state_key); hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int>>5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * existing_key_void, * existing_val_void; is_state_new = (fc_solve_hash_insert( instance->hash, new_state_key, new_state_val, &existing_key_void, &existing_val_void, perl_hash_function( (ub1 *)new_state_key, sizeof(*new_state_key) ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ) == 0); if (! is_state_new) { *existing_state_val = existing_val_void; } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_INDIRECT) /* Try to see if the state is found in indirect_prev_states */ if ((pos_ptr = (fcs_standalone_state_ptrs_t *)bsearch(&new_state_key, instance->indirect_prev_states, instance->num_indirect_prev_states, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect)) == NULL) { /* It isn't in prev_states, but maybe it's in the sort margin */ pos_ptr = (fcs_standalone_state_ptrs_t *)fc_solve_bsearch( &new_state_key, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states_margin[0]), fc_solve_state_compare_indirect_with_context, NULL, &found); if (found) { is_state_new = 0; *existing_state_val = pos_ptr->val; } else { /* Insert the state into its corresponding place in the sort * margin */ memmove((void*)(pos_ptr+1), (void*)pos_ptr, sizeof(*pos_ptr) * (instance->num_prev_states_margin- (pos_ptr-instance->indirect_prev_states_margin) )); pos_ptr->key = new_state_key; pos_ptr->val = new_state_val; instance->num_prev_states_margin++; if (instance->num_prev_states_margin >= PREV_STATES_SORT_MARGIN) { /* The sort margin is full, let's combine it with the main array */ instance->indirect_prev_states = realloc( instance->indirect_prev_states, sizeof(instance->indirect_prev_states[0]) * (instance->num_indirect_prev_states + instance->num_prev_states_margin ) ); fc_solve_merge_large_and_small_sorted_arrays( instance->indirect_prev_states, instance->num_indirect_prev_states, instance->indirect_prev_states_margin, instance->num_prev_states_margin, sizeof(instance->indirect_prev_states[0]), fc_solve_state_compare_indirect_with_context, NULL ); instance->num_indirect_prev_states += instance->num_prev_states_margin; instance->num_prev_states_margin=0; } is_state_new = 1; } } else { *existing_state_val = pos_ptr->val; is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBREDBLACK_TREE) *existing_state_val = (fcs_state_extra_info_t *)rbsearch(new_state_val, instance->tree ); is_state_new = ((*existing_state_val) == new_state_val); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_AVL_TREE) || (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_REDBLACK_TREE) #if (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_AVL_TREE) #define fcs_libavl_states_tree_insert(a,b) avl_insert((a),(b)) #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_LIBAVL_REDBLACK_TREE) #define fcs_libavl_states_tree_insert(a,b) rb_insert((a),(b)) #endif *existing_state = fcs_libavl_states_tree_insert(instance->tree, new_state); is_state_new = (*existing_state == NULL); #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_TREE) *existing_state = g_tree_lookup(instance->tree, (gpointer)new_state); if (*existing_state == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_tree_insert( instance->tree, (gpointer)new_state, (gpointer)new_state ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_GLIB_HASH) *existing_state = g_hash_table_lookup(instance->hash, (gpointer)new_state); if (*existing_state == NULL) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ g_hash_table_insert( instance->hash, (gpointer)new_state, (gpointer)new_state ); is_state_new = 1; } else { is_state_new = 0; } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_DB_FILE) { DBT key, value; key.data = new_state; key.size = sizeof(*new_state); if (instance->db->get( instance->db, NULL, &key, &value, 0 ) == 0) { /* The new state was not found. Let's insert it. * The value must be the same as the key, so g_tree_lookup() * will return it. */ value.data = key.data; value.size = key.size; instance->db->put( instance->db, NULL, &key, &value, 0); is_state_new = 1; } else { is_state_new = 0; *existing_state = (fcs_state_with_locations_t *)(value.data); } } #elif (FCS_STATE_STORAGE == FCS_STATE_STORAGE_JUDY) { PWord_t * PValue; JHSI(PValue, instance->judy_array, new_state_key, sizeof(*new_state_key)); /* TODO : Handle out-of-memory. */ if (*PValue == 0) { /* A new state. */ is_state_new = 1; *PValue = (PWord_t)(*existing_state_val = new_state_val); } else { /* Already exists. */ is_state_new = 0; *existing_state_val = (fcs_state_extra_info_t *)(*PValue); } } #else #error no define #endif if (is_state_new) { /* The new state was not found in the cache, and it was already inserted */ if (new_state_val->parent_val) { new_state_val->parent_val->num_active_children++; } instance->num_states_in_collection++; if (new_state_val->moves_to_parent != NULL) { new_state_val->moves_to_parent = fc_solve_move_stack_compact_allocate( hard_thread, new_state_val->moves_to_parent ); } return FCS_STATE_DOES_NOT_EXIST; } else { return FCS_STATE_ALREADY_EXISTS; } }