00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <ctype.h>
00011 #include <assert.h>
00012 #include <string.h>
00013 #include <limits.h>
00014 #include <float.h>
00015 #include <stdarg.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018
00019 #include "luxrays/utils/plymesh/rply.h"
00020
00021 namespace luxrays {
00022
00023
00024
00025
00026 #define WORDSIZE 256
00027 #define LINESIZE 1024
00028 #define BUFFERSIZE (8*1024)
00029
00030 typedef enum e_ply_io_mode_ {
00031 PLY_READ,
00032 PLY_WRITE
00033 } e_ply_io_mode;
00034
00035 static const char *const ply_storage_mode_list[] = {
00036 "binary_big_endian", "binary_little_endian", "ascii", NULL
00037 };
00038
00039 static const char *const ply_type_list[] = {
00040 "int8", "uint8", "int16", "uint16",
00041 "int32", "uint32", "float32", "float64",
00042 "char", "uchar", "short", "ushort",
00043 "int", "uint", "float", "double",
00044 "list", NULL
00045 };
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 typedef struct t_ply_argument_ {
00062 p_ply_element element;
00063 long instance_index;
00064 p_ply_property property;
00065 long length, value_index;
00066 double value;
00067 void *pdata;
00068 long idata;
00069 } t_ply_argument;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 typedef struct t_ply_property_ {
00082 char name[WORDSIZE];
00083 e_ply_type type, value_type, length_type;
00084 p_ply_read_cb read_cb;
00085 void *pdata;
00086 long idata;
00087 } t_ply_property;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 typedef struct t_ply_element_ {
00100 char name[WORDSIZE];
00101 long ninstances;
00102 p_ply_property property;
00103 long nproperties;
00104 } t_ply_element;
00105
00106
00107
00108
00109
00110
00111
00112
00113 typedef int (*p_ply_ihandler)(p_ply ply, double *value);
00114 typedef int (*p_ply_ichunk)(p_ply ply, void *anydata, size_t size);
00115 typedef struct t_ply_idriver_ {
00116 p_ply_ihandler ihandler[16];
00117 p_ply_ichunk ichunk;
00118 const char *name;
00119 } t_ply_idriver;
00120 typedef t_ply_idriver *p_ply_idriver;
00121
00122 typedef int (*p_ply_ohandler)(p_ply ply, double value);
00123 typedef int (*p_ply_ochunk)(p_ply ply, void *anydata, size_t size);
00124 typedef struct t_ply_odriver_ {
00125 p_ply_ohandler ohandler[16];
00126 p_ply_ochunk ochunk;
00127 const char *name;
00128 } t_ply_odriver;
00129 typedef t_ply_odriver *p_ply_odriver;
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 typedef struct t_ply_ {
00156 e_ply_io_mode io_mode;
00157 e_ply_storage_mode storage_mode;
00158 p_ply_element element;
00159 long nelements;
00160 char *comment;
00161 long ncomments;
00162 char *obj_info;
00163 long nobj_infos;
00164 FILE *fp;
00165 int c;
00166 char buffer[BUFFERSIZE];
00167 size_t buffer_first, buffer_token, buffer_last;
00168 p_ply_idriver idriver;
00169 p_ply_odriver odriver;
00170 t_ply_argument argument;
00171 long welement, wproperty;
00172 long winstance_index, wvalue_index, wlength;
00173 p_ply_error_cb error_cb;
00174 } t_ply;
00175
00176
00177
00178
00179 extern t_ply_idriver ply_idriver_ascii;
00180 extern t_ply_idriver ply_idriver_binary;
00181 extern t_ply_idriver ply_idriver_binary_reverse;
00182 extern t_ply_odriver ply_odriver_ascii;
00183 extern t_ply_odriver ply_odriver_binary;
00184 extern t_ply_odriver ply_odriver_binary_reverse;
00185
00186 static int ply_read_word(p_ply ply);
00187 static int ply_check_word(p_ply ply);
00188 static int ply_read_line(p_ply ply);
00189 static int ply_check_line(p_ply ply);
00190 static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size);
00191 static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size);
00192 static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size);
00193 static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size);
00194 static void ply_reverse(void *anydata, size_t size);
00195
00196
00197
00198
00199 static int ply_find_string(const char *item, const char* const list[]);
00200 static p_ply_element ply_find_element(p_ply ply, const char *name);
00201 static p_ply_property ply_find_property(p_ply_element element,
00202 const char *name);
00203
00204
00205
00206
00207 static int ply_read_header_format(p_ply ply);
00208 static int ply_read_header_comment(p_ply ply);
00209 static int ply_read_header_obj_info(p_ply ply);
00210 static int ply_read_header_property(p_ply ply);
00211 static int ply_read_header_element(p_ply ply);
00212
00213
00214
00215
00216 static void ply_error_cb(const char *message);
00217 static void ply_error(p_ply ply, const char *fmt, ...);
00218
00219
00220
00221
00222 static void ply_init(p_ply ply);
00223 static void ply_element_init(p_ply_element element);
00224 static void ply_property_init(p_ply_property property);
00225 static p_ply ply_alloc(void);
00226 static p_ply_element ply_grow_element(p_ply ply);
00227 static p_ply_property ply_grow_property(p_ply ply, p_ply_element element);
00228 static void *ply_grow_array(p_ply ply, void **pointer, long *nmemb, long size);
00229
00230
00231
00232
00233 static e_ply_storage_mode ply_arch_endian(void);
00234 static int ply_type_check(void);
00235
00236
00237
00238
00239 static int ply_read_element(p_ply ply, p_ply_element element,
00240 p_ply_argument argument);
00241 static int ply_read_property(p_ply ply, p_ply_element element,
00242 p_ply_property property, p_ply_argument argument);
00243 static int ply_read_list_property(p_ply ply, p_ply_element element,
00244 p_ply_property property, p_ply_argument argument);
00245 static int ply_read_scalar_property(p_ply ply, p_ply_element element,
00246 p_ply_property property, p_ply_argument argument);
00247
00248
00249
00250
00251
00252
00253 #define BWORD(p) (p->buffer + p->buffer_token)
00254 #define BLINE(p) (p->buffer + p->buffer_token)
00255
00256
00257 #define BFIRST(p) (p->buffer + p->buffer_first)
00258
00259
00260 #define BSIZE(p) (p->buffer_last - p->buffer_first)
00261
00262
00263 #define BSKIP(p, s) (p->buffer_first += s)
00264
00265
00266 static int BREFILL(p_ply ply) {
00267
00268 size_t size = BSIZE(ply);
00269 memmove(ply->buffer, BFIRST(ply), size);
00270 ply->buffer_last = size;
00271 ply->buffer_first = ply->buffer_token = 0;
00272
00273 size = fread(ply->buffer+size, 1, BUFFERSIZE-size-1, ply->fp);
00274
00275 ply->buffer[BUFFERSIZE-1] = '\0';
00276
00277 if (size <= 0) return 0;
00278
00279 ply->buffer_last += size;
00280 return 1;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289 p_ply ply_open(const char *name, p_ply_error_cb error_cb) {
00290 char magic[5] = " ";
00291 FILE *fp = NULL;
00292 p_ply ply = NULL;
00293 if (error_cb == NULL) error_cb = ply_error_cb;
00294 if (!ply_type_check()) {
00295 error_cb("Incompatible type system");
00296 return NULL;
00297 }
00298 assert(name);
00299 fp = fopen(name, "r");
00300 if (!fp) {
00301 error_cb("Unable to open file");
00302 return NULL;
00303 }
00304 if (fread(magic, 1, 4, fp) < 4) {
00305 error_cb("Error reading from file");
00306 fclose(fp);
00307 return NULL;
00308 }
00309 if (strcmp(magic, "ply\n")) {
00310 fclose(fp);
00311 error_cb("Not a PLY file. Expected magic number 'ply\\n'");
00312 return NULL;
00313 }
00314 ply = ply_alloc();
00315 if (!ply) {
00316 error_cb("Out of memory");
00317 fclose(fp);
00318 return NULL;
00319 }
00320 ply->fp = fp;
00321 ply->io_mode = PLY_READ;
00322 ply->error_cb = error_cb;
00323 return ply;
00324 }
00325
00326 int ply_read_header(p_ply ply) {
00327 assert(ply && ply->fp && ply->io_mode == PLY_READ);
00328 if (!ply_read_word(ply)) return 0;
00329
00330 if (!ply_read_header_format(ply)) {
00331 ply_error(ply, "Invalid file format");
00332 return 0;
00333 }
00334
00335 while (strcmp(BWORD(ply), "end_header")) {
00336 if (!ply_read_header_comment(ply) &&
00337 !ply_read_header_element(ply) &&
00338 !ply_read_header_obj_info(ply)) {
00339 ply_error(ply, "Unexpected token '%s'", BWORD(ply));
00340 return 0;
00341 }
00342 }
00343 return 1;
00344 }
00345
00346 long ply_set_read_cb(p_ply ply, const char *element_name,
00347 const char* property_name, p_ply_read_cb read_cb,
00348 void *pdata, long idata) {
00349 p_ply_element element = NULL;
00350 p_ply_property property = NULL;
00351 assert(ply && element_name && property_name);
00352 element = ply_find_element(ply, element_name);
00353 if (!element) return 0;
00354 property = ply_find_property(element, property_name);
00355 if (!property) return 0;
00356 property->read_cb = read_cb;
00357 property->pdata = pdata;
00358 property->idata = idata;
00359 return (int) element->ninstances;
00360 }
00361
00362 int ply_read(p_ply ply) {
00363 long i;
00364 p_ply_argument argument;
00365 assert(ply && ply->fp && ply->io_mode == PLY_READ);
00366 argument = &ply->argument;
00367
00368 for (i = 0; i < ply->nelements; i++) {
00369 p_ply_element element = &ply->element[i];
00370 argument->element = element;
00371 if (!ply_read_element(ply, element, argument))
00372 return 0;
00373 }
00374 return 1;
00375 }
00376
00377
00378
00379
00380 p_ply ply_create(const char *name, e_ply_storage_mode storage_mode,
00381 p_ply_error_cb error_cb) {
00382 FILE *fp = NULL;
00383 p_ply ply = NULL;
00384 if (error_cb == NULL) error_cb = ply_error_cb;
00385 if (!ply_type_check()) {
00386 error_cb("Incompatible type system");
00387 return NULL;
00388 }
00389 assert(name && storage_mode <= PLY_DEFAULT);
00390 fp = fopen(name, "wb");
00391 if (!fp) {
00392 error_cb("Unable to create file");
00393 return NULL;
00394 }
00395 ply = ply_alloc();
00396 if (!ply) {
00397 fclose(fp);
00398 error_cb("Out of memory");
00399 return NULL;
00400 }
00401 ply->io_mode = PLY_WRITE;
00402 if (storage_mode == PLY_DEFAULT) storage_mode = ply_arch_endian();
00403 if (storage_mode == PLY_ASCII) ply->odriver = &ply_odriver_ascii;
00404 else if (storage_mode == ply_arch_endian())
00405 ply->odriver = &ply_odriver_binary;
00406 else ply->odriver = &ply_odriver_binary_reverse;
00407 ply->storage_mode = storage_mode;
00408 ply->fp = fp;
00409 ply->error_cb = error_cb;
00410 return ply;
00411 }
00412
00413 int ply_add_element(p_ply ply, const char *name, long ninstances) {
00414 p_ply_element element = NULL;
00415 assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
00416 assert(name && strlen(name) < WORDSIZE && ninstances >= 0);
00417 if (strlen(name) >= WORDSIZE || ninstances < 0) {
00418 ply_error(ply, "Invalid arguments");
00419 return 0;
00420 }
00421 element = ply_grow_element(ply);
00422 if (!element) return 0;
00423 strcpy(element->name, name);
00424 element->ninstances = ninstances;
00425 return 1;
00426 }
00427
00428 int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type) {
00429 p_ply_element element = NULL;
00430 p_ply_property property = NULL;
00431 assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
00432 assert(name && strlen(name) < WORDSIZE);
00433 assert(type < PLY_LIST);
00434 if (strlen(name) >= WORDSIZE || type >= PLY_LIST) {
00435 ply_error(ply, "Invalid arguments");
00436 return 0;
00437 }
00438 element = &ply->element[ply->nelements-1];
00439 property = ply_grow_property(ply, element);
00440 if (!property) return 0;
00441 strcpy(property->name, name);
00442 property->type = type;
00443 return 1;
00444 }
00445
00446 int ply_add_list_property(p_ply ply, const char *name,
00447 e_ply_type length_type, e_ply_type value_type) {
00448 p_ply_element element = NULL;
00449 p_ply_property property = NULL;
00450 assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
00451 assert(name && strlen(name) < WORDSIZE);
00452 if (strlen(name) >= WORDSIZE) {
00453 ply_error(ply, "Invalid arguments");
00454 return 0;
00455 }
00456 assert(length_type < PLY_LIST);
00457 assert(value_type < PLY_LIST);
00458 if (length_type >= PLY_LIST || value_type >= PLY_LIST) {
00459 ply_error(ply, "Invalid arguments");
00460 return 0;
00461 }
00462 element = &ply->element[ply->nelements-1];
00463 property = ply_grow_property(ply, element);
00464 if (!property) return 0;
00465 strcpy(property->name, name);
00466 property->type = PLY_LIST;
00467 property->length_type = length_type;
00468 property->value_type = value_type;
00469 return 1;
00470 }
00471
00472 int ply_add_property(p_ply ply, const char *name, e_ply_type type,
00473 e_ply_type length_type, e_ply_type value_type) {
00474 if (type == PLY_LIST)
00475 return ply_add_list_property(ply, name, length_type, value_type);
00476 else
00477 return ply_add_scalar_property(ply, name, type);
00478 }
00479
00480 int ply_add_comment(p_ply ply, const char *comment) {
00481 char *new_comment = NULL;
00482 assert(ply && comment && strlen(comment) < LINESIZE);
00483 if (!comment || strlen(comment) >= LINESIZE) {
00484 ply_error(ply, "Invalid arguments");
00485 return 0;
00486 }
00487 new_comment = (char *) ply_grow_array(ply, (void **) &ply->comment,
00488 &ply->ncomments, LINESIZE);
00489 if (!new_comment) return 0;
00490 strcpy(new_comment, comment);
00491 return 1;
00492 }
00493
00494 int ply_add_obj_info(p_ply ply, const char *obj_info) {
00495 char *new_obj_info = NULL;
00496 assert(ply && obj_info && strlen(obj_info) < LINESIZE);
00497 if (!obj_info || strlen(obj_info) >= LINESIZE) {
00498 ply_error(ply, "Invalid arguments");
00499 return 0;
00500 }
00501 new_obj_info = (char *) ply_grow_array(ply, (void **) &ply->obj_info,
00502 &ply->nobj_infos, LINESIZE);
00503 if (!new_obj_info) return 0;
00504 strcpy(new_obj_info, obj_info);
00505 return 1;
00506 }
00507
00508 int ply_write_header(p_ply ply) {
00509 long i, j;
00510 assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
00511 assert(ply->element || ply->nelements == 0);
00512 assert(!ply->element || ply->nelements > 0);
00513 if (fprintf(ply->fp, "ply\nformat %s 1.0\n",
00514 ply_storage_mode_list[ply->storage_mode]) <= 0) goto error;
00515 for (i = 0; i < ply->ncomments; i++)
00516 if (fprintf(ply->fp, "comment %s\n", ply->comment + LINESIZE*i) <= 0)
00517 goto error;
00518 for (i = 0; i < ply->nobj_infos; i++)
00519 if (fprintf(ply->fp, "obj_info %s\n", ply->obj_info + LINESIZE*i) <= 0)
00520 goto error;
00521 for (i = 0; i < ply->nelements; i++) {
00522 p_ply_element element = &ply->element[i];
00523 assert(element->property || element->nproperties == 0);
00524 assert(!element->property || element->nproperties > 0);
00525 if (fprintf(ply->fp, "element %s %ld\n", element->name,
00526 element->ninstances) <= 0) goto error;
00527 for (j = 0; j < element->nproperties; j++) {
00528 p_ply_property property = &element->property[j];
00529 if (property->type == PLY_LIST) {
00530 if (fprintf(ply->fp, "property list %s %s %s\n",
00531 ply_type_list[property->length_type],
00532 ply_type_list[property->value_type],
00533 property->name) <= 0) goto error;
00534 } else {
00535 if (fprintf(ply->fp, "property %s %s\n",
00536 ply_type_list[property->type],
00537 property->name) <= 0) goto error;
00538 }
00539 }
00540 }
00541 return fprintf(ply->fp, "end_header\n") > 0;
00542 error:
00543 ply_error(ply, "Error writing to file");
00544 return 0;
00545 }
00546
00547 int ply_write(p_ply ply, double value) {
00548 p_ply_element element = NULL;
00549 p_ply_property property = NULL;
00550 int type = -1;
00551 int breakafter = 0;
00552 if (ply->welement > ply->nelements) return 0;
00553 element = &ply->element[ply->welement];
00554 if (ply->wproperty > element->nproperties) return 0;
00555 property = &element->property[ply->wproperty];
00556 if (property->type == PLY_LIST) {
00557 if (ply->wvalue_index == 0) {
00558 type = property->length_type;
00559 ply->wlength = (long) value;
00560 } else type = property->value_type;
00561 } else {
00562 type = property->type;
00563 ply->wlength = 0;
00564 }
00565 if (!ply->odriver->ohandler[type](ply, value)) {
00566 ply_error(ply, "Failed writing %s of %s %d (%s: %s)",
00567 property->name, element->name,
00568 ply->winstance_index,
00569 ply->odriver->name, ply_type_list[type]);
00570 return 0;
00571 }
00572 ply->wvalue_index++;
00573 if (ply->wvalue_index > ply->wlength) {
00574 ply->wvalue_index = 0;
00575 ply->wproperty++;
00576 }
00577 if (ply->wproperty >= element->nproperties) {
00578 ply->wproperty = 0;
00579 ply->winstance_index++;
00580 if (ply->storage_mode == PLY_ASCII) breakafter = 1;
00581 }
00582 if (ply->winstance_index >= element->ninstances) {
00583 ply->winstance_index = 0;
00584 ply->welement++;
00585 }
00586 return !breakafter || putc('\n', ply->fp) > 0;
00587 }
00588
00589 int ply_close(p_ply ply) {
00590 long i;
00591 assert(ply && ply->fp);
00592 assert(ply->element || ply->nelements == 0);
00593 assert(!ply->element || ply->nelements > 0);
00594
00595 if (ply->io_mode == PLY_WRITE &&
00596 fwrite(ply->buffer, 1, ply->buffer_last, ply->fp) < ply->buffer_last) {
00597 ply_error(ply, "Error closing up");
00598 return 0;
00599 }
00600 fclose(ply->fp);
00601
00602 if (ply->element) {
00603 for (i = 0; i < ply->nelements; i++) {
00604 p_ply_element element = &ply->element[i];
00605 if (element->property) free(element->property);
00606 }
00607 free(ply->element);
00608 }
00609 if (ply->obj_info) free(ply->obj_info);
00610 if (ply->comment) free(ply->comment);
00611 free(ply);
00612 return 1;
00613 }
00614
00615
00616
00617
00618 p_ply_element ply_get_next_element(p_ply ply,
00619 p_ply_element last) {
00620 assert(ply);
00621 if (!last) return ply->element;
00622 last++;
00623 if (last < ply->element + ply->nelements) return last;
00624 else return NULL;
00625 }
00626
00627 int ply_get_element_info(p_ply_element element, const char** name,
00628 long *ninstances) {
00629 assert(element);
00630 if (name) *name = element->name;
00631 if (ninstances) *ninstances = (long) element->ninstances;
00632 return 1;
00633 }
00634
00635 p_ply_property ply_get_next_property(p_ply_element element,
00636 p_ply_property last) {
00637 assert(element);
00638 if (!last) return element->property;
00639 last++;
00640 if (last < element->property + element->nproperties) return last;
00641 else return NULL;
00642 }
00643
00644 int ply_get_property_info(p_ply_property property, const char** name,
00645 e_ply_type *type, e_ply_type *length_type, e_ply_type *value_type) {
00646 assert(property);
00647 if (name) *name = property->name;
00648 if (type) *type = property->type;
00649 if (length_type) *length_type = property->length_type;
00650 if (value_type) *value_type = property->value_type;
00651 return 1;
00652
00653 }
00654
00655 const char *ply_get_next_comment(p_ply ply, const char *last) {
00656 assert(ply);
00657 if (!last) return ply->comment;
00658 last += LINESIZE;
00659 if (last < ply->comment + LINESIZE*ply->ncomments) return last;
00660 else return NULL;
00661 }
00662
00663 const char *ply_get_next_obj_info(p_ply ply, const char *last) {
00664 assert(ply);
00665 if (!last) return ply->obj_info;
00666 last += LINESIZE;
00667 if (last < ply->obj_info + LINESIZE*ply->nobj_infos) return last;
00668 else return NULL;
00669 }
00670
00671
00672
00673
00674 int ply_get_argument_element(p_ply_argument argument,
00675 p_ply_element *element, long *instance_index) {
00676 assert(argument);
00677 if (!argument) return 0;
00678 if (element) *element = argument->element;
00679 if (instance_index) *instance_index = argument->instance_index;
00680 return 1;
00681 }
00682
00683 int ply_get_argument_property(p_ply_argument argument,
00684 p_ply_property *property, long *length, long *value_index) {
00685 assert(argument);
00686 if (!argument) return 0;
00687 if (property) *property = argument->property;
00688 if (length) *length = argument->length;
00689 if (value_index) *value_index = argument->value_index;
00690 return 1;
00691 }
00692
00693 int ply_get_argument_user_data(p_ply_argument argument, void **pdata,
00694 long *idata) {
00695 assert(argument);
00696 if (!argument) return 0;
00697 if (pdata) *pdata = argument->pdata;
00698 if (idata) *idata = argument->idata;
00699 return 1;
00700 }
00701
00702 double ply_get_argument_value(p_ply_argument argument) {
00703 assert(argument);
00704 if (!argument) return 0.0;
00705 return argument->value;
00706 }
00707
00708
00709
00710
00711 static int ply_read_list_property(p_ply ply, p_ply_element element,
00712 p_ply_property property, p_ply_argument argument) {
00713 int l;
00714 p_ply_read_cb read_cb = property->read_cb;
00715 p_ply_ihandler *driver = ply->idriver->ihandler;
00716
00717 p_ply_ihandler handler = driver[property->length_type];
00718 double length;
00719 if (!handler(ply, &length)) {
00720 ply_error(ply, "Error reading '%s' of '%s' number %d",
00721 property->name, element->name, argument->instance_index);
00722 return 0;
00723 }
00724
00725 argument->length = (long) length;
00726 argument->value_index = -1;
00727 argument->value = length;
00728 if (read_cb && !read_cb(argument)) {
00729 ply_error(ply, "Aborted by user");
00730 return 0;
00731 }
00732
00733 handler = driver[property->value_type];
00734
00735 for (l = 0; l < (long) length; l++) {
00736
00737 argument->value_index = l;
00738 if (!handler(ply, &argument->value)) {
00739 ply_error(ply, "Error reading value number %d of '%s' of "
00740 "'%s' number %d", l+1, property->name,
00741 element->name, argument->instance_index);
00742 return 0;
00743 }
00744
00745 if (read_cb && !read_cb(argument)) {
00746 ply_error(ply, "Aborted by user");
00747 return 0;
00748 }
00749 }
00750 return 1;
00751 }
00752
00753 static int ply_read_scalar_property(p_ply ply, p_ply_element element,
00754 p_ply_property property, p_ply_argument argument) {
00755 p_ply_read_cb read_cb = property->read_cb;
00756 p_ply_ihandler *driver = ply->idriver->ihandler;
00757 p_ply_ihandler handler = driver[property->type];
00758 argument->length = 1;
00759 argument->value_index = 0;
00760 if (!handler(ply, &argument->value)) {
00761 ply_error(ply, "Error reading '%s' of '%s' number %d",
00762 property->name, element->name, argument->instance_index);
00763 return 0;
00764 }
00765 if (read_cb && !read_cb(argument)) {
00766 ply_error(ply, "Aborted by user");
00767 return 0;
00768 }
00769 return 1;
00770 }
00771
00772 static int ply_read_property(p_ply ply, p_ply_element element,
00773 p_ply_property property, p_ply_argument argument) {
00774 if (property->type == PLY_LIST)
00775 return ply_read_list_property(ply, element, property, argument);
00776 else
00777 return ply_read_scalar_property(ply, element, property, argument);
00778 }
00779
00780 static int ply_read_element(p_ply ply, p_ply_element element,
00781 p_ply_argument argument) {
00782 long j, k;
00783
00784 for (j = 0; j < element->ninstances; j++) {
00785 argument->instance_index = j;
00786
00787 for (k = 0; k < element->nproperties; k++) {
00788 p_ply_property property = &element->property[k];
00789 argument->property = property;
00790 argument->pdata = property->pdata;
00791 argument->idata = property->idata;
00792 if (!ply_read_property(ply, element, property, argument))
00793 return 0;
00794 }
00795 }
00796 return 1;
00797 }
00798
00799 static int ply_find_string(const char *item, const char* const list[]) {
00800 int i;
00801 assert(item && list);
00802 for (i = 0; list[i]; i++)
00803 if (!strcmp(list[i], item)) return i;
00804 return -1;
00805 }
00806
00807 static p_ply_element ply_find_element(p_ply ply, const char *name) {
00808 p_ply_element element;
00809 int i, nelements;
00810 assert(ply && name);
00811 element = ply->element;
00812 nelements = ply->nelements;
00813 assert(element || nelements == 0);
00814 assert(!element || nelements > 0);
00815 for (i = 0; i < nelements; i++)
00816 if (!strcmp(element[i].name, name)) return &element[i];
00817 return NULL;
00818 }
00819
00820 static p_ply_property ply_find_property(p_ply_element element,
00821 const char *name) {
00822 p_ply_property property;
00823 int i, nproperties;
00824 assert(element && name);
00825 property = element->property;
00826 nproperties = element->nproperties;
00827 assert(property || nproperties == 0);
00828 assert(!property || nproperties > 0);
00829 for (i = 0; i < nproperties; i++)
00830 if (!strcmp(property[i].name, name)) return &property[i];
00831 return NULL;
00832 }
00833
00834 static int ply_check_word(p_ply ply) {
00835 if (strlen(BLINE(ply)) >= WORDSIZE) {
00836 ply_error(ply, "Word too long");
00837 return 0;
00838 }
00839 return 1;
00840 }
00841
00842 static int ply_read_word(p_ply ply) {
00843 size_t t = 0;
00844 assert(ply && ply->fp && ply->io_mode == PLY_READ);
00845
00846 while (1) {
00847 t = strspn(BFIRST(ply), " \n\r\t");
00848
00849 if (t >= BSIZE(ply)) {
00850 if (!BREFILL(ply)) {
00851 ply_error(ply, "Unexpected end of file");
00852 return 0;
00853 }
00854 } else break;
00855 }
00856 BSKIP(ply, t);
00857
00858 t = strcspn(BFIRST(ply), " \n\r\t");
00859
00860 if (t < BSIZE(ply)) {
00861 ply->buffer_token = ply->buffer_first;
00862 BSKIP(ply, t);
00863 *BFIRST(ply) = '\0';
00864 BSKIP(ply, 1);
00865 return ply_check_word(ply);
00866 }
00867
00868 if (!BREFILL(ply)) {
00869 ply_error(ply, "Unexpected end of file");
00870 return 0;
00871 }
00872
00873 t += strcspn(BFIRST(ply) + t, " \n\r\t");
00874
00875 if (t >= BSIZE(ply)) {
00876 ply_error(ply, "Token too large");
00877 return 0;
00878 }
00879
00880 ply->buffer_token = ply->buffer_first;
00881 BSKIP(ply, t);
00882 *BFIRST(ply) = '\0';
00883 BSKIP(ply, 1);
00884 return ply_check_word(ply);
00885 }
00886
00887 static int ply_check_line(p_ply ply) {
00888 if (strlen(BLINE(ply)) >= LINESIZE) {
00889 ply_error(ply, "Line too long");
00890 return 0;
00891 }
00892 return 1;
00893 }
00894
00895 static int ply_read_line(p_ply ply) {
00896 const char *end = NULL;
00897 assert(ply && ply->fp && ply->io_mode == PLY_READ);
00898
00899 end = strchr(BFIRST(ply), '\n');
00900
00901 if (end) {
00902 ply->buffer_token = ply->buffer_first;
00903 BSKIP(ply, end - BFIRST(ply));
00904 *BFIRST(ply) = '\0';
00905 BSKIP(ply, 1);
00906 return ply_check_line(ply);
00907 } else {
00908 end = ply->buffer + BSIZE(ply);
00909
00910 if (!BREFILL(ply)) {
00911 ply_error(ply, "Unexpected end of file");
00912 return 0;
00913 }
00914 }
00915
00916 end = strchr(end, '\n');
00917
00918 if (!end) {
00919 ply_error(ply, "Token too large");
00920 return 0;
00921 }
00922
00923 ply->buffer_token = ply->buffer_first;
00924 BSKIP(ply, end - BFIRST(ply));
00925 *BFIRST(ply) = '\0';
00926 BSKIP(ply, 1);
00927 return ply_check_line(ply);
00928 }
00929
00930 static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size) {
00931 char *buffer = (char *) anybuffer;
00932 size_t i = 0;
00933 assert(ply && ply->fp && ply->io_mode == PLY_READ);
00934 assert(ply->buffer_first <= ply->buffer_last);
00935 while (i < size) {
00936 if (ply->buffer_first < ply->buffer_last) {
00937 buffer[i] = ply->buffer[ply->buffer_first];
00938 ply->buffer_first++;
00939 i++;
00940 } else {
00941 ply->buffer_first = 0;
00942 ply->buffer_last = fread(ply->buffer, 1, BUFFERSIZE, ply->fp);
00943 if (ply->buffer_last <= 0) return 0;
00944 }
00945 }
00946 return 1;
00947 }
00948
00949 static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size) {
00950 char *buffer = (char *) anybuffer;
00951 size_t i = 0;
00952 assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
00953 assert(ply->buffer_last <= BUFFERSIZE);
00954 while (i < size) {
00955 if (ply->buffer_last < BUFFERSIZE) {
00956 ply->buffer[ply->buffer_last] = buffer[i];
00957 ply->buffer_last++;
00958 i++;
00959 } else {
00960 ply->buffer_last = 0;
00961 if (fwrite(ply->buffer, 1, BUFFERSIZE, ply->fp) < BUFFERSIZE)
00962 return 0;
00963 }
00964 }
00965 return 1;
00966 }
00967
00968 static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size) {
00969 int ret = 0;
00970 ply_reverse(anybuffer, size);
00971 ret = ply_write_chunk(ply, anybuffer, size);
00972 ply_reverse(anybuffer, size);
00973 return ret;
00974 }
00975
00976 static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size) {
00977 if (!ply_read_chunk(ply, anybuffer, size)) return 0;
00978 ply_reverse(anybuffer, size);
00979 return 1;
00980 }
00981
00982 static void ply_reverse(void *anydata, size_t size) {
00983 char *data = (char *) anydata;
00984 char temp;
00985 size_t i;
00986 for (i = 0; i < size/2; i++) {
00987 temp = data[i];
00988 data[i] = data[size-i-1];
00989 data[size-i-1] = temp;
00990 }
00991 }
00992
00993 static void ply_init(p_ply ply) {
00994 ply->c = ' ';
00995 ply->element = NULL;
00996 ply->nelements = 0;
00997 ply->comment = NULL;
00998 ply->ncomments = 0;
00999 ply->obj_info = NULL;
01000 ply->nobj_infos = 0;
01001 ply->idriver = NULL;
01002 ply->odriver = NULL;
01003 ply->buffer[0] = '\0';
01004 ply->buffer_first = ply->buffer_last = ply->buffer_token = 0;
01005 ply->welement = 0;
01006 ply->wproperty = 0;
01007 ply->winstance_index = 0;
01008 ply->wlength = 0;
01009 ply->wvalue_index = 0;
01010 }
01011
01012 static void ply_element_init(p_ply_element element) {
01013 element->name[0] = '\0';
01014 element->ninstances = 0;
01015 element->property = NULL;
01016 element->nproperties = 0;
01017 }
01018
01019 static void ply_property_init(p_ply_property property) {
01020 property->name[0] = '\0';
01021 property->type = (e_ply_type)-1;
01022 property->length_type = (e_ply_type)-1;
01023 property->value_type = (e_ply_type)-1;
01024 property->read_cb = (p_ply_read_cb) NULL;
01025 property->pdata = NULL;
01026 property->idata = 0;
01027 }
01028
01029 static p_ply ply_alloc(void) {
01030 p_ply ply = (p_ply) malloc(sizeof(t_ply));
01031 if (!ply) return NULL;
01032 ply_init(ply);
01033 return ply;
01034 }
01035
01036 static void *ply_grow_array(p_ply ply, void **pointer,
01037 long *nmemb, long size) {
01038 void *temp = *pointer;
01039 long count = *nmemb + 1;
01040 if (!temp) temp = malloc(count*size);
01041 else temp = realloc(temp, count*size);
01042 if (!temp) {
01043 ply_error(ply, "Out of memory");
01044 return NULL;
01045 }
01046 *pointer = temp;
01047 *nmemb = count;
01048 return (char *) temp + (count-1) * size;
01049 }
01050
01051 static p_ply_element ply_grow_element(p_ply ply) {
01052 p_ply_element element = NULL;
01053 assert(ply);
01054 assert(ply->element || ply->nelements == 0);
01055 assert(!ply->element || ply->nelements > 0);
01056 element = (p_ply_element) ply_grow_array(ply, (void **) &ply->element,
01057 &ply->nelements, sizeof(t_ply_element));
01058 if (!element) return NULL;
01059 ply_element_init(element);
01060 return element;
01061 }
01062
01063 static p_ply_property ply_grow_property(p_ply ply, p_ply_element element) {
01064 p_ply_property property = NULL;
01065 assert(ply);
01066 assert(element);
01067 assert(element->property || element->nproperties == 0);
01068 assert(!element->property || element->nproperties > 0);
01069 property = (p_ply_property) ply_grow_array(ply,
01070 (void **) &element->property,
01071 &element->nproperties, sizeof(t_ply_property));
01072 if (!property) return NULL;
01073 ply_property_init(property);
01074 return property;
01075 }
01076
01077 static int ply_read_header_format(p_ply ply) {
01078 assert(ply && ply->fp && ply->io_mode == PLY_READ);
01079 if (strcmp(BWORD(ply), "format")) return 0;
01080 if (!ply_read_word(ply)) return 0;
01081 ply->storage_mode = (e_ply_storage_mode)ply_find_string(BWORD(ply), ply_storage_mode_list);
01082 if (ply->storage_mode == (e_ply_storage_mode) (-1)) return 0;
01083 if (ply->storage_mode == PLY_ASCII) ply->idriver = &ply_idriver_ascii;
01084 else if (ply->storage_mode == ply_arch_endian())
01085 ply->idriver = &ply_idriver_binary;
01086 else ply->idriver = &ply_idriver_binary_reverse;
01087 if (!ply_read_word(ply)) return 0;
01088 if (strcmp(BWORD(ply), "1.0")) return 0;
01089 if (!ply_read_word(ply)) return 0;
01090 return 1;
01091 }
01092
01093 static int ply_read_header_comment(p_ply ply) {
01094 assert(ply && ply->fp && ply->io_mode == PLY_READ);
01095 if (strcmp(BWORD(ply), "comment")) return 0;
01096 if (!ply_read_line(ply)) return 0;
01097 if (!ply_add_comment(ply, BLINE(ply))) return 0;
01098 if (!ply_read_word(ply)) return 0;
01099 return 1;
01100 }
01101
01102 static int ply_read_header_obj_info(p_ply ply) {
01103 assert(ply && ply->fp && ply->io_mode == PLY_READ);
01104 if (strcmp(BWORD(ply), "obj_info")) return 0;
01105 if (!ply_read_line(ply)) return 0;
01106 if (!ply_add_obj_info(ply, BLINE(ply))) return 0;
01107 if (!ply_read_word(ply)) return 0;
01108 return 1;
01109 }
01110
01111 static int ply_read_header_property(p_ply ply) {
01112 p_ply_element element = NULL;
01113 p_ply_property property = NULL;
01114
01115 if (strcmp(BWORD(ply), "property")) return 0;
01116 element = &ply->element[ply->nelements-1];
01117 property = ply_grow_property(ply, element);
01118 if (!property) return 0;
01119
01120 if (!ply_read_word(ply)) return 0;
01121 property->type = (e_ply_type)ply_find_string(BWORD(ply), ply_type_list);
01122 if (property->type == (e_ply_type) (-1)) return 0;
01123 if (property->type == PLY_LIST) {
01124
01125 if (!ply_read_word(ply)) return 0;
01126 property->length_type = (e_ply_type)ply_find_string(BWORD(ply), ply_type_list);
01127 if (property->length_type == (e_ply_type) (-1)) return 0;
01128 if (!ply_read_word(ply)) return 0;
01129 property->value_type = (e_ply_type)ply_find_string(BWORD(ply), ply_type_list);
01130 if (property->value_type == (e_ply_type) (-1)) return 0;
01131 }
01132
01133 if (!ply_read_word(ply)) return 0;
01134 strcpy(property->name, BWORD(ply));
01135 if (!ply_read_word(ply)) return 0;
01136 return 1;
01137 }
01138
01139 static int ply_read_header_element(p_ply ply) {
01140 p_ply_element element = NULL;
01141 long dummy;
01142 assert(ply && ply->fp && ply->io_mode == PLY_READ);
01143 if (strcmp(BWORD(ply), "element")) return 0;
01144
01145 element = ply_grow_element(ply);
01146 if (!element) return 0;
01147
01148 if (!ply_read_word(ply)) return 0;
01149 strcpy(element->name, BWORD(ply));
01150
01151 if (!ply_read_word(ply)) return 0;
01152 if (sscanf(BWORD(ply), "%ld", &dummy) != 1) {
01153 ply_error(ply, "Expected number got '%s'", BWORD(ply));
01154 return 0;
01155 }
01156 element->ninstances = dummy;
01157
01158 if (!ply_read_word(ply)) return 0;
01159 while (ply_read_header_property(ply) ||
01160 ply_read_header_comment(ply) || ply_read_header_obj_info(ply))
01161 ;
01162 return 1;
01163 }
01164
01165 static void ply_error_cb(const char *message) {
01166 fprintf(stderr, "RPly: %s\n", message);
01167 }
01168
01169 static void ply_error(p_ply ply, const char *fmt, ...) {
01170 char buffer[1024];
01171 va_list ap;
01172 va_start(ap, fmt);
01173 vsprintf(buffer, fmt, ap);
01174 va_end(ap);
01175 ply->error_cb(buffer);
01176 }
01177
01178 static e_ply_storage_mode ply_arch_endian(void) {
01179 unsigned long i = 1;
01180 unsigned char *s = (unsigned char *) &i;
01181 if (*s == 1) return PLY_LITTLE_ENDIAN;
01182 else return PLY_BIG_ENDIAN;
01183 }
01184
01185 static int ply_type_check(void) {
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202 return 1;
01203 }
01204
01205
01206
01207
01208 static int oascii_int8(p_ply ply, double value) {
01209 if (value > CHAR_MAX || value < CHAR_MIN) return 0;
01210 return fprintf(ply->fp, "%d ", (char) value) > 0;
01211 }
01212
01213 static int oascii_uint8(p_ply ply, double value) {
01214 if (value > UCHAR_MAX || value < 0) return 0;
01215 return fprintf(ply->fp, "%d ", (unsigned char) value) > 0;
01216 }
01217
01218 static int oascii_int16(p_ply ply, double value) {
01219 if (value > SHRT_MAX || value < SHRT_MIN) return 0;
01220 return fprintf(ply->fp, "%d ", (short) value) > 0;
01221 }
01222
01223 static int oascii_uint16(p_ply ply, double value) {
01224 if (value > USHRT_MAX || value < 0) return 0;
01225 return fprintf(ply->fp, "%d ", (unsigned short) value) > 0;
01226 }
01227
01228 static int oascii_int32(p_ply ply, double value) {
01229 if (value > LONG_MAX || value < LONG_MIN) return 0;
01230 return fprintf(ply->fp, "%d ", (int) value) > 0;
01231 }
01232
01233 static int oascii_uint32(p_ply ply, double value) {
01234 if (value > ULONG_MAX || value < 0) return 0;
01235 return fprintf(ply->fp, "%d ", (unsigned int) value) > 0;
01236 }
01237
01238 static int oascii_float32(p_ply ply, double value) {
01239 if (value < -FLT_MAX || value > FLT_MAX) return 0;
01240 return fprintf(ply->fp, "%g ", (float) value) > 0;
01241 }
01242
01243 static int oascii_float64(p_ply ply, double value) {
01244 if (value < -DBL_MAX || value > DBL_MAX) return 0;
01245 return fprintf(ply->fp, "%g ", value) > 0;
01246 }
01247
01248 static int obinary_int8(p_ply ply, double value) {
01249 char int8 = (char) value;
01250 if (value > CHAR_MAX || value < CHAR_MIN) return 0;
01251 return ply->odriver->ochunk(ply, &int8, sizeof(int8));
01252 }
01253
01254 static int obinary_uint8(p_ply ply, double value) {
01255 unsigned char uint8 = (unsigned char) value;
01256 if (value > UCHAR_MAX || value < 0) return 0;
01257 return ply->odriver->ochunk(ply, &uint8, sizeof(uint8));
01258 }
01259
01260 static int obinary_int16(p_ply ply, double value) {
01261 short int16 = (short) value;
01262 if (value > SHRT_MAX || value < SHRT_MIN) return 0;
01263 return ply->odriver->ochunk(ply, &int16, sizeof(int16));
01264 }
01265
01266 static int obinary_uint16(p_ply ply, double value) {
01267 unsigned short uint16 = (unsigned short) value;
01268 if (value > USHRT_MAX || value < 0) return 0;
01269 return ply->odriver->ochunk(ply, &uint16, sizeof(uint16));
01270 }
01271
01272 static int obinary_int32(p_ply ply, double value) {
01273 long int32 = (long) value;
01274 if (value > LONG_MAX || value < LONG_MIN) return 0;
01275 return ply->odriver->ochunk(ply, &int32, sizeof(int32));
01276 }
01277
01278 static int obinary_uint32(p_ply ply, double value) {
01279 unsigned long uint32 = (unsigned long) value;
01280 if (value > ULONG_MAX || value < 0) return 0;
01281 return ply->odriver->ochunk(ply, &uint32, sizeof(uint32));
01282 }
01283
01284 static int obinary_float32(p_ply ply, double value) {
01285 float float32 = (float) value;
01286 if (value > FLT_MAX || value < -FLT_MAX) return 0;
01287 return ply->odriver->ochunk(ply, &float32, sizeof(float32));
01288 }
01289
01290 static int obinary_float64(p_ply ply, double value) {
01291 return ply->odriver->ochunk(ply, &value, sizeof(value));
01292 }
01293
01294
01295
01296
01297 static int iascii_int8(p_ply ply, double *value) {
01298 char *end;
01299 if (!ply_read_word(ply)) return 0;
01300 *value = strtol(BWORD(ply), &end, 10);
01301 if (*end || *value > CHAR_MAX || *value < CHAR_MIN) return 0;
01302 return 1;
01303 }
01304
01305 static int iascii_uint8(p_ply ply, double *value) {
01306 char *end;
01307 if (!ply_read_word(ply)) return 0;
01308 *value = strtol(BWORD(ply), &end, 10);
01309 if (*end || *value > UCHAR_MAX || *value < 0) return 0;
01310 return 1;
01311 }
01312
01313 static int iascii_int16(p_ply ply, double *value) {
01314 char *end;
01315 if (!ply_read_word(ply)) return 0;
01316 *value = strtol(BWORD(ply), &end, 10);
01317 if (*end || *value > SHRT_MAX || *value < SHRT_MIN) return 0;
01318 return 1;
01319 }
01320
01321 static int iascii_uint16(p_ply ply, double *value) {
01322 char *end;
01323 if (!ply_read_word(ply)) return 0;
01324 *value = strtol(BWORD(ply), &end, 10);
01325 if (*end || *value > USHRT_MAX || *value < 0) return 0;
01326 return 1;
01327 }
01328
01329 static int iascii_int32(p_ply ply, double *value) {
01330 char *end;
01331 if (!ply_read_word(ply)) return 0;
01332 *value = strtol(BWORD(ply), &end, 10);
01333 if (*end || *value > LONG_MAX || *value < LONG_MIN) return 0;
01334 return 1;
01335 }
01336
01337 static int iascii_uint32(p_ply ply, double *value) {
01338 char *end;
01339 if (!ply_read_word(ply)) return 0;
01340 *value = strtol(BWORD(ply), &end, 10);
01341 if (*end || *value < 0) return 0;
01342 return 1;
01343 }
01344
01345 static int iascii_float32(p_ply ply, double *value) {
01346 char *end;
01347 if (!ply_read_word(ply)) return 0;
01348 *value = strtod(BWORD(ply), &end);
01349 if (*end || *value < -FLT_MAX || *value > FLT_MAX) return 0;
01350 return 1;
01351 }
01352
01353 static int iascii_float64(p_ply ply, double *value) {
01354 char *end;
01355 if (!ply_read_word(ply)) return 0;
01356 *value = strtod(BWORD(ply), &end);
01357 if (*end || *value < -DBL_MAX || *value > DBL_MAX) return 0;
01358 return 1;
01359 }
01360
01361 static int ibinary_int8(p_ply ply, double *value) {
01362 char int8;
01363 if (!ply->idriver->ichunk(ply, &int8, 1)) return 0;
01364 *value = int8;
01365 return 1;
01366 }
01367
01368 static int ibinary_uint8(p_ply ply, double *value) {
01369 unsigned char uint8;
01370 if (!ply->idriver->ichunk(ply, &uint8, 1)) return 0;
01371 *value = uint8;
01372 return 1;
01373 }
01374
01375 static int ibinary_int16(p_ply ply, double *value) {
01376 short int16;
01377 if (!ply->idriver->ichunk(ply, &int16, sizeof(int16))) return 0;
01378 *value = int16;
01379 return 1;
01380 }
01381
01382 static int ibinary_uint16(p_ply ply, double *value) {
01383 unsigned short uint16;
01384 if (!ply->idriver->ichunk(ply, &uint16, sizeof(uint16))) return 0;
01385 *value = uint16;
01386 return 1;
01387 }
01388
01389 static int ibinary_int32(p_ply ply, double *value) {
01390 long int32;
01391 if (!ply->idriver->ichunk(ply, &int32, sizeof(int32))) return 0;
01392 *value = int32;
01393 return 1;
01394 }
01395
01396 static int ibinary_uint32(p_ply ply, double *value) {
01397 unsigned long uint32;
01398 if (!ply->idriver->ichunk(ply, &uint32, sizeof(uint32))) return 0;
01399 *value = uint32;
01400 return 1;
01401 }
01402
01403 static int ibinary_float32(p_ply ply, double *value) {
01404 float float32;
01405 if (!ply->idriver->ichunk(ply, &float32, sizeof(float32))) return 0;
01406 *value = float32;
01407 ply_reverse(&float32, sizeof(float32));
01408 return 1;
01409 }
01410
01411 static int ibinary_float64(p_ply ply, double *value) {
01412 return ply->idriver->ichunk(ply, value, sizeof(double));
01413 }
01414
01415
01416
01417
01418 t_ply_idriver ply_idriver_ascii = {
01419 { iascii_int8, iascii_uint8, iascii_int16, iascii_uint16,
01420 iascii_int32, iascii_uint32, iascii_float32, iascii_float64,
01421 iascii_int8, iascii_uint8, iascii_int16, iascii_uint16,
01422 iascii_int32, iascii_uint32, iascii_float32, iascii_float64
01423 },
01424 NULL,
01425 "ascii input"
01426 };
01427
01428 t_ply_idriver ply_idriver_binary = {
01429 { ibinary_int8, ibinary_uint8, ibinary_int16, ibinary_uint16,
01430 ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64,
01431 ibinary_int8, ibinary_uint8, ibinary_int16, ibinary_uint16,
01432 ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64
01433 },
01434 ply_read_chunk,
01435 "binary input"
01436 };
01437
01438 t_ply_idriver ply_idriver_binary_reverse = {
01439 { ibinary_int8, ibinary_uint8, ibinary_int16, ibinary_uint16,
01440 ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64,
01441 ibinary_int8, ibinary_uint8, ibinary_int16, ibinary_uint16,
01442 ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64
01443 },
01444 ply_read_chunk_reverse,
01445 "reverse binary input"
01446 };
01447
01448 t_ply_odriver ply_odriver_ascii = {
01449 { oascii_int8, oascii_uint8, oascii_int16, oascii_uint16,
01450 oascii_int32, oascii_uint32, oascii_float32, oascii_float64,
01451 oascii_int8, oascii_uint8, oascii_int16, oascii_uint16,
01452 oascii_int32, oascii_uint32, oascii_float32, oascii_float64
01453 },
01454 NULL,
01455 "ascii output"
01456 };
01457
01458 t_ply_odriver ply_odriver_binary = {
01459 { obinary_int8, obinary_uint8, obinary_int16, obinary_uint16,
01460 obinary_int32, obinary_uint32, obinary_float32, obinary_float64,
01461 obinary_int8, obinary_uint8, obinary_int16, obinary_uint16,
01462 obinary_int32, obinary_uint32, obinary_float32, obinary_float64
01463 },
01464 ply_write_chunk,
01465 "binary output"
01466 };
01467
01468 t_ply_odriver ply_odriver_binary_reverse = {
01469 { obinary_int8, obinary_uint8, obinary_int16, obinary_uint16,
01470 obinary_int32, obinary_uint32, obinary_float32, obinary_float64,
01471 obinary_int8, obinary_uint8, obinary_int16, obinary_uint16,
01472 obinary_int32, obinary_uint32, obinary_float32, obinary_float64
01473 },
01474 ply_write_chunk_reverse,
01475 "reverse binary output"
01476 };
01477
01478 }
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501