/api_bson.c

http://github.com/gerald-lindsly/mongo-matlab-driver · C · 780 lines · 621 code · 117 blank · 42 comment · 155 complexity · 5b74da7f55e728f7ae07163fddeed3d3 MD5 · raw file

  1. /** Copyright 2009-2011 10gen Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "MongoMatlabDriver.h"
  16. #include "bson.h"
  17. #include <malloc.h>
  18. #include <mex.h>
  19. #define MAXDIM 20
  20. const char* numstr(int i) {
  21. extern const char bson_numstrs[1000][4];
  22. if (i < 1000)
  23. return bson_numstrs[i];
  24. else {
  25. static char s[20];
  26. sprintf(s, "%d", i);
  27. return s;
  28. }
  29. }
  30. EXPORT void mongo_bson_buffer_create(struct bson_buffer** b)
  31. {
  32. bson* _b = (bson*)bson_malloc(sizeof(bson));
  33. bson_init(_b);
  34. *b = (struct bson_buffer*)_b;
  35. }
  36. EXPORT void mongo_bson_buffer_to_bson(struct bson_buffer* b, struct bson_** out) {
  37. bson* _b = (bson*)b;
  38. bson_finish(_b);
  39. *out = (struct bson_*) _b;
  40. //*b = 0;
  41. }
  42. EXPORT void mongo_bson_free(struct bson_* b) {
  43. if (b != NULL) {
  44. bson_destroy((bson*)b);
  45. free(b);
  46. }
  47. }
  48. EXPORT void mongo_bson_buffer_free(struct bson_buffer* b) {
  49. bson_destroy((bson*)b);
  50. free(b);
  51. }
  52. static void reverse(mwSize* p, mwSize len) {
  53. mwSize* q = p + len - 1;
  54. mwSize t;
  55. while (p < q) {
  56. t = *p;
  57. *p = *q;
  58. *q = t;
  59. p++, q--;
  60. }
  61. }
  62. static int mongo_bson_buffer_append_complex(struct bson_buffer* b, const char* name, double r, double i) {
  63. bson* _b = (bson*) b;
  64. return (bson_append_start_object(_b, name) == BSON_OK) &&
  65. (bson_append_double(_b, "r", r) == BSON_OK) &&
  66. (bson_append_double(_b, "i", i) == BSON_OK) &&
  67. (bson_append_finish_object(_b) == BSON_OK);
  68. }
  69. EXPORT int mongo_bson_buffer_append(struct bson_buffer* b, char* name, mxArray* value) {
  70. size_t numel = mxGetNumberOfElements(value);
  71. mxClassID cls = mxGetClassID(value);
  72. bson* _b = (bson*)b;
  73. mwSize i, j;
  74. mwSize dims[MAXDIM];
  75. mwSize ijk[MAXDIM];
  76. mwSize sizes[MAXDIM];
  77. mwSize ndims;
  78. const mwSize *odims;
  79. int depth = 0;
  80. int success;
  81. if (numel == 1) {
  82. /* Append a single element using the given name */
  83. switch (cls) {
  84. case mxLOGICAL_CLASS:
  85. return (bson_append_bool(_b, name, ((char*)mxGetData(value))[0]) == BSON_OK);
  86. case mxDOUBLE_CLASS:
  87. if (mxIsComplex(value))
  88. return mongo_bson_buffer_append_complex(b, name, mxGetPr(value)[0], mxGetPi(value)[0]);
  89. else
  90. return (bson_append_double(_b, name, mxGetPr(value)[0]) == BSON_OK);
  91. case mxSINGLE_CLASS:
  92. return (bson_append_double(_b, name, ((float*)mxGetData(value))[0]) == BSON_OK);
  93. case mxINT8_CLASS:
  94. return (bson_append_int(_b, name, ((signed char*)mxGetData(value))[0]) == BSON_OK);
  95. case mxUINT8_CLASS:
  96. return (bson_append_int(_b, name, ((unsigned char*)mxGetData(value))[0]) == BSON_OK);
  97. case mxINT16_CLASS:
  98. return (bson_append_int(_b, name, ((short*)mxGetData(value))[0]) == BSON_OK);
  99. case mxUINT16_CLASS:
  100. return (bson_append_int(_b, name, ((unsigned short*)mxGetData(value))[0]) == BSON_OK);
  101. case mxINT32_CLASS:
  102. return (bson_append_int(_b, name, ((int*)mxGetData(value))[0]) == BSON_OK);
  103. case mxUINT32_CLASS:
  104. return (bson_append_int(_b, name, ((unsigned int*)mxGetData(value))[0]) == BSON_OK);
  105. case mxINT64_CLASS: ;
  106. case mxUINT64_CLASS:
  107. return (bson_append_long(_b, name, ((int64_t*)mxGetData(value))[0]) == BSON_OK);
  108. default:
  109. mexPrintf("BsonBuffer:append - Unhandled type: %s\n", mxGetClassName(value));
  110. return 0;
  111. }
  112. }
  113. success = (bson_append_start_array(_b, name) == BSON_OK);
  114. odims = mxGetDimensions(value);
  115. ndims = mxGetNumberOfDimensions(value);
  116. memcpy(dims, odims, ndims*sizeof(mwSize));
  117. if (ndims > 1)
  118. reverse(dims, ndims);
  119. i = ndims;
  120. /* calculate offset to multiply each dimension's index by */
  121. j = 1;
  122. do {
  123. i--;
  124. sizes[i] = j;
  125. j *= dims[i];
  126. } while (i > 0);
  127. if (ndims == 2 && dims[1] == 1)
  128. ndims--; /* 1 dimensional row vector */
  129. if (ndims > 1) {
  130. /* reverse row and columns */
  131. j = dims[ndims-1];
  132. dims[ndims-1] = dims[ndims-2];
  133. dims[ndims-2] = j;
  134. j = sizes[ndims-1];
  135. sizes[ndims-1] = sizes[ndims-2];
  136. sizes[ndims-2] = j;
  137. }
  138. memset(ijk, 0, ndims * sizeof(mwSize));
  139. while (success && depth >= 0) {
  140. if (ijk[depth] < dims[depth]) {
  141. const char* num = numstr((int)(ijk[depth]++));
  142. if (depth < (int)(ndims - 1)) {
  143. depth++;
  144. success = (bson_append_start_array(_b, num) == BSON_OK);
  145. }
  146. else {
  147. i = 0;
  148. for (j = 0; j < ndims; j++)
  149. i += (ijk[j]-1) * sizes[j];
  150. switch (cls) {
  151. case mxLOGICAL_CLASS:
  152. success = (bson_append_bool(_b, num, ((char*)mxGetData(value))[i]) == BSON_OK);
  153. break;
  154. case mxDOUBLE_CLASS:
  155. if (mxIsComplex(value))
  156. success = mongo_bson_buffer_append_complex(b, num, mxGetPr(value)[i], mxGetPi(value)[i]);
  157. else
  158. success = (bson_append_double(_b, num, mxGetPr(value)[i]) == BSON_OK);
  159. break;
  160. case mxSINGLE_CLASS:
  161. success = (bson_append_double(_b, num, ((float*)mxGetData(value))[i]) == BSON_OK);
  162. break;
  163. case mxINT8_CLASS:
  164. success = (bson_append_int(_b, num, ((signed char*)mxGetData(value))[i]) == BSON_OK);
  165. break;
  166. case mxUINT8_CLASS:
  167. success = (bson_append_int(_b, num, ((unsigned char*)mxGetData(value))[i]) == BSON_OK);
  168. break;
  169. case mxINT16_CLASS:
  170. success = (bson_append_int(_b, num, ((short*)mxGetData(value))[i]) == BSON_OK);
  171. break;
  172. case mxUINT16_CLASS:
  173. success = (bson_append_int(_b, num, ((unsigned short*)mxGetData(value))[i]) == BSON_OK);
  174. break;
  175. case mxINT32_CLASS:
  176. success = (bson_append_int(_b, num, ((int*)mxGetData(value))[i]) == BSON_OK);
  177. break;
  178. case mxUINT32_CLASS:
  179. success = (bson_append_int(_b, num, ((unsigned int*)mxGetData(value))[i]) == BSON_OK);
  180. break;
  181. case mxINT64_CLASS: ;
  182. case mxUINT64_CLASS:
  183. success = (bson_append_long(_b, num, ((int64_t*)mxGetData(value))[i]) == BSON_OK);
  184. break;
  185. default:
  186. mexPrintf("BsonBuffer:append - Unhandled type: %s\n", mxGetClassName(value));
  187. return 0;
  188. }
  189. }
  190. }
  191. else {
  192. ijk[depth] = 0;
  193. success = (bson_append_finish_object(_b) == BSON_OK);
  194. depth--;
  195. }
  196. }
  197. return success;
  198. }
  199. EXPORT int mongo_bson_buffer_append_string(struct bson_buffer* b, char* name, char* value) {
  200. return (bson_append_string((bson*) b, name, value) == BSON_OK);
  201. }
  202. EXPORT int mongo_bson_buffer_append_binary(struct bson_buffer* b, char* name, int type, void* value, int len) {
  203. return (bson_append_binary((bson*) b, name, type, (const char*) value, len) == BSON_OK);
  204. }
  205. EXPORT int mongo_bson_buffer_append_oid(struct bson_buffer* b, char* name, void* value) {
  206. return (bson_append_oid((bson*) b, name, (bson_oid_t*) value) == BSON_OK);
  207. }
  208. EXPORT int mongo_bson_buffer_append_date(struct bson_buffer* b, char *name, mxArray* value) {
  209. size_t numel = mxGetNumberOfElements(value);
  210. mxClassID cls = mxGetClassID(value);
  211. bson* _b = (bson*)b;
  212. mwSize i, j;
  213. mwSize dims[MAXDIM];
  214. mwSize ijk[MAXDIM];
  215. mwSize sizes[MAXDIM];
  216. mwSize ndims;
  217. const mwSize *odims; /* original dimensions */
  218. char* p;
  219. int depth = 0;
  220. int success;
  221. if (cls != mxDOUBLE_CLASS) {
  222. mexPrintf("Only double values are permitted in appendDate\n");
  223. return 0;
  224. }
  225. if (numel == 1)
  226. return (bson_append_date(_b, name, (bson_date_t)((mxGetPr(value)[0] - 719529) * (1000 * 60 * 60 * 24)) ) == BSON_OK);
  227. success = (bson_append_start_array(_b, name) == BSON_OK);
  228. odims = mxGetDimensions(value);
  229. ndims = mxGetNumberOfDimensions(value);
  230. memcpy(dims, odims, ndims*sizeof(mwSize));
  231. if (ndims > 1)
  232. reverse(dims, ndims);
  233. i = ndims;
  234. j = 1;
  235. /* calculate offset to multiply each dimension's index by */
  236. do {
  237. i--;
  238. sizes[i] = j;
  239. j *= dims[i];
  240. } while (i > 0);
  241. if (ndims == 2 && dims[1] == 1)
  242. ndims--;
  243. if (ndims > 1) {
  244. /* reverse row and columns */
  245. j = dims[ndims-1];
  246. dims[ndims-1] = dims[ndims-2];
  247. dims[ndims-2] = j;
  248. j = sizes[ndims-1];
  249. sizes[ndims-1] = sizes[ndims-2];
  250. sizes[ndims-2] = j;
  251. }
  252. memset(ijk, 0, ndims * sizeof(mwSize));
  253. p = (char*)mxGetData(value);
  254. while (success && depth >= 0) {
  255. if (ijk[depth] < dims[depth]) {
  256. const char* num = numstr((int)(ijk[depth]++));
  257. if (depth < (int)(ndims - 1)) {
  258. depth++;
  259. success = (bson_append_start_array(_b, num) == BSON_OK);
  260. }
  261. else {
  262. i = 0;
  263. for (j = 0; j < ndims; j++)
  264. i += (ijk[j]-1) * sizes[j];
  265. success = (bson_append_date(_b, num, (bson_date_t)((mxGetPr(value)[i] - 719529) * (1000 * 60 * 60 * 24)) ) == BSON_OK);
  266. }
  267. }
  268. else {
  269. ijk[depth] = 0;
  270. success = (bson_append_finish_object(_b) == BSON_OK);
  271. depth--;
  272. }
  273. }
  274. return success;
  275. }
  276. EXPORT int mongo_bson_buffer_append_null(struct bson_buffer* b, char *name) {
  277. return (bson_append_null((bson*) b, name) == BSON_OK);
  278. }
  279. EXPORT int mongo_bson_buffer_append_regex(struct bson_buffer* b, char *name, char* pattern, char* options) {
  280. return (bson_append_regex((bson*) b, name, pattern, options) == BSON_OK);
  281. }
  282. EXPORT int mongo_bson_buffer_append_code(struct bson_buffer* b, char *name, char* value) {
  283. return (bson_append_code((bson*) b, name, value) == BSON_OK);
  284. }
  285. EXPORT int mongo_bson_buffer_append_symbol(struct bson_buffer* b, char *name, char* value) {
  286. return (bson_append_symbol((bson*) b, name, value) == BSON_OK);
  287. }
  288. EXPORT int mongo_bson_buffer_append_codewscope(struct bson_buffer* b, char *name, char* code, struct bson_* scope) {
  289. return (bson_append_code_w_scope((bson*) b, name, code, (bson*) scope) == BSON_OK);
  290. }
  291. EXPORT int mongo_bson_buffer_append_timestamp(struct bson_buffer* b, char *name, int date, int increment) {
  292. bson_timestamp_t ts;
  293. ts.i = increment;
  294. ts.t = date;
  295. return (bson_append_timestamp((bson*) b, name, &ts) == BSON_OK);
  296. }
  297. EXPORT int mongo_bson_buffer_start_object(struct bson_buffer* b, char* name) {
  298. return (bson_append_start_object((bson*) b, name) == BSON_OK);
  299. }
  300. EXPORT int mongo_bson_buffer_finish_object(struct bson_buffer* b) {
  301. return (bson_append_finish_object((bson*) b) == BSON_OK);
  302. }
  303. EXPORT int mongo_bson_buffer_start_array(struct bson_buffer* b, char* name) {
  304. return (bson_append_start_array((bson*) b, name) == BSON_OK);
  305. }
  306. EXPORT int mongo_bson_buffer_append_bson(struct bson_buffer* b, char* name, struct bson_* bs) {
  307. return (bson_append_bson((bson*)b, name, (bson*)bs) == BSON_OK);
  308. }
  309. EXPORT void mongo_bson_empty(struct bson_** b) {
  310. bson empty;
  311. bson* b_ = (bson*)malloc(sizeof(bson));
  312. bson_empty(&empty);
  313. bson_copy(b_, &empty);
  314. *b = (struct bson_*)b_;
  315. }
  316. EXPORT int mongo_bson_size(struct bson_* b) {
  317. return bson_size((bson*) b);
  318. }
  319. EXPORT int mongo_bson_buffer_size(struct bson_buffer* b) {
  320. bson* _b = (bson*)b;
  321. return (int)(_b->cur - _b->data) + 1;
  322. }
  323. EXPORT void mongo_bson_iterator_create(struct bson_* b, struct bson_iterator_** i) {
  324. bson_iterator* _i = (bson_iterator*)malloc(sizeof(bson_iterator));
  325. bson_iterator_init(_i, (bson*) b);
  326. *i = (struct bson_iterator_*)_i;
  327. }
  328. EXPORT int mongo_bson_find(struct bson_* b, char* name, struct bson_iterator_** i) {
  329. bson* _b = (bson*)b;
  330. bson sub;
  331. bson_iterator iter;
  332. const char* next = name;
  333. do {
  334. int t;
  335. char *p;
  336. char prefix[2048];
  337. int len;
  338. if (bson_find(&iter, _b, next) != BSON_EOO) {
  339. bson_iterator* _i = (bson_iterator*)malloc(sizeof(bson_iterator));
  340. *_i = iter;
  341. *i = (struct bson_iterator_*)_i;
  342. return 1;
  343. }
  344. p = strchr((char*)next, '.');
  345. if (!p)
  346. return 0;
  347. len = (int)(p - next);
  348. strncpy(prefix, next, len);
  349. prefix[len] = '\0';
  350. if ((t = bson_find(&iter, _b, prefix)) == BSON_EOO)
  351. return 0;
  352. if (t == BSON_ARRAY || t == BSON_OBJECT) {
  353. bson_iterator_subobject(&iter, &sub);
  354. _b = &sub;
  355. next = p + 1;
  356. }
  357. else
  358. return 0;
  359. }
  360. while (1);
  361. /* never gets here */
  362. return 0;
  363. }
  364. EXPORT void mongo_bson_iterator_free(struct bson_iterator_* i) {
  365. free(i);
  366. }
  367. EXPORT int mongo_bson_iterator_type(struct bson_iterator_* i) {
  368. return bson_iterator_type((bson_iterator*) i);
  369. }
  370. EXPORT int mongo_bson_iterator_next(struct bson_iterator_* i) {
  371. return bson_iterator_next((bson_iterator*) i);
  372. }
  373. EXPORT const char* mongo_bson_iterator_key(struct bson_iterator_* i) {
  374. return bson_iterator_key((bson_iterator*) i);
  375. }
  376. EXPORT void mongo_bson_subiterator(struct bson_iterator_* i, struct bson_iterator_** si) {
  377. bson_iterator* sub = (bson_iterator*)malloc(sizeof(bson_iterator));
  378. bson_iterator_subiterator((bson_iterator*)i, sub);
  379. *si = (struct bson_iterator_*)sub;
  380. }
  381. EXPORT int mongo_bson_iterator_int(struct bson_iterator_* i) {
  382. return bson_iterator_int((bson_iterator*)i);
  383. }
  384. EXPORT mxint64 mongo_bson_iterator_long(struct bson_iterator_* i) {
  385. return bson_iterator_long((bson_iterator*)i);
  386. }
  387. EXPORT double mongo_bson_iterator_double(struct bson_iterator_* i) {
  388. return bson_iterator_double((bson_iterator*)i);
  389. }
  390. EXPORT const char* mongo_bson_iterator_string(struct bson_iterator_* i) {
  391. return bson_iterator_string((bson_iterator*)i);
  392. }
  393. EXPORT int mongo_bson_iterator_bin_type(struct bson_iterator_* i) {
  394. return bson_iterator_bin_type((bson_iterator*)i);
  395. }
  396. EXPORT int mongo_bson_iterator_bin_len(struct bson_iterator_* i) {
  397. return bson_iterator_bin_len((bson_iterator*)i);
  398. }
  399. EXPORT void mongo_bson_iterator_bin_value(struct bson_iterator_* i, void* v) {
  400. int len = bson_iterator_bin_len((bson_iterator*)i);
  401. memcpy(v, bson_iterator_bin_data((bson_iterator*)i), len);
  402. }
  403. EXPORT void mongo_bson_oid_gen(void* oid) {
  404. bson_oid_gen((bson_oid_t*) oid);
  405. }
  406. EXPORT const char* mongo_bson_oid_to_string(void* oid) {
  407. static char s[25];
  408. bson_oid_to_string((bson_oid_t*) oid, s);
  409. return s;
  410. }
  411. EXPORT void mongo_bson_oid_from_string(char* s, void* oid) {
  412. bson_oid_from_string((bson_oid_t*) oid, s);
  413. }
  414. EXPORT void mongo_bson_iterator_oid(struct bson_iterator_* i, void* oid) {
  415. memcpy(oid, bson_iterator_oid((bson_iterator*) i), 12);
  416. }
  417. EXPORT int mongo_bson_iterator_bool(struct bson_iterator_* i) {
  418. return (bson_iterator_bool((bson_iterator*) i) != 0);
  419. }
  420. EXPORT mxint64 mongo_bson_iterator_date(struct bson_iterator_* i) {
  421. return bson_iterator_date((bson_iterator*) i);
  422. }
  423. EXPORT const char* mongo_bson_iterator_regex(struct bson_iterator_* i) {
  424. return bson_iterator_regex((bson_iterator*) i);
  425. }
  426. EXPORT const char* mongo_bson_iterator_regex_opts(struct bson_iterator_* i) {
  427. return bson_iterator_regex_opts((bson_iterator*) i);
  428. }
  429. EXPORT const char* mongo_bson_iterator_code(struct bson_iterator_* i) {
  430. return bson_iterator_code((bson_iterator*) i);
  431. }
  432. EXPORT void mongo_bson_iterator_code_scope(struct bson_iterator_* i, struct bson_buffer** b) {
  433. bson* _b = (bson*)malloc(sizeof(bson));
  434. bson scope;
  435. bson_iterator_code_scope((bson_iterator*) i, &scope);
  436. bson_copy(_b, &scope);
  437. *b = (struct bson_buffer*)_b;
  438. }
  439. EXPORT int mongo_bson_iterator_timestamp(struct bson_iterator_* i, int* increment) {
  440. bson_timestamp_t ts = bson_iterator_timestamp((bson_iterator*) i);
  441. *increment = ts.i;
  442. return ts.t;
  443. }
  444. struct Rcomplex {
  445. double r;
  446. double i;
  447. };
  448. int _iterator_getComplex(bson_iterator* iter, struct Rcomplex* z) {
  449. bson_iterator sub;
  450. if (bson_iterator_type(iter) != BSON_OBJECT)
  451. return 0;
  452. bson_iterator_subiterator(iter, &sub);
  453. if (bson_iterator_next(&sub) != BSON_DOUBLE || strcmp(bson_iterator_key(&sub), "r") != 0)
  454. return 0;
  455. z->r = bson_iterator_double(&sub);
  456. if (bson_iterator_next(&sub) != BSON_DOUBLE || strcmp(bson_iterator_key(&sub), "i") != 0)
  457. return 0;
  458. z->i = bson_iterator_double(&sub);
  459. if (bson_iterator_next(&sub) != BSON_EOO)
  460. return 0;
  461. return 1;
  462. }
  463. EXPORT mxArray* mongo_bson_array_value(struct bson_iterator_* i) {
  464. bson_type sub_type, common_type;
  465. struct Rcomplex z;
  466. bson_iterator sub[MAXDIM+1];
  467. mwSize ndims = 0;
  468. mwSize count[MAXDIM+1];
  469. mwSize dim[MAXDIM+1];
  470. mwSize* mdim = dim + 1;
  471. mwSize sizes[MAXDIM+1];
  472. mxArray* ret;
  473. mwSize depth, j, len, ofs;
  474. int isRow = 0;
  475. sub[0] = *(bson_iterator*)i;
  476. /* count number of dimensions. This is equal to the number of
  477. consecutive array markers in the BSON */
  478. do {
  479. bson_iterator_subiterator(&sub[ndims], &sub[ndims+1]);
  480. if (++ndims > MAXDIM) {
  481. mexPrintf("Max dimensions (%d) exceeded. Use an iterator\n", MAXDIM);
  482. return 0;
  483. }
  484. sub_type = bson_iterator_next(&sub[ndims]);
  485. }
  486. while (sub_type == BSON_ARRAY);
  487. /* get the first data value's type */
  488. switch (common_type = sub_type) {
  489. case BSON_INT: ;
  490. case BSON_LONG: ;
  491. case BSON_DOUBLE: ;
  492. case BSON_BOOL: ;
  493. case BSON_DATE:
  494. break;
  495. case BSON_STRING:
  496. if (ndims > 1) {
  497. mexPrintf("Unable to convert array - Only 1 dimenisonal arrays of strings supported");
  498. return 0;
  499. }
  500. break;
  501. case BSON_OBJECT:
  502. if (_iterator_getComplex(&sub[ndims], &z))
  503. break;
  504. /* fall thru to default */
  505. default:
  506. /* including empty array */
  507. mexPrintf("Unable to convert array - invalid type (%d)", common_type);
  508. return 0;
  509. }
  510. /* initial lowest level count */
  511. for (j = 0; j <= ndims; j++)
  512. count[j] = 1;
  513. while ((sub_type = bson_iterator_next(&sub[ndims])) != BSON_EOO) {
  514. if (sub_type != common_type) {
  515. mexPrintf("Unable to convert array - inconsistent types");
  516. return 0;
  517. }
  518. if (sub_type == BSON_OBJECT && !_iterator_getComplex(&sub[ndims], &z)) {
  519. mexPrintf("Unable to convert array - invalid subobject");
  520. return 0;
  521. }
  522. ++count[ndims];
  523. }
  524. /* step through rest of array -- checking common type and dimensions */
  525. memset(dim, 0, sizeof(dim));
  526. depth = ndims;
  527. while (depth >= 1) {
  528. sub_type = bson_iterator_next(&sub[depth]);
  529. switch (sub_type) {
  530. case BSON_EOO:
  531. if (dim[depth] == 0)
  532. dim[depth] = count[depth];
  533. else if (dim[depth] != count[depth]) {
  534. mexPrintf("Unable to convert array - inconsistent dimensions");
  535. return 0;
  536. }
  537. depth--;
  538. break;
  539. case BSON_ARRAY:
  540. count[depth]++;
  541. bson_iterator_subiterator(&sub[depth], &sub[depth+1]);
  542. if (++depth > ndims) {
  543. mexPrintf("Unable to convert array - inconsistent dimensions");
  544. return 0;
  545. }
  546. count[depth] = 0;
  547. break;
  548. case BSON_INT: ;
  549. case BSON_LONG: ;
  550. case BSON_DOUBLE: ;
  551. case BSON_STRING: ;
  552. case BSON_BOOL: ;
  553. case BSON_DATE: ;
  554. GotEl: {
  555. if (depth != ndims || sub_type != common_type) {
  556. mexPrintf("Unable to convert array - inconsistent dimensions or types");
  557. return 0;
  558. }
  559. count[depth]++;
  560. break;
  561. }
  562. case BSON_OBJECT:
  563. if (_iterator_getComplex(&sub[depth], &z))
  564. goto GotEl;
  565. /* fall thru to default */
  566. default:
  567. mexPrintf("Unable to convert array - invalid type (%d)", sub_type);
  568. return 0;
  569. }
  570. }
  571. if (ndims > 1) {
  572. j = dim[ndims]; /* reverse row and column */
  573. dim[ndims] = dim[ndims-1];
  574. dim[ndims-1] = j;
  575. }
  576. /* calculate offset each dimension multiplies it's index by */
  577. len = 1;
  578. for (depth = ndims; depth > 0; depth--) {
  579. sizes[depth] = len;
  580. len *= dim[depth];
  581. }
  582. if (ndims > 1) {
  583. reverse(mdim, ndims); /* reverse dimensions for Matlab */
  584. j = sizes[ndims];
  585. sizes[ndims] = sizes[ndims-1];
  586. sizes[ndims-1] = j;
  587. } else {
  588. isRow = 1;
  589. ndims = 2;
  590. mdim[1] = mdim[0];
  591. mdim[0] = 1;
  592. }
  593. /*
  594. for (j = 1; j <= ndims; j++)
  595. mexPrintf("%d ", dim[j]);
  596. mexPrintf("\n");
  597. for (j = 1; j <= ndims; j++)
  598. mexPrintf("%d ", sizes[j]);
  599. mexPrintf("\n");
  600. */
  601. switch (common_type) {
  602. case BSON_INT: ret = mxCreateNumericArray(ndims, mdim, mxINT32_CLASS, mxREAL); break;
  603. case BSON_LONG: ret = mxCreateNumericArray(ndims, mdim, mxINT64_CLASS, mxREAL); break;
  604. case BSON_DATE:
  605. case BSON_DOUBLE: ret = mxCreateNumericArray(ndims, mdim, mxDOUBLE_CLASS, mxREAL); break;
  606. case BSON_STRING: ret = mxCreateCellMatrix(len, 1); break;
  607. case BSON_BOOL: ret = mxCreateLogicalArray(ndims, mdim); break;
  608. case BSON_OBJECT: ret = mxCreateNumericArray(ndims, mdim, mxDOUBLE_CLASS, mxCOMPLEX); break;
  609. default:
  610. /* never reaches here */
  611. ret = 0;
  612. }
  613. if (isRow)
  614. ndims--;
  615. /* step through array(s) again, pulling out values */
  616. bson_iterator_subiterator(&sub[0], &sub[1]);
  617. depth = 1;
  618. count[depth] = 0;
  619. while (depth >= 1) {
  620. sub_type = bson_iterator_next(&sub[depth]);
  621. count[depth]++;
  622. if (sub_type == BSON_EOO) {
  623. depth--;
  624. } else if (sub_type == BSON_ARRAY) {
  625. bson_iterator_subiterator(&sub[depth], &sub[depth+1]);
  626. depth++;
  627. count[depth] = 0;
  628. } else {
  629. ofs = 0;
  630. for (j = 1; j <= ndims; j++)
  631. ofs += sizes[j] * (count[j] - 1);
  632. switch (sub_type) {
  633. case BSON_INT:
  634. ((int*)mxGetData(ret))[ofs] = bson_iterator_int(&sub[depth]);
  635. break;
  636. case BSON_DATE:
  637. mxGetPr(ret)[ofs] = 719529.0 + bson_iterator_date(&sub[depth]) / (1000.0 * 60 * 60 * 24);
  638. break;
  639. case BSON_DOUBLE:
  640. mxGetPr(ret)[ofs] = bson_iterator_double(&sub[depth]);
  641. break;
  642. case BSON_LONG:
  643. ((int64_t*)mxGetData(ret))[ofs] = bson_iterator_long(&sub[depth]);
  644. break;
  645. case BSON_BOOL: ;
  646. ((mxLogical*)mxGetData(ret))[ofs] = bson_iterator_bool(&sub[depth]);
  647. break;
  648. case BSON_OBJECT:
  649. _iterator_getComplex(&sub[depth], &z);
  650. mxGetPr(ret)[ofs] = z.r;
  651. mxGetPi(ret)[ofs] = z.i;
  652. break;
  653. case BSON_STRING:
  654. mxSetCell(ret, count[depth]-1, mxCreateString(bson_iterator_string(&sub[depth])));
  655. break;
  656. default: ;
  657. /* never reaches here */
  658. }
  659. }
  660. }
  661. return ret;
  662. }