subdiv.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "subdiv.h"
  5. /* --- Fonctions privées traitement valeurs --- */
  6. /**
  7. * Indique si une chaine est la clef d'un noeud
  8. * @param node* Le noeud
  9. * @param char* La mémoire
  10. * @param char* La clef
  11. * @return true - Oui/false - Non
  12. */
  13. boolean is_key(node* n, char* mem, char* key) {
  14. int i, length = strlen(key);
  15. //Verif que la clef correspond à celle en param
  16. for (i = 0; i < length; i++) {
  17. if (mem[i + n->start] != key[i]) {
  18. return false;
  19. }
  20. }
  21. //Verif que le caractere suivant est bien un =
  22. if (mem[i + n->start] != '=') {
  23. return false;
  24. }
  25. return true;
  26. }
  27. /**
  28. * Cherche une clef
  29. * @param subdiv* Le gestionnaire de mémoire par subdivision
  30. * @param char* La mémoire
  31. * @param char* La clef
  32. * @return La node correspondante ou NULL si introuvable
  33. */
  34. node* find_key(subdiv* sd, char* mem, char* key) {
  35. int length = strlen(key) + 2; //Clef + = + taille min mot
  36. node* n = NULL;
  37. //Cherche la clef
  38. for (int i = 0; i < MEM_SIZE / 2; i++) {
  39. if (sd->use[i] && sd->mem[i].type == MEMSET && sd->mem[i].length >= length) {
  40. //Regarde si la clef correspond
  41. if (is_key(&sd->mem[i], mem, key)) {
  42. n = &sd->mem[i];
  43. break;
  44. }
  45. }
  46. }
  47. return n;
  48. }
  49. /**
  50. * Récupère la valeur d'un noeid
  51. * @param node* La noeud
  52. * @param char* La mémoire
  53. */
  54. char* parse_val(node* n, char* mem) {
  55. int pos = 0;
  56. //Cherche la postion du =
  57. while (mem[pos + n->start] != '=') {
  58. pos++;
  59. }
  60. pos++;
  61. //Creation chaine
  62. char* str = mem + n->start + pos;
  63. char* val = malloc(sizeof (char) * (n->length - pos + 1));
  64. memset(val, 0, n->length - pos + 1);
  65. strncpy(val, str, n->length - pos);
  66. //Retour
  67. return val;
  68. }
  69. /* --- Fonctions privées nodes --- */
  70. boolean div_node(subdiv* sd, node* n) {
  71. node* newn = NULL;
  72. int i;
  73. //Verif que la node à diviser est bien libre
  74. if (n->type != MEMEMPTY) {
  75. return false;
  76. }
  77. //Cherche une node libre
  78. for (i = 0; i < MEM_SIZE; i++) {
  79. if (sd->use[i] == 0) {
  80. newn = &sd->mem[i];
  81. break;
  82. }
  83. }
  84. //Plus de place
  85. if (newn == NULL) {
  86. return false;
  87. }
  88. //Setup node
  89. newn->index = i;
  90. newn->start = n->start + (n->length / 2);
  91. newn->end = n->end;
  92. newn->length = n->length / 2;
  93. newn->type = MEMEMPTY;
  94. newn->prev = n;
  95. newn->next = n->next;
  96. //Modifie node suivant la nouvelle
  97. if (n->next != NULL) {
  98. n->next->prev = newn;
  99. }
  100. //Modifie node origine
  101. n->end = n->start + (n->length / 2);
  102. n->length /= 2;
  103. n->next = newn;
  104. //Indique que la node est utilisé
  105. sd->use[i] = true;
  106. return true;
  107. }
  108. boolean fusion_node(subdiv* sd, node* n) {
  109. //Verif que la node et la node suivante sont vide
  110. if (!(n->type == MEMEMPTY && n->next != NULL && n->next->type == MEMEMPTY)) {
  111. return false;
  112. }
  113. node* n2 = n->next;
  114. //Verif qu'elles ont la meme taille
  115. if (n->length != n2->length) {
  116. return false;
  117. }
  118. //Met à jour la node
  119. n->end = n2->end;
  120. n->length *= 2;
  121. n->next = n2->next;
  122. if (n2->next != NULL) {
  123. n2->next->prev = n;
  124. }
  125. //Indique que l'autre node n'est plus utilisée
  126. sd->use[n2->index] = false;
  127. return true;
  128. }
  129. /* --- Fonctions publiques --- */
  130. void ini_subdiv(subdiv* sd) {
  131. sd->mem[0] = (node){0, 0, MEM_SIZE, MEM_SIZE, MEMEMPTY, NULL, NULL};
  132. sd->use[0] = true;
  133. for (int i = 1; i < MEM_SIZE / 2; i++) {
  134. sd->use[i] = false;
  135. }
  136. }
  137. boolean add_data_subdiv(subdiv* sd, char* mem, char* key, char* data) {
  138. //Recup taille data
  139. int length = strlen(data) + strlen(key) + 1;
  140. //Cherche un espace ou mettre la données
  141. node* n = &sd->mem[0];
  142. while (n != NULL) {
  143. if (n->type == MEMEMPTY && n->length >= length) {
  144. break;
  145. }
  146. n = n->next;
  147. }
  148. //Si plus de place
  149. if (n == NULL) {
  150. return false;
  151. }
  152. //Si on peut diviser par deux la place libre et stocker dedans
  153. if ((n->length / 2) >= length) {
  154. //On divise la zone en 2
  155. if (!div_node(sd, n)) {
  156. return false;
  157. }
  158. return add_data_subdiv(sd, mem, key, data);
  159. }
  160. //Genere chaine à mettre en mémoire
  161. char* str = malloc(sizeof (char) * (length + 1));
  162. memset(str, 0, length + 1);
  163. snprintf(str, length + 1, "%s=%s", key, data);
  164. //On maj la node
  165. n->type = MEMSET;
  166. n->length = length;
  167. //On met dans la mémoire
  168. for (int i = 0; i < length; i++) {
  169. mem[i + n->start] = str[i];
  170. }
  171. //Nettoyage
  172. free(str);
  173. return true;
  174. }
  175. boolean add_fdata_subdiv(subdiv* sd, char* mem, char* data) {
  176. //Recup taille data
  177. int length = strlen(data);
  178. //Cherche un espace ou mettre la données
  179. node* n = &sd->mem[0];
  180. while (n != NULL) {
  181. if (n->type == MEMEMPTY && n->length >= length) {
  182. break;
  183. }
  184. n = n->next;
  185. }
  186. //Si plus de place
  187. if (n == NULL) {
  188. return false;
  189. }
  190. //Si on peut diviser par deux la place libre et stocker dedans
  191. if ((n->length / 2) >= length) {
  192. //On divise la zone en 2
  193. if (!div_node(sd, n)) {
  194. return false;
  195. }
  196. return add_fdata_subdiv(sd, mem, data);
  197. }
  198. //On maj la node
  199. n->type = MEMSET;
  200. n->length = length;
  201. //On met dans la mémoire
  202. for (int i = 0; i < length; i++) {
  203. mem[i + n->start] = data[i];
  204. }
  205. return true;
  206. }
  207. char* get_data_subdiv(subdiv* sd, char* mem, char* key) {
  208. node* n = find_key(sd, mem, key);
  209. //Si pas trouvé la clef
  210. if (n == NULL) {
  211. return NULL;
  212. }
  213. //Recup valeur
  214. return parse_val(n, mem);
  215. }
  216. boolean remove_data_subdiv(subdiv* sd, char* mem, char* key) {
  217. node* n = find_key(sd, mem, key);
  218. //Si pas trouvé la clef
  219. if (n == NULL) {
  220. return false;
  221. }
  222. //Marque la node comme vide
  223. n->length = n->end - n->start;
  224. n->type = MEMEMPTY;
  225. //Tente la fusion des noeuds (Algo imparfait)
  226. n = &sd->mem[0];
  227. while (n != NULL) {
  228. //On fusionne avec celui d'après si celui d'avant à une taille différente
  229. if (n == &sd->mem[0]) {
  230. if (fusion_node(sd, n)) {
  231. n = &sd->mem[0];
  232. } else {
  233. n = n->next;
  234. }
  235. } else if (n->prev->length != n->length) {
  236. if (fusion_node(sd, n)) {
  237. n = &sd->mem[0];
  238. } else {
  239. n = n->next;
  240. }
  241. } else {
  242. n = n->next;
  243. }
  244. }
  245. return true;
  246. }
  247. void show_subdiv(subdiv* sd) {
  248. node* n = &sd->mem[0];
  249. while (n != NULL) {
  250. 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);
  251. n = n->next;
  252. }
  253. }
  254. void show_data_subdiv(subdiv* sd, char* mem){
  255. node* n = &sd->mem[0];
  256. while (n != NULL) {
  257. if(n->type == MEMSET){
  258. char* str = malloc(sizeof(char) * (n->length + 1));
  259. char* deb = mem + n->start;
  260. memset(str, 0, n->length + 1);
  261. strncpy(str, deb, n->length);
  262. printf("%s\n", str);
  263. free(str);
  264. }
  265. n = n->next;
  266. }
  267. }