/* Pseudo-key (lien_url structure) hash function */ static inthash_keys key_adrfil_hashes_generic(void *arg, const char *value_, const int former) { hash_struct *const hash = (hash_struct*) arg; const lien_url*const lien = (lien_url*) value_; const char *const adr = !former ? lien->adr : lien->former_adr; const char *const fil = !former ? lien->fil : lien->former_fil; const char *const adr_norm = adr != NULL ? ( hash->normalized ? jump_normalized(adr) : jump_identification(adr) ) : NULL; // copy address assertf(adr_norm != NULL); strcpy(hash->normfil, adr_norm); // copy link assertf(fil != NULL); if (hash->normalized) { fil_normalized(fil, &hash->normfil[strlen(hash->normfil)]); } else { strcpy(&hash->normfil[strlen(hash->normfil)], fil); } // hash return inthash_hash_value(hash->normfil); }
/* Pseudo-key (lien_url structure) comparison function */ static int key_adrfil_equals_generic(void *arg, const char *a_, const char *b_, const int former) { hash_struct *const hash = (hash_struct*) arg; const int normalized = hash->normalized; const lien_url*const a = (lien_url*) a_; const lien_url*const b = (lien_url*) b_; const char *const a_adr = !former ? a->adr : a->former_adr; const char *const b_adr = !former ? b->adr : b->former_adr; const char *const a_fil = !former ? a->fil : a->former_fil; const char *const b_fil = !former ? b->fil : b->former_fil; const char *ja; const char *jb; // safety assertf(a_adr != NULL); assertf(b_adr != NULL); assertf(a_fil != NULL); assertf(b_fil != NULL); // skip scheme and authentication to the domain (possibly without www.) ja = normalized ? jump_normalized(a_adr) : jump_identification(a_adr); jb = normalized ? jump_normalized(b_adr) : jump_identification(b_adr); assertf(ja != NULL); assertf(jb != NULL); if (strcasecmp(ja, jb) != 0) { return 0; } // now compare pathes if (normalized) { fil_normalized(a_fil, hash->normfil); fil_normalized(b_fil, hash->normfil2); return strcmp(hash->normfil, hash->normfil2) == 0; } else { return strcmp(a_fil, b_fil) == 0; } }
// GESTION DES TABLES DE HACHAGE // Méthode à 2 clés (adr+fil), 2e cle facultative // hash[no_enregistrement][pos]->hash est un index dans le tableau général liens // #define HTS_HASH_SIZE 8191 (premier si possible!) // type: numero enregistrement - 0 est case insensitive (sav) 1 (adr+fil) 2 (former_adr+former_fil) // recherche dans la table selon nom1,nom2 et le no d'enregistrement // retour: position ou -1 si non trouvé int hash_read(const hash_struct* hash,char* nom1,char* nom2,int type,int normalized) { char BIGSTK normfil_[HTS_URLMAXSIZE*2]; char catbuff[CATBUFF_SIZE]; char* normfil; char* normadr; unsigned int cle; int pos; // calculer la clé de recherche, non modulée if (type) cle = hash_cle(nom1,nom2); else cle = hash_cle(convtolower(catbuff,nom1),nom2); // case insensitive // la position se calcule en modulant pos = (int) (cle%HTS_HASH_SIZE); // entrée trouvée? if (hash->hash[type][pos] >= 0) { // un ou plusieurs enregistrement(s) avec une telle clé existe.. // tester table de raccourcis (hash) // pos est maintenant la position recherchée dans liens pos = hash->hash[type][pos]; while (pos>=0) { // parcourir la chaine switch (type) { case 0: // sav if (strfield2(nom1,hash->liens[pos]->sav)) { // case insensitive #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } break; case 1: // adr+fil { if (!normalized) normfil=hash->liens[pos]->fil; else normfil=fil_normalized(hash->liens[pos]->fil,normfil_); if (!normalized) normadr = jump_identification(hash->liens[pos]->adr); else normadr = jump_normalized(hash->liens[pos]->adr); if ((strfield2(nom1,normadr)!=0) && (strcmp(nom2,normfil)==0)) { #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } } break; case 2: // former_adr+former_fil { if (hash->liens[pos]->former_adr) { if (!normalized) normfil=hash->liens[pos]->former_fil; else normfil=fil_normalized(hash->liens[pos]->former_fil,normfil_); if (!normalized) normadr = jump_identification(hash->liens[pos]->former_adr); else normadr = jump_normalized(hash->liens[pos]->former_adr); if ((strfield2(nom1,normadr)!=0) && (strcmp(nom2,normfil)==0)) { #if DEBUG_HASH==2 printf("hash: found shortcut at %d\n",pos); #endif return pos; } } } break; } // calculer prochaine position dans la chaine { int old=pos; pos=hash->liens[pos]->hash_next[type]; // sinon prochain dans la chaine if (old==pos) pos=-1; // erreur de bouclage (ne devrait pas arriver) } } // Ok va falloir chercher alors.. /*pos=hash->max_lien; // commencer à max_lien switch (type) { case 0: // sav while(pos>=0) { if (hash->liens[pos]->hash_sav == cle ) { if (strcmp(nom1,hash->liens[pos]->sav)==0) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } break; case 1: // adr+fil while(pos>=0) { if (hash->liens[pos]->hash_adrfil == cle ) { if ((strcmp(nom1,hash->liens[pos]->adr)==0) && (strcmp(nom2,hash->liens[pos]->fil)==0)) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } break; case 2: // former_adr+former_fil while(pos>=0) { if (hash->liens[pos]->hash_fadrfil == cle ) { if (hash->liens[pos]->former_adr) if ((strcmp(nom1,hash->liens[pos]->former_adr)==0) && (strcmp(nom2,hash->liens[pos]->former_fil)==0)) { hash->hash[type][(int) (cle%HTS_HASH_SIZE)] = pos; // noter plus récent dans shortcut table #if DEBUG_HASH==2 printf("hash: found long search at %d\n",pos); #endif return pos; } } pos--; } }*/ #if DEBUG_HASH==1 printf("hash: not found after test %s%s\n",nom1,nom2); #endif return -1; // non trouvé } else { #if DEBUG_HASH==2 printf("hash: not found %s%s\n",nom1,nom2); #endif return -1; // non trouvé : clé non entrée (même une fois) } }
// enregistrement lien lpos dans les 3 tables hash1..3 void hash_write(hash_struct* hash,int lpos,int normalized) { char BIGSTK normfil_[HTS_URLMAXSIZE*2]; char catbuff[CATBUFF_SIZE]; char* normfil; unsigned int cle; int pos; int* ptr; // if (hash->liens[lpos]) { // on sait jamais.. hash->max_lien = max(hash->max_lien,lpos); #if DEBUG_HASH hashnumber=hash->max_lien; #endif // élément actuel sur -1 (fin de chaine) hash->liens[lpos]->hash_next[0]=hash->liens[lpos]->hash_next[1]=hash->liens[lpos]->hash_next[2]=-1; // cle = hash_cle(convtolower(catbuff,hash->liens[lpos]->sav),""); // CASE INSENSITIVE pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,0,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf("[%d",pos); #endif // if (!normalized) normfil=hash->liens[lpos]->fil; else normfil=fil_normalized(hash->liens[lpos]->fil,normfil_); if (!normalized) cle = hash_cle(jump_identification(hash->liens[lpos]->adr),normfil); else cle = hash_cle(jump_normalized(hash->liens[lpos]->adr),normfil); pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,1,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf(",%d",pos); #endif // if (hash->liens[lpos]->former_adr) { // former_adr existe? if (!normalized) normfil=hash->liens[lpos]->former_fil; else normfil=fil_normalized(hash->liens[lpos]->former_fil,normfil_); if (!normalized) cle = hash_cle(jump_identification(hash->liens[lpos]->former_adr),normfil); else cle = hash_cle(jump_normalized(hash->liens[lpos]->former_adr),normfil); pos = (int) (cle%HTS_HASH_SIZE); ptr = hash_calc_chaine(hash,2,pos); // calculer adresse chaine *ptr = lpos; // noter dernier enregistré #if DEBUG_HASH==3 printf(",%d",pos); #endif } #if DEBUG_HASH==3 printf("] "); fflush(stdout); #endif } #if DEBUT_HASH else { printf("* hash_write=0!!\n"); abortLogFmt("unexpected error in hash_write (pos=%d)" _ pos); exit(1); } #endif // }