arr.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // check pointer
  2. owl_bool owl_check_arr_pointer(owl_byte * src, owl_umax size)
  3. {
  4. return (src != NULL && size >= sizeof(owl_arr));
  5. }
  6. // check members
  7. owl_bool owl_check_arr_members(owl_byte * ptr, owl_umax arr_size, owl_type type, owl_umax var_size,
  8. owl_umax (* print_elem)(owl_byte *, owl_umax size),
  9. owl_char (* comp_elem)(owl_byte *, owl_byte *))
  10. {
  11. return (ptr != NULL && arr_size != 0 && type != OWL_TYPE_NONE
  12. && var_size != 0 && print_elem != NULL && comp_elem != NULL);
  13. }
  14. // check all
  15. owl_bool owl_check_arr_all(owl_arr * data, owl_umax size)
  16. {
  17. return owl_check_arr_pointer((void *) data, size)
  18. && owl_check_arr_members(data -> arr -> ptr, data -> arr -> size,
  19. data -> var.type, data -> var.size,
  20. data -> var.print_elem, data -> var.comp_elem);
  21. }
  22. // create
  23. owl_arr * owl_create_arr(owl_byte * data, owl_umax arr_size, owl_type type, owl_umax var_size,
  24. owl_umax (* print_elem)(owl_byte *, owl_umax size),
  25. owl_char (* comp_elem)(owl_byte *, owl_byte *))
  26. {
  27. // check params
  28. owl_arr * arr = NULL;
  29. owl_mem_space * mem_space = NULL;
  30. if (owl_check_arr_members(data, arr_size, type, var_size, print_elem, comp_elem) == owl_false)
  31. goto err;
  32. // create the structure
  33. // it will need 2 allocations:
  34. // - one for the structure itself
  35. // - the other one for the mem_space inside the struct
  36. arr = (void *) (owl_create_mem_space(sizeof(owl_arr)) -> ptr);
  37. if (arr == NULL)
  38. goto err;
  39. mem_space = (owl_mem_space *) owl_create_bytarr(data, arr_size * var_size);
  40. if (mem_space == NULL)
  41. goto err;
  42. // assign the rest of the variables
  43. arr -> arr = mem_space;
  44. arr -> var.type = type;
  45. arr -> var.size = var_size;
  46. arr -> var.print_elem = print_elem;
  47. arr -> var.comp_elem = comp_elem;
  48. return arr; // first time returning such a weird struct
  49. // error
  50. err:
  51. ;
  52. owl_free_mem_space(&((owl_mem_space) {(void *) arr, sizeof(owl_arr)}));
  53. owl_free_mem_space(mem_space);
  54. return NULL;
  55. }
  56. // free
  57. owl_umax owl_free_arr(owl_arr * arr)
  58. {
  59. // check params
  60. if (owl_check_arr_all((void *) arr, sizeof(owl_arr)) == owl_false)
  61. goto err;
  62. // free the memory allocated by the struct
  63. owl_umax tmp = owl_free_mem_space(arr -> arr);
  64. if (tmp == 0)
  65. goto err;
  66. owl_mem_space sp = {(void *) arr, sizeof(owl_arr)};
  67. tmp = owl_free_mem_space(&sp);
  68. if (tmp == 0)
  69. goto err;
  70. // return the number of free slots on the mem_space table
  71. return tmp;
  72. err:
  73. return 0;
  74. }
  75. // print
  76. owl_umax owl_print_arr(owl_byte * src, owl_umax size)
  77. {
  78. // check params
  79. printf("OWL_ARR struct info:\n");
  80. printf(" Struct info: %p, %d\n", src, size);
  81. if (owl_check_arr_pointer(src, size) == owl_false)
  82. return 0;
  83. // else print the structure
  84. owl_arr * arr = (void *) src;
  85. printf(" Variable type: %u\n", arr -> var.type);
  86. printf(" Variable size (bytes): %llu\n", arr -> var.size);
  87. printf(" Print function: %p\n", arr -> var.print_elem);
  88. printf(" Compare function: %p\n", arr -> var.comp_elem);
  89. printf(" Array pointer: %p\n", arr -> arr -> ptr);
  90. printf(" Array size (bytes): %llu\n", arr -> arr -> size);
  91. printf(" Array contents: ");
  92. for (owl_umax i = 0; i < (arr -> arr -> size); i += arr -> var.size) {
  93. arr -> var.print_elem((arr -> arr -> ptr) + i, (arr -> arr -> size) - i);
  94. putchar(' ');
  95. }
  96. putchar('\n');
  97. return sizeof(owl_arr);
  98. }
  99. // compare
  100. owl_char owl_comp_arr(owl_byte * arr1, owl_byte * arr2)
  101. {
  102. // check params
  103. owl_arr * arr1_tmp = (void *) arr1,
  104. * arr2_tmp = (void *) arr2;
  105. // check params
  106. if (owl_check_arr_all(arr1_tmp, sizeof(owl_arr)) == owl_false
  107. || owl_check_arr_all(arr2_tmp, sizeof(owl_arr)) == owl_false)
  108. return owl_comp_err;
  109. // do the comparison, size and element contents matter
  110. // arr size -> var size -> var type -> element content
  111. // arr size
  112. if (arr1_tmp -> arr -> size < arr2_tmp -> arr -> size)
  113. return owl_comp_less;
  114. else if (arr1_tmp -> arr -> size > arr2_tmp -> arr -> size)
  115. return owl_comp_greater;
  116. // var size
  117. if (arr1_tmp -> var.size < arr2_tmp -> var.size)
  118. return owl_comp_less;
  119. else if (arr1_tmp -> var.size > arr2_tmp -> var.size)
  120. return owl_comp_greater;
  121. // var type
  122. if (arr1_tmp -> var.type < arr2_tmp -> var.type)
  123. return owl_comp_less;
  124. else if (arr1_tmp -> var.type > arr2_tmp -> var.type)
  125. return owl_comp_greater;
  126. // element comparison if types are equal
  127. // first element comparison to trigger the < or > expressions
  128. for (owl_umax i = 0; i < arr1_tmp -> arr -> size; i += arr1_tmp -> var.size) {
  129. owl_bool tmp_bool = arr1_tmp -> var.comp_elem(arr1_tmp -> arr -> ptr + i, arr2_tmp -> arr -> ptr + i);
  130. if (tmp_bool == owl_comp_less || tmp_bool == owl_comp_greater)
  131. return tmp_bool;
  132. }
  133. // legit real equal arrays
  134. return owl_comp_equal;
  135. }
  136. // reverse the contents of an array
  137. owl_umax owl_reverse_arr(owl_arr * arr)
  138. {
  139. // check params
  140. if (owl_check_arr_all(arr, sizeof(owl_arr)) == owl_false)
  141. return 0;
  142. // else do the reversing process
  143. owl_bytarr * tmp = owl_create_bytarr(NULL, arr -> var.size);
  144. owl_bytarr tmp1 = {arr -> arr -> ptr, arr -> var.size},
  145. tmp2 = {arr -> arr -> ptr + arr -> arr -> size - (arr -> var.size), arr -> var.size};
  146. if (tmp -> ptr == NULL)
  147. return 0;
  148. owl_umax middle_pos = (arr -> arr -> size / arr -> var.size) / 2;
  149. for (owl_umax i = 0; i < middle_pos; i++) {
  150. owl_copy_bytarr(&tmp1, tmp);
  151. owl_copy_bytarr(&tmp2, &tmp1);
  152. owl_copy_bytarr(tmp, &tmp2);
  153. tmp1.ptr += arr -> var.size;
  154. tmp2.ptr -= arr -> var.size;
  155. }
  156. // return the number of bytes moved
  157. owl_free_bytarr(tmp);
  158. return arr -> arr -> size;
  159. }
  160. // find an element inside an array
  161. owl_byte * owl_find_arr_elem(owl_arr * arr, owl_byte * elem, owl_umax size)
  162. {
  163. // check params
  164. if (owl_check_arr_all(arr, sizeof(owl_arr)) == owl_false
  165. || elem == NULL || size == 0 || size < arr -> var.size)
  166. return NULL;
  167. // find the element
  168. for (owl_umax i = 0; i < arr -> arr -> size; i += arr -> var.size)
  169. if ((arr -> var.comp_elem(arr -> arr -> ptr + i, elem)) == owl_comp_equal)
  170. return arr -> arr -> ptr + i;
  171. // not found
  172. return NULL;
  173. }