LIST.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. // C source file with the function definitions to handle lists
  2. // get_lnode() function
  3. // function to create a list node to probably start a list in
  4. lnode * get_lnode(void * src, umax src_size, lnode_data_type type)
  5. {
  6. // check params
  7. lnode * new = NULL;
  8. if (src == NULL || src_size == 0 || type == LNODE_DT_NO_TYPE)
  9. goto err;
  10. // check if src actually contains what type claims
  11. // I can only do checks for strings as integers/floats cant be checked
  12. umax tmp = 0;
  13. if (type > LNODE_DT_FLT64LE) {
  14. char_enc old_enc = CHAR_ARR_ENC_STATE;
  15. set_ch_arr_enc_state(type - LNODE_DT_FLT64LE);
  16. if ((tmp = check_chenc_arr(src, src_size)) == 0)
  17. goto err;
  18. set_ch_arr_enc_state(old_enc);
  19. }
  20. // allocate space for the node
  21. new = allocate_memory(1, sizeof(lnode));
  22. if (new == NULL)
  23. goto err;
  24. // assign variables
  25. new -> SRC = src;
  26. new -> SIZE = tmp == 0 ? src_size : tmp;
  27. new -> TYPE = type;
  28. // switch time (set print functions)
  29. switch (type)
  30. {
  31. case LNODE_DT_UINT8: new -> print = print_uint8; break;
  32. case LNODE_DT_UINT16BE: new -> print = print_uint16be; break;
  33. case LNODE_DT_UINT16LE: new -> print = print_uint16le; break;
  34. case LNODE_DT_UINT32BE: new -> print = print_uint32be; break;
  35. case LNODE_DT_UINT32LE: new -> print = print_uint32le; break;
  36. case LNODE_DT_SINT8: new -> print = print_sint8; break;
  37. case LNODE_DT_SINT16BE: new -> print = print_sint16be; break;
  38. case LNODE_DT_SINT16LE: new -> print = print_sint16le; break;
  39. case LNODE_DT_SINT32BE: new -> print = print_sint32be; break;
  40. case LNODE_DT_SINT32LE: new -> print = print_sint32le; break;
  41. // floats
  42. case LNODE_DT_FLT16BE: new -> print = print_float16be; break;
  43. case LNODE_DT_FLT16LE: new -> print = print_float16le; break;
  44. case LNODE_DT_FLT32BE: new -> print = print_float32be; break;
  45. case LNODE_DT_FLT32LE: new -> print = print_float32le; break;
  46. case LNODE_DT_FLT64BE: new -> print = print_float64be; break;
  47. case LNODE_DT_FLT64LE: new -> print = print_float64le; break;
  48. // strings
  49. case LNODE_DT_STR_ASCII:
  50. case LNODE_DT_STR_CP1252:
  51. case LNODE_DT_STR_CP932:
  52. case LNODE_DT_STR_SHIFT_JIS:
  53. case LNODE_DT_STR_UTF8:
  54. case LNODE_DT_STR_UTF16BE:
  55. case LNODE_DT_STR_UTF16LE:
  56. new -> print = print_chenc_arr;
  57. break;
  58. }
  59. // inconsistent info was provided *somehow*
  60. if (new -> print == NULL)
  61. goto err;
  62. // return the new node
  63. return new;
  64. // failure
  65. err:
  66. free_memory(new);
  67. return NULL;
  68. }
  69. // find_lnode_behind() function
  70. lnode * find_lnode_behind(lnode * node, umax index)
  71. {
  72. // check params
  73. if (node == NULL)
  74. return NULL;
  75. // search for the required behind node
  76. for (umax i = 0; i < index; i++)
  77. if (node -> BEHIND != NULL)
  78. node = node -> BEHIND;
  79. else
  80. break;
  81. // return the result
  82. return node;
  83. }
  84. // find_lnode_front() function
  85. lnode * find_lnode_front(lnode * node, umax index)
  86. {
  87. // check params
  88. if (node == NULL)
  89. return NULL;
  90. // search for the required front node
  91. for (umax i = 0; i < index; i++)
  92. if (node -> FRONT != NULL)
  93. node = node -> FRONT;
  94. else
  95. break;
  96. // return the result
  97. return node;
  98. }
  99. // find_lnode_parent() function
  100. // function to find the upper level parent needed
  101. lnode * find_lnode_parent(lnode * node, umax index)
  102. {
  103. // check params
  104. if (node == NULL)
  105. return NULL;
  106. // search for the required parent node
  107. lnode * parent = NULL;
  108. for (umax i = 0; i < index; i++) {
  109. // find the most behind node and check if it has a parent
  110. node = find_lnode_behind(node, (umax) -1);
  111. if (node -> PARENT != NULL) {
  112. parent = node -> PARENT;
  113. node = node -> PARENT;
  114. }
  115. else
  116. break;
  117. }
  118. // return the result
  119. return node;
  120. }
  121. // find_lnode_child() function
  122. // function to find the child index needed
  123. lnode * find_lnode_child(lnode * node, umax index)
  124. {
  125. // check params
  126. if (node == NULL || node -> CHILD == NULL)
  127. return NULL;
  128. // otherwise, search for the required child node
  129. return find_lnode_front(node -> CHILD, index);
  130. }
  131. // add_lnode_front() function
  132. // function to append an element to a node as a new element on the list
  133. // or as a child element (at the end of both lists)
  134. lnode * add_lnode_front(lnode * node, void * src, umax src_size, lnode_data_type type)
  135. {
  136. // check params
  137. lnode * front = NULL;
  138. if (node == NULL || (front = get_lnode(src, src_size, type)) == NULL)
  139. goto err;
  140. // append the item to the list
  141. node = find_lnode_front(node, (umax) -1);
  142. if (node == NULL)
  143. goto err;
  144. node -> FRONT = front;
  145. front -> BEHIND = node;
  146. // return the result
  147. return front;
  148. err: // error happened
  149. free_memory(front);
  150. return NULL;
  151. }
  152. // add_lnode_child() function
  153. // function to create a child node for a parent node
  154. lnode * add_lnode_child(lnode * node, void * src, umax src_size, lnode_data_type type)
  155. {
  156. // check params
  157. lnode * child = NULL;
  158. if (node == NULL || (child = get_lnode(src, src_size, type)) == NULL)
  159. goto err;
  160. // add the child node at the end of the child list of the parent
  161. if (node -> CHILD == NULL) {
  162. node -> CHILD = child;
  163. child -> PARENT = node;
  164. } else /* find the last node child in the list */ {
  165. node = find_lnode_child(node, (umax) -1);
  166. if (node == NULL)
  167. goto err;
  168. node -> FRONT = child;
  169. child -> BEHIND = node;
  170. }
  171. // return the result
  172. return child;
  173. err: // error happened
  174. free_memory(child);
  175. return NULL;
  176. }
  177. // rm_lnode() function
  178. // function to remove the memory allocated for a lnode pointer
  179. // the function will return a pointer to the ideal lnode to be deleted next
  180. lnode * rm_lnode(lnode * node)
  181. {
  182. // check params
  183. if (node == NULL)
  184. return NULL;
  185. // Parent
  186. // |
  187. // Behind - Node - Front
  188. // |
  189. // Child
  190. // variable to return
  191. lnode * tmp = NULL;
  192. // handle behind and front
  193. if (node -> CHILD == NULL) {
  194. /***********************************/
  195. // <div> | <div>
  196. // <div/> | <div/>
  197. // <div/> --> to delete |
  198. // <div/> | <div/>
  199. // </div> | </div>
  200. /***********************************/
  201. // link front with behind (if they exist)
  202. // return front if behind is NULL
  203. if ((node -> FRONT != NULL) && (node -> BEHIND != NULL)) {
  204. node -> BEHIND -> FRONT = node -> FRONT;
  205. node -> FRONT -> BEHIND = node -> BEHIND;
  206. } else if (node -> BEHIND != NULL)
  207. node -> BEHIND -> FRONT = NULL;
  208. else if (node -> FRONT != NULL)
  209. node -> FRONT -> BEHIND = NULL;
  210. // return the front node
  211. tmp = node -> FRONT;
  212. } else /* node has childs */ {
  213. /***********************************/
  214. // <div> | <div>
  215. // <div/> | <div/>
  216. // <div> --> to delete |
  217. // <div/> | <div/>
  218. // <div/> | <div/>
  219. // </div> --> to delete |
  220. // <div/> | <div/>
  221. // </div> | </div>
  222. /***********************************/
  223. // link behind with first child
  224. // then link front with last child
  225. // check the existance of everything
  226. if (node -> BEHIND != NULL) {
  227. node -> BEHIND -> FRONT = node -> CHILD;
  228. node -> CHILD -> BEHIND = node -> BEHIND;
  229. node -> CHILD -> PARENT = NULL; // override parent
  230. } else // assign current node's parent if it exists
  231. node -> CHILD -> PARENT = node -> PARENT;
  232. // link the last child with the front node
  233. if (node -> FRONT != NULL) {
  234. tmp = find_lnode_child(node, (umax) -1);
  235. tmp -> FRONT = node -> FRONT;
  236. node -> FRONT -> BEHIND = tmp;
  237. }
  238. // return the first child
  239. tmp = node -> CHILD;
  240. }
  241. // release node's memory
  242. end:
  243. free_memory(node);
  244. return tmp;
  245. }
  246. // rm_lnode_fronts() function
  247. // function to remove the front nodes of a node (childs of front nodes remain)
  248. umax rm_lnode_fronts(lnode * node)
  249. {
  250. // check params
  251. if (node == NULL)
  252. return 0;
  253. // list the front nodes remove them
  254. umax node_count = 0;
  255. lnode * tmp = node -> FRONT;
  256. while (tmp != NULL) {
  257. node = tmp -> FRONT;
  258. rm_lnode(tmp);
  259. tmp = node;
  260. node_count++;
  261. }
  262. // return the number of nodes deteled
  263. return node_count;
  264. }
  265. // rm_lnode_childs() function
  266. // function to remove the direct child nodes of a node (childs of childs remain)
  267. umax rm_lnode_childs(lnode * node)
  268. {
  269. // check params
  270. if (node == NULL || node -> CHILD == NULL)
  271. return 0;
  272. // remove the childs of the node
  273. umax node_count = rm_lnode_fronts(node -> CHILD);
  274. rm_lnode(node -> CHILD);
  275. node -> CHILD = NULL;
  276. node_count++;
  277. return node_count;
  278. }
  279. // rm_lnode_list() function
  280. // function to completely delete the list coming out of an lnode (recursive)
  281. umax rm_lnode_list(lnode * node)
  282. {
  283. // check params
  284. if (node == NULL)
  285. return 0;
  286. // start the removal
  287. umax node_count = 0;
  288. while (node != NULL) {
  289. node = rm_lnode(node);
  290. node_count++;
  291. }
  292. // return how many nodes were cleared
  293. return node_count;
  294. }
  295. // the following count functions are basically a copy from the remove
  296. // functions above but used to count nodes instead of removing them
  297. // count_lnode_fronts() function
  298. umax count_lnode_fronts(lnode * node)
  299. {
  300. // check params
  301. if (node == NULL)
  302. return 0;
  303. // list the front nodes and check if they have children
  304. umax node_count = 0;
  305. lnode * tmp = node -> FRONT;
  306. while (tmp != NULL) {
  307. tmp = tmp -> FRONT;
  308. node_count++;
  309. }
  310. // return the number of nodes deleted
  311. return node_count;
  312. }
  313. // count_lnode_childs() function
  314. umax count_lnode_childs(lnode * node)
  315. {
  316. // check params
  317. if (node == NULL || node -> CHILD == NULL)
  318. return 0;
  319. // count the childs of the node
  320. return count_lnode_fronts(node -> CHILD) + 1;
  321. }
  322. // count_lnodes() function
  323. umax count_lnodes(lnode * node)
  324. {
  325. // check params
  326. if (node == NULL)
  327. return 0;
  328. // start the count
  329. // count nodes at the same parenting level in each iteration
  330. lnode * ptr = node;
  331. umax old_smlvl_cnt = count_lnode_fronts(node) + 1, new_smlvl_cnt = 0;
  332. lnode ** old_node_arr = allocate_memory(sizeof(lnode *), old_smlvl_cnt), ** new_node_arr = NULL;
  333. // add all the nodes at the same level to old_node_arr
  334. for (umax i = 0; i < old_smlvl_cnt; i++) {
  335. old_node_arr[i] = ptr;
  336. ptr = ptr -> FRONT;
  337. }
  338. // variable to return
  339. umax node_count = old_smlvl_cnt;
  340. // start the count
  341. while (old_smlvl_cnt != 0)
  342. {
  343. // go through each node to see if they have children
  344. for (umax i = 0; i < old_smlvl_cnt; i++)
  345. new_smlvl_cnt += count_lnode_childs(old_node_arr[i]);
  346. // allocate memory for the next level of nodes
  347. new_node_arr = allocate_memory(sizeof(lnode *), new_smlvl_cnt);
  348. if (new_node_arr == NULL) {
  349. free_memory(old_node_arr);
  350. return 0;
  351. }
  352. // add the new nodes
  353. for (umax i = 0, arr_pos = 0; i < old_smlvl_cnt; i++) {
  354. ptr = old_node_arr[i];
  355. if (ptr -> CHILD != NULL) {
  356. new_node_arr[arr_pos++] = ptr -> CHILD;
  357. ptr = ptr -> CHILD;
  358. while (ptr -> FRONT != NULL) {
  359. new_node_arr[arr_pos++] = ptr -> FRONT;
  360. ptr = ptr -> FRONT;
  361. }
  362. }
  363. }
  364. // setup the variables for the next loop
  365. free_memory(old_node_arr);
  366. old_node_arr = new_node_arr;
  367. new_node_arr = NULL;
  368. node_count += new_smlvl_cnt;
  369. old_smlvl_cnt = new_smlvl_cnt;
  370. new_smlvl_cnt = 0;
  371. }
  372. // for the last loop
  373. free_memory(old_node_arr);
  374. // return the result
  375. return node_count;
  376. }
  377. // count_lnodes_parent_lvls() function
  378. umax count_lnodes_parent_lvls(lnode * node)
  379. {
  380. // check params
  381. if (node == NULL)
  382. return 0;
  383. // ok so, I have to traverse through all nodes keeping count of the parent level
  384. umax parent_lvls = 1;
  385. umax old_node_cnt = 1, new_node_cnt = 0;
  386. lnode * ptr = node, ** old_node_arr = {&node}, ** new_node_arr = NULL;
  387. while (old_node_cnt != 0)
  388. {
  389. // get how many nodes have children
  390. // and get those nodes into tmp
  391. bool is_new_par_lvl = false;
  392. for (umax i = 0; i < old_node_cnt; i++)
  393. if (old_node_arr[i] -> CHILD != NULL) {
  394. if (is_new_par_lvl == false)
  395. parent_lvls++; // epik variable to return here
  396. new_node_cnt += count_lnode_childs(old_node_arr[i]);
  397. }
  398. // allocate memory for the new array to be created
  399. new_node_arr = allocate_memory(new_node_cnt, sizeof(lnode *));
  400. if (new_node_arr == NULL) {
  401. free_memory(old_node_arr);
  402. return 0;
  403. }
  404. // add all the child nodes to new_node_arr
  405. for (umax i = 0, arr_pos = 0; i < old_node_cnt; i++)
  406. if (old_node_arr[i] -> CHILD != NULL) {
  407. ptr = old_node_arr[i] -> CHILD;
  408. while (ptr != NULL) {
  409. new_node_arr[arr_pos++] = ptr;
  410. ptr = ptr -> FRONT;
  411. }
  412. }
  413. // setup the variables for the next loop
  414. free_memory(old_node_arr);
  415. old_node_arr = new_node_arr;
  416. new_node_arr = NULL;
  417. old_node_cnt = new_node_cnt;
  418. new_node_cnt = 0;
  419. }
  420. // for the last loop
  421. free_memory(old_node_arr);
  422. // return the result
  423. return parent_lvls;
  424. }
  425. // print_lnode_list()
  426. // not to dissapoint, but this will only print the structure of the list and
  427. // print the intergers relating the type of element contained in each lnode item
  428. umax print_lnode_list(lnode * node)
  429. {
  430. // check params
  431. if (node == NULL)
  432. return 0;
  433. // make a 2 dimensional array so that each row will refer to a single node
  434. // the position of the node in the row will determine its parenting level
  435. // and it can be visually inferred which is the direct parent
  436. // first, I need to count the number of nodes
  437. // after that I need to count the number of parenting levels
  438. // little representation
  439. // just for myself
  440. // number of nodes: 9
  441. // parenting levels: 4
  442. // [1, 0, 0 ,0]
  443. // [0, 1, 0, 0]
  444. // [0, 1, 0, 0]
  445. // [0, 0, 1, 0]
  446. // [1, 0, 0, 0]
  447. // [0, 1, 0, 0]
  448. // [0, 1, 0, 0]
  449. // [0, 0, 1, 0]
  450. // [0, 0, 0, 1]
  451. // allocate memory for the 2 dimensional array
  452. umax node_cnt = count_lnodes(node), parent_lvls = count_lnodes_parent_lvls(node);
  453. umax * node_diag = allocate_memory(sizeof(umax), node_cnt * parent_lvls);
  454. // ^ node_diag[node row][parent column]
  455. // analize the nodes at the same parenting level and then move to the next level
  456. lnode * ptr = node;
  457. umax old_smlvl_cnt = count_lnode_fronts(node) + 1,
  458. new_smlvl_cnt = 0;
  459. umax cur_node_pos = 0,
  460. cur_par_lvl = 0;
  461. lnode ** old_node_arr = allocate_memory(sizeof(lnode *), old_smlvl_cnt),
  462. ** new_node_arr = NULL;
  463. umax * old_node_pos = allocate_memory(sizeof(umax), old_smlvl_cnt),
  464. * new_node_pos = NULL;
  465. // add all the nodes at the same level to old_node_arr
  466. // and also, get their respective position on node_diag
  467. for (umax i = 0; i < old_smlvl_cnt; i++) {
  468. old_node_arr[i] = ptr;
  469. old_node_pos[i] = cur_node_pos;
  470. if (ptr -> CHILD != NULL)
  471. cur_node_pos += count_lnodes(ptr -> CHILD) + 1;
  472. else
  473. cur_node_pos++;
  474. ptr = ptr -> FRONT;
  475. }
  476. // start the loop
  477. while (old_smlvl_cnt != 0)
  478. {
  479. // put each node in its position on node_diag
  480. for (umax i = 0; i < old_smlvl_cnt; i++) {
  481. ptr = old_node_arr[i];
  482. node_diag[(old_node_pos[i] * parent_lvls) + cur_par_lvl] = ptr -> TYPE;
  483. // count the childs to be added for the next parenting level
  484. new_smlvl_cnt += count_lnode_childs(ptr);
  485. cur_node_pos += count_lnodes(ptr);
  486. }
  487. // allocate memory for the next level of nodes
  488. // node array
  489. new_node_arr = allocate_memory(sizeof(lnode *), new_smlvl_cnt);
  490. if (new_node_arr == NULL) {
  491. free_memory(old_node_arr);
  492. return 0;
  493. }
  494. // node position array
  495. new_node_pos = allocate_memory(sizeof(umax), new_smlvl_cnt);
  496. if (new_node_pos == NULL) {
  497. free_memory(new_node_arr);
  498. free_memory(old_node_arr);
  499. return 0;
  500. }
  501. // get the new nodes and their position for the next loop
  502. for (umax i = 0, node_pos_index = 0; i < old_smlvl_cnt; i++)
  503. {
  504. ptr = old_node_arr[i] -> CHILD;
  505. if (ptr != NULL) {
  506. cur_node_pos = old_node_pos[i] + 1;
  507. while (ptr != NULL) {
  508. new_node_arr[node_pos_index] = ptr;
  509. new_node_pos[node_pos_index] = cur_node_pos;
  510. node_pos_index++;
  511. if (ptr -> CHILD != NULL)
  512. cur_node_pos += count_lnodes(ptr -> CHILD) + 1;
  513. else
  514. cur_node_pos++;
  515. ptr = ptr -> FRONT;
  516. }
  517. }
  518. }
  519. // setup the variables for the next loop
  520. free_memory(old_node_arr);
  521. old_node_arr = new_node_arr;
  522. new_node_arr = NULL;
  523. free_memory(old_node_pos);
  524. old_node_pos = new_node_pos;
  525. new_node_pos = NULL;
  526. old_smlvl_cnt = new_smlvl_cnt;
  527. new_smlvl_cnt = 0;
  528. cur_par_lvl++;
  529. }
  530. // for the last loop
  531. free_memory(old_node_arr);
  532. free_memory(old_node_pos);
  533. // print the node diagram (finally)
  534. printf("\nList node diagram:\n");
  535. for (umax i = 0; i < node_cnt; i++) {
  536. printf("[");
  537. for (umax j = 0; j < parent_lvls - 1; j++)
  538. printf("%2llu, ", node_diag[(i * parent_lvls) + j]);
  539. printf("%2llu]\n", node_diag[(i * parent_lvls) + parent_lvls - 1]);
  540. }
  541. // done!
  542. free_memory(node_diag);
  543. return node_cnt;
  544. }
  545. // find_lnode_index() function
  546. // function to find lnode at an index position respect to the current node
  547. lnode * find_lnode(lnode * node, lnode_dir dir, umax index)
  548. {
  549. // check params
  550. if (node == NULL || dir == LNODE_DIR_NO_DIR)
  551. return NULL;
  552. // reuse the functions from above
  553. if (dir == LNODE_DIR_FRONT)
  554. return find_lnode_front(node, index);
  555. else if (dir == LNODE_DIR_BEHIND)
  556. return find_lnode_behind(node, index);
  557. else if (dir == LNODE_DIR_PARENT)
  558. return find_lnode_parent(node, index);
  559. else if (dir == LNODE_DIR_CHILD)
  560. return find_lnode_child(node, index);
  561. // huh?
  562. return NULL;
  563. }