fork(1) download
  1. /*
  2.  * Because we are using the kindly-provided services of
  3.  * http://i...content-available-to-author-only...e.com , we mush together three separate
  4.  * files using some preprocessor tricks. The files are
  5.  * identified individually so that you can copy and paste
  6.  * them into their own files, if you so choose. The
  7.  * stuff that only matters for this http://i...content-available-to-author-only...e.com
  8.  * paste is every line that contains the text
  9.  * 'ALL_IN_ONE'. This very comment section is also not
  10.  * part of the three files
  11.  */
  12.  
  13. #ifndef MULDIM_TEST_C_ /* ALL_IN_ONE */
  14. #define MULDIM_TEST_C_ /* ALL_IN_ONE */
  15.  
  16.  
  17.  
  18. /**** muldim_test.c - Shao Miller, April 4th, 2012 */
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22.  
  23. #if 0 /* ALL_IN_ONE */
  24. #include "muldim.h"
  25. #else /* ALL_IN_ONE */
  26. #include "prog.c" /* ALL_IN_ONE */
  27. #endif /* ALL_IN_ONE */
  28.  
  29. /*** Macros */
  30. #define CountOf(array) (sizeof (array) / sizeof *(array))
  31.  
  32. int main(void) {
  33. int result;
  34. muldim_t arr;
  35. muldim_t end;
  36. int test[2][3][4];
  37. int i, j, k, * ip;
  38.  
  39. /* Assume failure */
  40. result = EXIT_FAILURE;
  41.  
  42. /* Same dimensions as 'test' */
  43. arr = muldim_zalloc(sizeof (int), 3, 2, 3, 4);
  44. if (!arr.ptr) {
  45. goto err_arr;
  46. }
  47.  
  48. muldim_dmp(arr);
  49.  
  50. end = muldim_get(arr, 3, 1, 2, 4);
  51. if (!end.ptr) {
  52. goto err_end;
  53. }
  54.  
  55. muldim_dmp(end);
  56.  
  57. "(\n"
  58. " (char *) (test[1][2] + 4) -\n"
  59. " (char *) test[0][0]\n"
  60. " ) == %d\n",
  61. (
  62. (char *) (test[1][2] + 4) -
  63. (char *) test[0][0]
  64. )
  65. );
  66.  
  67. "(\n"
  68. " (char *) end.ptr -\n"
  69. " (char *) arr.ptr\n"
  70. " ) == %d\n",
  71. (
  72. (char *) end.ptr -
  73. (char *) arr.ptr
  74. )
  75. );
  76.  
  77. /* Same dimensions as 'test' */
  78. for (i = 0; i < CountOf(test); ++i) {
  79. for (j = 0; j < CountOf(test[0]); ++j) {
  80. ip = muldim_get(arr, 2, i, j).ptr;
  81. for (k = 0; k < CountOf(test[0][0]); ++k) {
  82. if (ip[k]) {
  83. printf("muldim_zalloc failed!\n");
  84. goto err_nonzero;
  85. }
  86. ip[k] = 42;
  87. continue;
  88. }
  89. continue;
  90. }
  91. continue;
  92. }
  93.  
  94. /* Success */
  95. printf("Yay\n");
  96. result = EXIT_SUCCESS;
  97.  
  98. err_nonzero:
  99.  
  100. err_end:
  101.  
  102. free(arr.mem);
  103. err_arr:
  104.  
  105. return result;
  106. }
  107.  
  108.  
  109.  
  110. #else /* ALL_IN_ONE */
  111.  
  112.  
  113.  
  114. /**** muldim.h - Shao Miller, April 4th, 2012 */
  115.  
  116. #ifndef MULDIM_H_
  117.  
  118. #include <stddef.h>
  119.  
  120. /*** Macros */
  121. #define MULDIM_H_
  122.  
  123. /*** Object types */
  124.  
  125. typedef struct s_muldim s_muldim, muldim_t;
  126.  
  127. /*** Struct/union definitions */
  128.  
  129. struct s_muldim {
  130. void * ptr;
  131. size_t dims;
  132. size_t stride;
  133. size_t * dims_at;
  134. void * mem;
  135. };
  136.  
  137. /*** Function declarations */
  138.  
  139. extern muldim_t muldim_alloc(size_t base_sz, size_t dims, ...);
  140. extern muldim_t muldim_zalloc(size_t base_sz, size_t dims, ...);
  141. extern muldim_t muldim_get(muldim_t muldim, size_t dims, ...);
  142. extern void muldim_dmp(muldim_t muldim);
  143.  
  144. #endif /* MULDIM_H_ */
  145.  
  146.  
  147.  
  148. /**** muldim.c - Shao Miller, April 4th, 2012 */
  149.  
  150. #include <stddef.h>
  151. #include <stdarg.h>
  152. #include <stdlib.h>
  153. #include <stdio.h>
  154.  
  155. #if 0 /* ALL_IN_ONE */
  156. #include "muldim.h"
  157. #endif /* ALL_IN_ONE */
  158.  
  159. /*** Function declarations */
  160.  
  161. static size_t sz_add(size_t x, size_t y);
  162. static size_t sz_mul(size_t x, size_t y);
  163.  
  164. /*** Struct/union definitions */
  165.  
  166. struct s_muldim_wrapper {
  167. muldim_t muldim;
  168. size_t dims_hdr[1];
  169. };
  170.  
  171. /*** Object definitions */
  172. static const muldim_t new_muldim;
  173.  
  174. /*** Function definitions */
  175.  
  176. muldim_t muldim_alloc(size_t base_sz, size_t dims, ...) {
  177. register const size_t dims_offset = offsetof(
  178. struct s_muldim_wrapper,
  179. dims_hdr
  180. );
  181. muldim_t result;
  182. size_t dims_sz;
  183. size_t hdr_sz;
  184. va_list vargs;
  185. size_t array_sz;
  186. size_t i;
  187. int dim;
  188. size_t total_sz;
  189. char * ptr;
  190. size_t * dims_at;
  191.  
  192. result = new_muldim;
  193.  
  194. if (!base_sz) {
  195. goto err_base_sz;
  196. }
  197.  
  198. dims_sz = sz_mul(dims, sizeof result.dims_at[0]);
  199. if (!dims_sz) {
  200. goto err_dims_sz;
  201. }
  202.  
  203. hdr_sz = sz_add(dims_offset, dims_sz);
  204. if (!hdr_sz) {
  205. goto err_hdr_sz;
  206. }
  207. hdr_sz = sz_add(base_sz, hdr_sz);
  208. if (!hdr_sz) {
  209. goto err_hdr_sz;
  210. }
  211. hdr_sz = hdr_sz - 1;
  212. hdr_sz = hdr_sz / base_sz;
  213. hdr_sz = hdr_sz * base_sz;
  214.  
  215. va_start(vargs, dims);
  216. array_sz = base_sz;
  217. for (i = dims; i; --i) {
  218. dim = va_arg(vargs, int);
  219. if (dim < 1) {
  220. goto err_dim;
  221. }
  222.  
  223. array_sz = sz_mul(array_sz, (size_t) dim);
  224. if (!array_sz) {
  225. goto err_array_sz;
  226. }
  227.  
  228. continue;
  229. }
  230. va_end(vargs);
  231.  
  232. total_sz = sz_add(hdr_sz, array_sz);
  233. if (!total_sz) {
  234. goto err_total_sz;
  235. }
  236.  
  237. ptr = malloc(total_sz);
  238. if (!ptr) {
  239. goto err_ptr;
  240. }
  241.  
  242. /* Success */
  243.  
  244. dims_at = (void *) (ptr + dims_offset);
  245.  
  246. va_start(vargs, dims);
  247. for (i = 0; i < dims; ++i) {
  248. dim = va_arg(vargs, int);
  249. dims_at[i] = (size_t) dim;
  250.  
  251. continue;
  252. }
  253. va_end(vargs);
  254.  
  255. result.ptr = ptr + hdr_sz;
  256. result.dims = dims;
  257. result.stride = array_sz;
  258. result.dims_at = dims_at;
  259. result.mem = ptr;
  260.  
  261. *(muldim_t *) ptr = result;
  262. return result;
  263.  
  264. free(ptr);
  265. err_ptr:
  266.  
  267. err_total_sz:
  268.  
  269. err_array_sz:
  270.  
  271. err_dim:
  272.  
  273. err_hdr_sz:
  274.  
  275. err_dims_sz:
  276.  
  277. err_base_sz:
  278.  
  279. return result;
  280. }
  281.  
  282. muldim_t muldim_zalloc(size_t base_sz, size_t dims, ...) {
  283. register const size_t dims_offset = offsetof(
  284. struct s_muldim_wrapper,
  285. dims_hdr
  286. );
  287. muldim_t result;
  288. size_t dims_sz;
  289. size_t hdr_sz;
  290. va_list vargs;
  291. size_t array_sz;
  292. size_t i;
  293. int dim;
  294. size_t total_sz;
  295. char * ptr;
  296. size_t * dims_at;
  297.  
  298. result = new_muldim;
  299.  
  300. if (!base_sz) {
  301. goto err_base_sz;
  302. }
  303.  
  304. dims_sz = sz_mul(dims, sizeof result.dims_at[0]);
  305. if (!dims_sz) {
  306. goto err_dims_sz;
  307. }
  308.  
  309. hdr_sz = sz_add(dims_offset, dims_sz);
  310. if (!hdr_sz) {
  311. goto err_hdr_sz;
  312. }
  313. hdr_sz = sz_add(base_sz, hdr_sz);
  314. if (!hdr_sz) {
  315. goto err_hdr_sz;
  316. }
  317. hdr_sz = hdr_sz - 1;
  318. hdr_sz = hdr_sz / base_sz;
  319. hdr_sz = hdr_sz * base_sz;
  320.  
  321. va_start(vargs, dims);
  322. array_sz = base_sz;
  323. for (i = dims; i; --i) {
  324. dim = va_arg(vargs, int);
  325. if (dim < 1) {
  326. goto err_dim;
  327. }
  328.  
  329. array_sz = sz_mul(array_sz, (size_t) dim);
  330. if (!array_sz) {
  331. goto err_array_sz;
  332. }
  333.  
  334. continue;
  335. }
  336. va_end(vargs);
  337.  
  338. total_sz = sz_add(hdr_sz, array_sz);
  339. if (!total_sz) {
  340. goto err_total_sz;
  341. }
  342.  
  343. total_sz = total_sz / base_sz;
  344. ptr = calloc(total_sz, base_sz);
  345. if (!ptr) {
  346. goto err_ptr;
  347. }
  348.  
  349. /* Success */
  350.  
  351. dims_at = (void *) (ptr + dims_offset);
  352.  
  353. va_start(vargs, dims);
  354. for (i = 0; i < dims; ++i) {
  355. dim = va_arg(vargs, int);
  356. dims_at[i] = (size_t) dim;
  357.  
  358. continue;
  359. }
  360. va_end(vargs);
  361.  
  362. result.ptr = ptr + hdr_sz;
  363. result.dims = dims;
  364. result.stride = array_sz;
  365. result.dims_at = dims_at;
  366. result.mem = ptr;
  367.  
  368. *(muldim_t *) ptr = result;
  369. return result;
  370.  
  371. free(ptr);
  372. err_ptr:
  373.  
  374. err_total_sz:
  375.  
  376. err_array_sz:
  377.  
  378. err_dim:
  379.  
  380. err_hdr_sz:
  381.  
  382. err_dims_sz:
  383.  
  384. err_base_sz:
  385.  
  386. return result;
  387. }
  388.  
  389. muldim_t muldim_get(muldim_t muldim, size_t dims, ...) {
  390. char * ptr;
  391. va_list vargs;
  392. int dim;
  393.  
  394. if (!dims || dims > muldim.dims) {
  395. goto err_dims;
  396. }
  397.  
  398. ptr = muldim.ptr;
  399. va_start(vargs, dims);
  400. while (dims--) {
  401. dim = va_arg(vargs, int);
  402. if (dim < 0 || dim > muldim.dims_at[0]) {
  403. goto err_dim;
  404. }
  405.  
  406. muldim.stride = muldim.stride / muldim.dims_at[0];
  407. ptr = ptr + muldim.stride * dim;
  408. --muldim.dims;
  409. ++muldim.dims_at;
  410.  
  411. continue;
  412. }
  413. va_end(vargs);
  414.  
  415. /* Success */
  416.  
  417. muldim.ptr = ptr;
  418. return muldim;
  419.  
  420. err_dim:
  421.  
  422. err_dims:
  423.  
  424. return new_muldim;
  425. }
  426.  
  427. void muldim_dmp(muldim_t muldim) {
  428. "ptr == %p\n"
  429. "dims == %u\n"
  430. "stride == %u\n"
  431. "dims_at == %p\n"
  432. "mem == %p\n",
  433. muldim.ptr,
  434. (unsigned int) muldim.dims,
  435. (unsigned int) muldim.stride,
  436. (void *) muldim.dims_at,
  437. muldim.mem
  438. );
  439. printf("dimensions: { ");
  440. while (muldim.dims--) {
  441. printf("%u, ", (unsigned int) muldim.dims_at++[0]);
  442. continue;
  443. }
  444. printf("}\n");
  445. return;
  446. }
  447.  
  448. static size_t sz_add(size_t x, size_t y) {
  449. size_t result;
  450.  
  451. result = x + y;
  452. if (result <= x || result <= y) {
  453. /* Wrap-around */
  454. return 0;
  455. }
  456. return result;
  457. }
  458.  
  459. static size_t sz_mul(size_t x, size_t y) {
  460. size_t result;
  461.  
  462. result = x * y;
  463. if (result <= x || result <= y) {
  464. /* Wrap-around */
  465. return 0;
  466. }
  467. return result;
  468. }
  469.  
  470.  
  471.  
  472. #endif /* ALL_IN_ONE */
Success #stdin #stdout 0.02s 1852KB
stdin
Standard input is empty
stdout
ptr == 0x92db028
dims == 3
stride == 96
dims_at == 0x92db01c
mem == 0x92db008
dimensions: { 2, 3, 4, }
ptr == 0x92db088
dims == 0
stride == 4
dims_at == 0x92db028
mem == 0x92db008
dimensions: { }
(
    (char *) (test[1][2] + 4) -
    (char *) test[0][0]
  ) == 96
(
    (char *) end.ptr -
    (char *) arr.ptr
  ) == 96
Yay