#include #include #include #include "subdiv.h" /* --- Fonctions privées traitement valeurs --- */ boolean is_key(node* n, char* mem, char* key) { int i, length = strlen(key); //Verif que la clef correspond à celle en param for (i = 0; i < length; i++) { if (mem[i + n->start] != key[i]) { return false; } } //Verif que le caractere suivant est bien un = if (mem[i + n->start] != '=') { return false; } return true; } node* find_key(subdiv* sd, char* mem, char* key) { int length = strlen(key) + 2; //Clef + = + taille min mot node* n = NULL; //Cherche la clef for (int i = 0; i < MEM_SIZE / 2; i++) { if (sd->use[i] && sd->mem[i].type == MEMSET && sd->mem[i].length >= length) { //Regarde si la clef correspond if (is_key(&sd->mem[i], mem, key)) { n = &sd->mem[i]; break; } } } return n; } char* parse_val(node* n, char* mem) { int pos = 0; //Cherche la postion du = while (mem[pos + n->start] != '=') { pos++; } pos++; //Creation chaine char* str = mem + n->start + pos; char* val = malloc(sizeof (char) * (n->length - pos + 1)); memset(val, 0, n->length - pos + 1); strncpy(val, str, n->length - pos); //Retour return val; } /* --- Fonctions privées nodes --- */ boolean div_node(subdiv* sd, node* n) { node* newn = NULL; int i; //Verif que la node à diviser est bien libre if (n->type != MEMEMPTY) { return false; } //Cherche une node libre for (i = 0; i < MEM_SIZE; i++) { if (sd->use[i] == 0) { newn = &sd->mem[i]; break; } } //Plus de place if (newn == NULL) { return false; } //Setup node newn->index = i; newn->start = n->start + (n->length / 2); newn->end = n->end; newn->length = n->length / 2; newn->type = MEMEMPTY; newn->prev = n; newn->next = n->next; //Modifie node suivant la nouvelle if (n->next != NULL) { n->next->prev = newn; } //Modifie node origine n->end = n->start + (n->length / 2); n->length /= 2; n->next = newn; //Indique que la node est utilisé sd->use[i] = true; return true; } boolean fusion_node(subdiv* sd, node* n) { //Verif que la node et la node suivante sont vide if (!(n->type == MEMEMPTY && n->next != NULL && n->next->type == MEMEMPTY)) { return false; } node* n2 = n->next; //Verif qu'elles ont la meme taille if (n->length != n2->length) { return false; } //Met à jour la node n->end = n2->end; n->length *= 2; n->next = n2->next; if (n2->next != NULL) { n2->next->prev = n; } //Indique que l'autre node n'est plus utilisée sd->use[n2->index] = false; return true; } /* --- Fonctions publiques --- */ void ini_subdiv(subdiv* sd) { sd->mem[0] = (node){0, 0, MEM_SIZE, MEM_SIZE, MEMEMPTY, NULL, NULL}; sd->use[0] = true; for (int i = 1; i < MEM_SIZE / 2; i++) { sd->use[i] = false; } } boolean add_data_subdiv(subdiv* sd, char* mem, char* key, char* data) { //Recup taille data int length = strlen(data) + strlen(key) + 1; //Cherche un espace ou mettre la données node* n = &sd->mem[0]; while (n != NULL) { if (n->type == MEMEMPTY && n->length >= length) { break; } n = n->next; } //Si plus de place if (n == NULL) { return false; } //Si on peut diviser par deux la place libre et stocker dedans if ((n->length / 2) >= length) { //On divise la zone en 2 if (!div_node(sd, n)) { return false; } return add_data_subdiv(sd, mem, key, data); } //Genere chaine à mettre en mémoire char* str = malloc(sizeof (char) * (length + 1)); memset(str, 0, length + 1); snprintf(str, length + 1, "%s=%s", key, data); //On maj la node n->type = MEMSET; n->length = length; //On met dans la mémoire for (int i = 0; i < length; i++) { mem[i + n->start] = str[i]; } //Nettoyage free(str); return true; } boolean add_fdata_subdiv(subdiv* sd, char* mem, char* data) { //Recup taille data int length = strlen(data); //Cherche un espace ou mettre la données node* n = &sd->mem[0]; while (n != NULL) { if (n->type == MEMEMPTY && n->length >= length) { break; } n = n->next; } //Si plus de place if (n == NULL) { return false; } //Si on peut diviser par deux la place libre et stocker dedans if ((n->length / 2) >= length) { //On divise la zone en 2 if (!div_node(sd, n)) { return false; } return add_fdata_subdiv(sd, mem, data); } //On maj la node n->type = MEMSET; n->length = length; //On met dans la mémoire for (int i = 0; i < length; i++) { mem[i + n->start] = data[i]; } return true; } char* get_data_subdiv(subdiv* sd, char* mem, char* key) { node* n = find_key(sd, mem, key); //Si pas trouvé la clef if (n == NULL) { return NULL; } //Recup valeur return parse_val(n, mem); } boolean remove_data_subdiv(subdiv* sd, char* mem, char* key) { node* n = find_key(sd, mem, key); //Si pas trouvé la clef if (n == NULL) { return false; } //Marque la node comme vide n->length = n->end - n->start; n->type = MEMEMPTY; //Tente la fusion des noeuds (Algo imparfait) n = &sd->mem[0]; while (n != NULL) { //On fusionne avec celui d'après si celui d'avant à une taille différente if (n->prev == NULL) { if (fusion_node(sd, n)) { n = &sd->mem[0]; } else { n = n->next; } } else if (n->prev->length != n->length) { if (fusion_node(sd, n)) { n = &sd->mem[0]; } else { n = n->next; } } else { n = n->next; } } return true; } void show_subdiv(subdiv* sd) { node* n = &sd->mem[0]; while (n != NULL) { printf("Deb : %d, Fin : %d, Length : %d, Real length : %d, Use : %d\n", n->start, n->end, n->length, n->end - n->start, (int) n->type); n = n->next; } } void show_data_subdiv(subdiv* sd, char* mem){ node* n = &sd->mem[0]; while (n != NULL) { if(n->type == MEMSET){ char* str = malloc(sizeof(char) * (n->length + 1)); char* deb = mem + n->start; memset(str, 0, n->length + 1); strncpy(str, deb, n->length); printf("%s\n", str); free(str); } n = n->next; } }