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