byte_arr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // check pointer
  2. owl_bool owl_check_bytarr_pointer(owl_byte * src, owl_umax size)
  3. {
  4. return (src != NULL && size >= sizeof(owl_bytarr));
  5. }
  6. // check members
  7. owl_bool owl_check_bytarr_members(owl_byte * ptr, owl_umax size)
  8. {
  9. // reuse owl_check_mem_space_members()
  10. return owl_check_mem_space_members(ptr, size);
  11. }
  12. // check all
  13. owl_bool owl_check_bytarr_all(owl_bytarr * data, owl_umax size)
  14. {
  15. return owl_check_bytarr_pointer((void *) data, size)
  16. && owl_check_bytarr_members(data -> ptr, data -> size);
  17. }
  18. // create a bytarr structure
  19. owl_bytarr * owl_create_bytarr(owl_byte * data, owl_umax size)
  20. {
  21. // check parameters (only the size)
  22. if (size == 0)
  23. return NULL;
  24. // otherwise create the structure
  25. owl_bytarr * rtn = (owl_bytarr *) owl_create_mem_space(size);
  26. if (data != NULL) // copy the bytes from data into the structure
  27. for (owl_umax i = 0; i < size; i++)
  28. (rtn -> ptr)[i] = data[i];
  29. return rtn;
  30. }
  31. // function to free a bytarr structure
  32. owl_umax owl_free_bytarr(owl_bytarr * arr)
  33. {
  34. // check params
  35. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false)
  36. return 0;
  37. return owl_free_mem_space((owl_mem_space *) arr);
  38. }
  39. // function to print a bytarr structure
  40. owl_umax owl_print_bytarr(owl_byte * src, owl_umax size)
  41. {
  42. // check params
  43. printf("OWL_BYTARR struct info:\n");
  44. printf(" Struct info: %p, %llu\n", src, size);
  45. if (owl_check_bytarr_pointer(src, size) == owl_false)
  46. return 0;
  47. // otherwise print the contents of the bytarr
  48. owl_bytarr * arr = (void *) src;
  49. printf(" Array pointer: %p\n", arr -> ptr);
  50. printf(" Array size (bytes): %llu\n", arr -> size);
  51. printf(" Array contents (hex): ");
  52. for (owl_umax i = 0; i < (arr -> size); i++) {
  53. //~ owl_print_char_char((arr -> ptr) + i, (arr -> size) - i);
  54. owl_print_byte_hex((arr -> ptr) + i, (arr -> size) - i);
  55. putchar(' ');
  56. }
  57. putchar('\n');
  58. return sizeof(owl_bytarr);
  59. }
  60. // compare 2 bytarrs
  61. owl_char owl_comp_bytarr(owl_byte * arr1, owl_byte * arr2)
  62. {
  63. // check params
  64. owl_bytarr * arr1_tmp = (void *) arr1,
  65. * arr2_tmp = (void *) arr2;
  66. // check params
  67. if (owl_check_bytarr_all(arr1_tmp, sizeof(owl_bytarr)) == owl_false
  68. || owl_check_bytarr_all(arr2_tmp, sizeof(owl_bytarr)) == owl_false)
  69. return owl_comp_err;
  70. // do the comparison, size and byte contents matter
  71. // size has higher meaning than byte content
  72. // size
  73. if (arr1_tmp -> size < arr2_tmp -> size)
  74. return owl_comp_less;
  75. else if (arr1_tmp -> size > arr2_tmp -> size)
  76. return owl_comp_greater;
  77. // byte comparison if sizes are equal
  78. // first byte comparison to trigger the < or > expressions
  79. for (owl_umax i = 0; i < arr1_tmp -> size; i++) {
  80. if ((arr1_tmp -> ptr)[i] < (arr2_tmp -> ptr)[i])
  81. return owl_comp_less;
  82. else if ((arr1_tmp -> ptr)[i] > (arr2_tmp -> ptr)[i])
  83. return owl_comp_greater;
  84. }
  85. // legit real equal bytarrs
  86. return owl_comp_equal;
  87. }
  88. // function to copy a bytarr into another bytarr
  89. owl_bytarr owl_copy_bytarr(owl_bytarr * src, owl_bytarr * dest)
  90. {
  91. // check params
  92. if (owl_check_bytarr_all(src, sizeof(owl_bytarr)) == owl_false
  93. || owl_check_bytarr_all(dest, sizeof(owl_bytarr)) == owl_false
  94. || (src -> size) > (dest -> size))
  95. return (owl_bytarr) {NULL, 0};
  96. // copy the byte contents of a bytarr into the other
  97. for (owl_umax i = 0; i < src -> size; i++)
  98. (dest -> ptr)[i] = (src -> ptr)[i];
  99. // return the last write position on dest as a bytarr struct
  100. return (owl_bytarr) {(dest -> ptr) + (src -> size),
  101. (dest -> size) - (src -> size)};
  102. }
  103. // get the integer index at which 2 bytarrs start not being equal
  104. owl_umax owl_get_bytarr_mismatch_index(owl_bytarr * arr1, owl_bytarr * arr2)
  105. {
  106. // check params (arr1 -> size will be used for error checking)
  107. if (owl_check_bytarr_all(arr1, sizeof(owl_bytarr)) == owl_false
  108. || owl_check_bytarr_all(arr2, sizeof(owl_bytarr)) == owl_false)
  109. return arr1 -> size;
  110. // else do comparisons until a mismatch
  111. // get max bytarr size
  112. owl_umax low_size = arr1 -> size < arr2 -> size ? arr1 -> size : arr2 -> size;
  113. for (owl_umax i = 0; i < low_size; i++)
  114. if ((arr1 -> ptr)[i] != (arr2 -> ptr)[i])
  115. return i;
  116. // in case the tiniest bytarr is contained within the larger one
  117. return arr1 -> size;
  118. }
  119. // function to ignore certain types of bytes from a bytarr and
  120. // return the position in which there are no more bytes to skip
  121. owl_bytarr owl_ignore_bytarr_bytes(owl_bytarr * arr, owl_bytarr * skip)
  122. {
  123. // check params (arr -> size will be used for error checking)
  124. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  125. || owl_check_bytarr_all(skip, sizeof(owl_bytarr)) == owl_false)
  126. return (owl_bytarr) {NULL, 0};
  127. // otherwise, return the integer index
  128. owl_bool keep_skipping = owl_false;
  129. for (owl_umax i = 0; i < arr -> size; i++)
  130. {
  131. // compare i's element from arr with all the elements from skip
  132. for (owl_umax j = 0; j < skip -> size; j++)
  133. keep_skipping = keep_skipping || ((arr -> ptr)[i] == (skip -> ptr)[j]);
  134. // if none of the bytes from skip matches the i's byte from arr the return the i index
  135. if (keep_skipping == owl_false)
  136. return (owl_bytarr) {arr -> ptr + i, arr -> size - i};
  137. // otherwise, reset the boolean
  138. keep_skipping = owl_false;
  139. }
  140. // in case all the bytes from arr can be found in skip
  141. return (owl_bytarr) {NULL, 0};
  142. }
  143. // function to search if a bytarr is found inside another one
  144. owl_bytarr owl_search_bytarr(owl_bytarr * src, owl_bytarr * search)
  145. {
  146. // check params (src -> size will be used for error checking)
  147. if (owl_check_bytarr_all(src, sizeof(owl_bytarr)) == owl_false
  148. || owl_check_bytarr_all(search, sizeof(owl_bytarr)) == owl_false
  149. || src -> size < search -> size)
  150. goto err;
  151. // use owl_comp_bytarr() until a match is found
  152. owl_bytarr tmp = {src -> ptr, search -> size};
  153. for (owl_umax i = 0; i <= (src -> size - search -> size); i++) {
  154. // return the i index when a match is found
  155. owl_bool cmp = owl_comp_bytarr((void *) &tmp, (void *) search);
  156. if (cmp == owl_comp_equal)
  157. return (owl_bytarr) {src -> ptr + i, src -> size - i};
  158. else if (cmp == owl_comp_err)
  159. goto err;
  160. else
  161. (tmp.ptr)++;
  162. }
  163. // no match found
  164. err:
  165. return (owl_bytarr) {NULL, 0};
  166. }
  167. // function to reverse the bytes in a bytarr
  168. owl_umax owl_reverse_bytarr(owl_bytarr * arr)
  169. {
  170. // check params
  171. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false)
  172. return 0;
  173. // reverse the bytes
  174. owl_umax middle_pos = arr -> size / 2;
  175. for (owl_umax i = 0, tmp = 0; i < middle_pos; i++) {
  176. tmp = (arr -> ptr)[i];
  177. (arr -> ptr)[i] = (arr -> ptr)[arr -> size - i - 1];
  178. (arr -> ptr)[arr -> size - i - 1] = tmp;
  179. }
  180. // reverse op was done (return the number of bytes moved)
  181. return arr -> size;
  182. }
  183. // check if a byteshift integer is valid
  184. owl_bool owl_check_byteshift_dir(owl_byteshift_dir shift)
  185. {
  186. return (shift == OWL_BYTESHIFT_LEFT || shift == OWL_BYTESHIFT_RIGHT);
  187. }
  188. // make a simple shift on the bytes of data
  189. owl_umax owl_bytarr_shift(owl_bytarr * arr, owl_byteshift_dir shift)
  190. {
  191. // check params
  192. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  193. || owl_check_byteshift_dir(shift) == owl_false)
  194. return 0;
  195. // decide the byteshift direction
  196. owl_char increment = 1;
  197. owl_umax arr_index = 0;
  198. if (shift == OWL_BYTESHIFT_LEFT) {
  199. increment = -1;
  200. arr_index = arr -> size - 1;
  201. }
  202. // do the byteshift
  203. owl_byte tmp1 = 0, tmp2 = 0;
  204. for (owl_umax i = 0; i < arr -> size; i++) {
  205. tmp1 = (arr -> ptr)[arr_index];
  206. (arr -> ptr)[arr_index] = tmp2;
  207. tmp2 = tmp1;
  208. arr_index += increment;
  209. }
  210. // return the number of bytes read
  211. return arr -> size;
  212. }
  213. // just call owl_bytarr_shift() n times
  214. owl_umax owl_bytarr_n_shift(owl_bytarr * arr, owl_byteshift_dir shift, owl_umax n)
  215. {
  216. // check params
  217. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  218. || owl_check_byteshift_dir(shift) == owl_false
  219. || n == 0)
  220. return 0;
  221. // do the byteshift
  222. owl_umax tmp = n;
  223. while (n-- != 0)
  224. owl_bytarr_shift(arr, shift);
  225. return tmp * (arr -> size);
  226. }
  227. // function to do a circular byteshift on a bytarr
  228. owl_umax owl_bytarr_circ_shift(owl_bytarr * arr, owl_byteshift_dir shift)
  229. {
  230. // check params
  231. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  232. || owl_check_byteshift_dir(shift) == owl_false)
  233. return 0;
  234. // get the byte that will get lost after a call to owl_bytarr_shift
  235. owl_byte tmp = (arr -> ptr)[arr -> size - 1];
  236. if (shift == OWL_BYTESHIFT_LEFT)
  237. tmp = (arr -> ptr)[0];
  238. // do the byteshift
  239. owl_bytarr_shift(arr, shift);
  240. // place the byte where it should be after the circular shift
  241. if (shift == OWL_BYTESHIFT_RIGHT)
  242. (arr -> ptr)[0] = tmp;
  243. else
  244. (arr -> ptr)[arr -> size - 1] = tmp;
  245. // return the number of bytes read
  246. return arr -> size;
  247. }
  248. // function to call n times owl_bytarr_circ_shift()
  249. owl_umax owl_bytarr_n_circ_shift(owl_bytarr * arr, owl_byteshift_dir shift, owl_umax n)
  250. {
  251. // check params
  252. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  253. || owl_check_byteshift_dir(shift) == owl_false
  254. || n == 0)
  255. return 0;
  256. // do the circular byteshift
  257. owl_umax tmp = n;
  258. while (n-- != 0)
  259. owl_bytarr_circ_shift(arr, shift);
  260. return tmp * (arr -> size);
  261. }
  262. // function to insert a bytarr inside another one
  263. owl_bytarr * owl_ins_bytarr(owl_bytarr * arr, owl_umax arr_ins_pos, owl_bytarr * insert)
  264. {
  265. // check params
  266. owl_bytarr * new = NULL;
  267. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  268. || arr_ins_pos > arr -> size
  269. || owl_check_bytarr_all(insert, sizeof(owl_bytarr)) == owl_false)
  270. goto err;
  271. // otherwise allocate memory for the new array
  272. new = owl_create_bytarr(NULL, arr -> size + insert -> size);
  273. if (new == NULL)
  274. goto err;
  275. // copy the contents from arr into new until arr_ins_pos
  276. // then copy the insert byte data and after copy the rest of the bytes on arr
  277. owl_bytarr tmp1 = *arr, tmp2 = *arr;
  278. // consider the case in which insertion occurs at the very beginning
  279. if (arr_ins_pos != 0) {
  280. tmp1.size = arr_ins_pos;
  281. tmp1 = owl_copy_bytarr(&tmp1, new);
  282. if (tmp1.ptr == NULL)
  283. goto err;
  284. }
  285. else
  286. tmp1 = *new;
  287. // insert the bytes
  288. tmp1 = owl_copy_bytarr(insert, &tmp1);
  289. if (tmp1.ptr == NULL)
  290. goto err;
  291. // consider the case in which the bytes are added at the very end
  292. if (arr_ins_pos != arr -> size) {
  293. tmp2.ptr += arr_ins_pos;
  294. tmp2.size = tmp1.size;
  295. tmp1 = owl_copy_bytarr(&tmp2, &tmp1);
  296. if (tmp1.ptr == NULL)
  297. goto err;
  298. }
  299. // all done, return the new structure
  300. return new;
  301. err:
  302. // free the allocated memory if something wrong happens
  303. owl_free_bytarr(new);
  304. return NULL;
  305. }
  306. // function to remove bytes from a bytarr
  307. owl_umax owl_rm_bytarr(owl_bytarr * arr, owl_umax rm_pos, owl_umax rm_size)
  308. {
  309. // check params
  310. if (owl_check_bytarr_all(arr, sizeof(owl_bytarr)) == owl_false
  311. || rm_size == 0 || rm_size > arr -> size - (rm_pos + 1))
  312. return 0;
  313. // use bytarr_shift to remove the unwanted bytes
  314. owl_bytarr tmp = {arr -> ptr + rm_pos, arr -> size - (rm_pos + 1)};
  315. owl_bytarr_n_shift(&tmp, OWL_BYTESHIFT_LEFT, rm_size);
  316. return (arr -> size -= rm_size);
  317. }