subdiv.c 6.8 KB

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