Tucano  0.1
A library for rapid prototyping with modern OpenGL and GLSL
rply.hpp
Go to the documentation of this file.
1 #ifndef RPLY_H
2 #define RPLY_H
3 /* ----------------------------------------------------------------------
4  * RPly library, read/write PLY files
5  * Diego Nehab, IMPA
6  * http://www.impa.br/~diego/software/rply
7  *
8  * C++ port by Thiago Perrotta, LCG @ UFRJ
9  * http://www.lcg.ufrj.br/Members/thiago
10  *
11  * This library is distributed under the MIT License. See notice
12  * at the end of this file.
13  * ---------------------------------------------------------------------- */
14 
15 #define RPLY_VERSION "RPly 1.1.3"
16 #define RPLY_COPYRIGHT "Copyright (C) 2003-2013 Diego Nehab, 2014 Thiago Perrotta"
17 #define RPLY_AUTHORS "Diego Nehab, Thiago Perrotta"
18 
19 #include <cassert>
20 #include <cctype>
21 #include <cfloat>
22 #include <climits>
23 #include <cstdarg>
24 #include <cstddef>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 
29 
30 /* ----------------------------------------------------------------------
31  * Make sure we get our integer types right
32  * ---------------------------------------------------------------------- */
33 #if defined(_MSC_VER) && (_MSC_VER < 1600)
34 /* C99 stdint.h only supported in MSVC++ 10.0 and up */
35 typedef __int8 t_ply_int8;
36 typedef __int16 t_ply_int16;
37 typedef __int32 t_ply_int32;
38 typedef unsigned __int8 t_ply_uint8;
39 typedef unsigned __int16 t_ply_uint16;
40 typedef unsigned __int32 t_ply_uint32;
41 # define PLY_INT8_MAX (127)
42 # define PLY_INT8_MIN (-PLY_INT8_MAX-1)
43 # define PLY_INT16_MAX (32767)
44 # define PLY_INT16_MIN (-PLY_INT16_MAX-1)
45 # define PLY_INT32_MAX (2147483647)
46 # define PLY_INT32_MIN (-PLY_INT32_MAX-1)
47 # define PLY_UINT8_MAX (255)
48 # define PLY_UINT16_MAX (65535)
49 # define PLY_UINT32_MAX (4294967295)
50 #else
51 /****************************************************************
52  ** Under FreeBSD the stdint.h, cstdint, sys/_stdint.h and x86/_sdtint.h
53  ** not work correct because this need be include in C not in C++
54  ** a simple copy of x86/_stdint.h was enougth
55  ** by Nilton Jose Rizzo
56  ** *************************************************************/
57 typedef int8_t t_ply_int8;
58 typedef int16_t t_ply_int16;
59 typedef int32_t t_ply_int32;
60 typedef uint8_t t_ply_uint8;
61 typedef uint16_t t_ply_uint16;
62 typedef uint32_t t_ply_uint32;
63 # ifdef __FreeBSD__
64 
65 # define INT8_MIN (-0x7f-1)
66 # define INT16_MIN (-0x7fff-1)
67 # define INT32_MIN (-0x7fffffff-1)
68 
69 # define INT8_MAX 0x7f
70 # define INT16_MAX 0x7fff
71 # define INT32_MAX 0x7fffffff
72 
73 # define UINT8_MAX 0xff
74 # define UINT16_MAX 0xffff
75 # define UINT32_MAX 0xffffffffU
76 
77 # ifdef __LP64__
78 # define INT64_MIN (-0x7fffffffffffffff-1)
79 # define INT64_MAX 0x7fffffffffffffff
80 # define UINT64_MAX 0xffffffffffffffff
81 # else
82 # define INT64_MIN (-0x7fffffffffffffffLL-1)
83 # define INT64_MAX 0x7fffffffffffffffLL
84 # define UINT64_MAX 0xffffffffffffffffULL
85 # endif
86 # else
87 # include <stdint.h>
88 # endif
89 # define PLY_INT8_MIN INT8_MIN
90 # define PLY_INT8_MAX INT8_MAX
91 # define PLY_INT16_MIN INT16_MIN
92 # define PLY_INT16_MAX INT16_MAX
93 # define PLY_INT32_MIN INT32_MIN
94 # define PLY_INT32_MAX INT32_MAX
95 # define PLY_UINT8_MAX UINT8_MAX
96 # define PLY_UINT16_MAX UINT16_MAX
97 # define PLY_UINT32_MAX UINT32_MAX
98 #endif
99 
100 
101 
102 /* ----------------------------------------------------------------------
103  * Types
104  * ---------------------------------------------------------------------- */
105 /* structures are opaque */
106 typedef struct t_ply_ *p_ply;
110 
111 /* ply format mode type */
116  PLY_DEFAULT /* has to be the last in enum */
117 }; /* order matches ply_storage_mode_list */
118 
119 /* ply data type */
125  PLY_LIST /* has to be the last in enum */
126 }; /* order matches ply_type_list */
127 
128 /* ----------------------------------------------------------------------
129  * Error callback prototype
130  *
131  * message: error message
132  * ply: handle returned by ply_open or ply_create
133  * ---------------------------------------------------------------------- */
134 typedef void (*p_ply_error_cb)(p_ply ply, const char *message);
135 
136 /* ----------------------------------------------------------------------
137  * Gets user data from within an error callback
138  *
139  * ply: handle returned by ply_open or ply_create
140  * idata,pdata: contextual information set in ply_open or ply_create
141  * ---------------------------------------------------------------------- */
142 inline int ply_get_ply_user_data(p_ply ply, void **pdata, long *idata);
143 
144 /* ----------------------------------------------------------------------
145  * Opens a PLY file for reading (fails if file is not a PLY file)
146  *
147  * name: file name
148  * error_cb: error callback function
149  * idata,pdata: contextual information available to users
150  *
151  * Returns 1 if successful, 0 otherwise
152  * ---------------------------------------------------------------------- */
153 inline p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata,
154  void *pdata);
155 
156 /* ----------------------------------------------------------------------
157  * Reads and parses the header of a PLY file returned by ply_open
158  *
159  * ply: handle returned by ply_open
160  *
161  * Returns 1 if successfull, 0 otherwise
162  * ---------------------------------------------------------------------- */
163 inline int ply_read_header(p_ply ply);
164 
165 /* ----------------------------------------------------------------------
166  * Property reading callback prototype
167  *
168  * argument: parameters for property being processed when callback is called
169  *
170  * Returns 1 if should continue processing file, 0 if should abort.
171  * ---------------------------------------------------------------------- */
172 typedef int (*p_ply_read_cb)(p_ply_argument argument);
173 
174 /* ----------------------------------------------------------------------
175  * Sets up callbacks for property reading after header was parsed
176  *
177  * ply: handle returned by ply_open
178  * element_name: element where property is
179  * property_name: property to associate element with
180  * read_cb: function to be called for each property value
181  * pdata/idata: user data that will be passed to callback
182  *
183  * Returns 0 if no element or no property in element, returns the
184  * number of element instances otherwise.
185  * ---------------------------------------------------------------------- */
186 inline long ply_set_read_cb(p_ply ply, const char *element_name,
187  const char *property_name, p_ply_read_cb read_cb,
188  void *pdata, long idata);
189 
190 /* ----------------------------------------------------------------------
191  * Returns information about the element originating a callback
192  *
193  * argument: handle to argument
194  * element: receives a the element handle (if non-null)
195  * instance_index: receives the index of the current element instance
196  * (if non-null)
197  *
198  * Returns 1 if successfull, 0 otherwise
199  * ---------------------------------------------------------------------- */
200 inline int ply_get_argument_element(p_ply_argument argument,
201  p_ply_element *element, long *instance_index);
202 
203 /* ----------------------------------------------------------------------
204  * Returns information about the property originating a callback
205  *
206  * argument: handle to argument
207  * property: receives the property handle (if non-null)
208  * length: receives the number of values in this property (if non-null)
209  * value_index: receives the index of current property value (if non-null)
210  *
211  * Returns 1 if successfull, 0 otherwise
212  * ---------------------------------------------------------------------- */
213 inline int ply_get_argument_property(p_ply_argument argument,
214  p_ply_property *property, long *length, long *value_index);
215 
216 /* ----------------------------------------------------------------------
217  * Returns user data associated with callback
218  *
219  * pdata: receives a copy of user custom data pointer (if non-null)
220  * idata: receives a copy of user custom data integer (if non-null)
221  *
222  * Returns 1 if successfull, 0 otherwise
223  * ---------------------------------------------------------------------- */
224 inline int ply_get_argument_user_data(p_ply_argument argument, void **pdata,
225  long *idata);
226 
227 /* ----------------------------------------------------------------------
228  * Returns the value associated with a callback
229  *
230  * argument: handle to argument
231  *
232  * Returns the current data item
233  * ---------------------------------------------------------------------- */
234 inline double ply_get_argument_value(p_ply_argument argument);
235 
236 /* ----------------------------------------------------------------------
237  * Reads all elements and properties calling the callbacks defined with
238  * calls to ply_set_read_cb
239  *
240  * ply: handle returned by ply_open
241  *
242  * Returns 1 if successfull, 0 otherwise
243  * ---------------------------------------------------------------------- */
244 inline int ply_read(p_ply ply);
245 
246 /* ----------------------------------------------------------------------
247  * Iterates over all elements by returning the next element.
248  * Call with NULL to return handle to first element.
249  *
250  * ply: handle returned by ply_open
251  * last: handle of last element returned (NULL for first element)
252  *
253  * Returns element if successfull or NULL if no more elements
254  * ---------------------------------------------------------------------- */
255 inline p_ply_element ply_get_next_element(p_ply ply, p_ply_element last);
256 
257 /* ----------------------------------------------------------------------
258  * Iterates over all comments by returning the next comment.
259  * Call with NULL to return pointer to first comment.
260  *
261  * ply: handle returned by ply_open
262  * last: pointer to last comment returned (NULL for first comment)
263  *
264  * Returns comment if successfull or NULL if no more comments
265  * ---------------------------------------------------------------------- */
266 inline const char *ply_get_next_comment(p_ply ply, const char *last);
267 
268 /* ----------------------------------------------------------------------
269  * Iterates over all obj_infos by returning the next obj_info.
270  * Call with NULL to return pointer to first obj_info.
271  *
272  * ply: handle returned by ply_open
273  * last: pointer to last obj_info returned (NULL for first obj_info)
274  *
275  * Returns obj_info if successfull or NULL if no more obj_infos
276  * ---------------------------------------------------------------------- */
277 inline const char *ply_get_next_obj_info(p_ply ply, const char *last);
278 
279 /* ----------------------------------------------------------------------
280  * Returns information about an element
281  *
282  * element: element of interest
283  * name: receives a pointer to internal copy of element name (if non-null)
284  * ninstances: receives the number of instances of this element (if non-null)
285  *
286  * Returns 1 if successfull or 0 otherwise
287  * ---------------------------------------------------------------------- */
288 inline int ply_get_element_info(p_ply_element element, const char** name,
289  long *ninstances);
290 
291 /* ----------------------------------------------------------------------
292  * Iterates over all properties by returning the next property.
293  * Call with NULL to return handle to first property.
294  *
295  * element: handle of element with the properties of interest
296  * last: handle of last property returned (NULL for first property)
297  *
298  * Returns element if successfull or NULL if no more properties
299  * ---------------------------------------------------------------------- */
300 inline p_ply_property ply_get_next_property(p_ply_element element,
301  p_ply_property last);
302 
303 /* ----------------------------------------------------------------------
304  * Returns information about a property
305  *
306  * property: handle to property of interest
307  * name: receives a pointer to internal copy of property name (if non-null)
308  * type: receives the property type (if non-null)
309  * length_type: for list properties, receives the scalar type of
310  * the length field (if non-null)
311  * value_type: for list properties, receives the scalar type of the value
312  * fields (if non-null)
313  *
314  * Returns 1 if successfull or 0 otherwise
315  * ---------------------------------------------------------------------- */
316 inline int ply_get_property_info(p_ply_property property, const char** name,
317  e_ply_type *type, e_ply_type *length_type, e_ply_type *value_type);
318 
319 /* ----------------------------------------------------------------------
320  * Creates new PLY file
321  *
322  * name: file name
323  * storage_mode: file format mode
324  *
325  * Returns handle to PLY file if successfull, NULL otherwise
326  * ---------------------------------------------------------------------- */
327 inline p_ply ply_create(const char *name, e_ply_storage_mode storage_mode,
328  p_ply_error_cb error_cb, long idata, void *pdata);
329 
330 /* ----------------------------------------------------------------------
331  * Adds a new element to the PLY file created by ply_create
332  *
333  * ply: handle returned by ply_create
334  * name: name of new element
335  * ninstances: number of element of this time in file
336  *
337  * Returns 1 if successfull, 0 otherwise
338  * ---------------------------------------------------------------------- */
339 inline int ply_add_element(p_ply ply, const char *name, long ninstances);
340 
341 /* ----------------------------------------------------------------------
342  * Adds a new property to the last element added by ply_add_element
343  *
344  * ply: handle returned by ply_create
345  * name: name of new property
346  * type: property type
347  * length_type: scalar type of length field of a list property
348  * value_type: scalar type of value fields of a list property
349  *
350  * Returns 1 if successfull, 0 otherwise
351  * ---------------------------------------------------------------------- */
352 inline int ply_add_property(p_ply ply, const char *name, e_ply_type type,
353  e_ply_type length_type, e_ply_type value_type);
354 
355 /* ----------------------------------------------------------------------
356  * Adds a new list property to the last element added by ply_add_element
357  *
358  * ply: handle returned by ply_create
359  * name: name of new property
360  * length_type: scalar type of length field of a list property
361  * value_type: scalar type of value fields of a list property
362  *
363  * Returns 1 if successfull, 0 otherwise
364  * ---------------------------------------------------------------------- */
365 inline int ply_add_list_property(p_ply ply, const char *name,
366  e_ply_type length_type, e_ply_type value_type);
367 
368 /* ----------------------------------------------------------------------
369  * Adds a new property to the last element added by ply_add_element
370  *
371  * ply: handle returned by ply_create
372  * name: name of new property
373  * type: property type
374  *
375  * Returns 1 if successfull, 0 otherwise
376  * ---------------------------------------------------------------------- */
377 inline int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type);
378 
379 /* ----------------------------------------------------------------------
380  * Adds a new comment item
381  *
382  * ply: handle returned by ply_create
383  * comment: pointer to string with comment text
384  *
385  * Returns 1 if successfull, 0 otherwise
386  * ---------------------------------------------------------------------- */
387 inline int ply_add_comment(p_ply ply, const char *comment);
388 
389 /* ----------------------------------------------------------------------
390  * Adds a new obj_info item
391  *
392  * ply: handle returned by ply_create
393  * comment: pointer to string with obj_info data
394  *
395  * Returns 1 if successfull, 0 otherwise
396  * ---------------------------------------------------------------------- */
397 inline int ply_add_obj_info(p_ply ply, const char *obj_info);
398 
399 /* ----------------------------------------------------------------------
400  * Writes the PLY file header after all element and properties have been
401  * defined by calls to ply_add_element and ply_add_property
402  *
403  * ply: handle returned by ply_create
404  *
405  * Returns 1 if successfull, 0 otherwise
406  * ---------------------------------------------------------------------- */
407 inline int ply_write_header(p_ply ply);
408 
409 /* ----------------------------------------------------------------------
410  * Writes one property value, in the order they should be written to the
411  * file. For each element type, write all elements of that type in order.
412  * For each element, write all its properties in order. For scalar
413  * properties, just write the value. For list properties, write the length
414  * and then each of the values.
415  *
416  * ply: handle returned by ply_create
417  *
418  * Returns 1 if successfull, 0 otherwise
419  * ---------------------------------------------------------------------- */
420 inline int ply_write(p_ply ply, double value);
421 
422 /* ----------------------------------------------------------------------
423  * Closes a PLY file handle. Releases all memory used by handle
424  *
425  * ply: handle to be closed.
426  *
427  * Returns 1 if successfull, 0 otherwise
428  * ---------------------------------------------------------------------- */
429 inline int ply_close(p_ply ply);
430 
431 
432 
433 /* ----------------------------------------------------------------------
434  * Constants
435  * ---------------------------------------------------------------------- */
436 const int WORDSIZE = 256;
437 const int LINESIZE = 1024;
438 const int BUFFERSIZE = (8*1024);
439 
443 };
444 
445 static const char *const ply_storage_mode_list[] = {
446  "binary_big_endian", "binary_little_endian", "ascii", NULL
447 }; /* order matches e_ply_storage_mode enum */
448 
449 static const char *const ply_type_list[] = {
450  "int8", "uint8", "int16", "uint16",
451  "int32", "uint32", "float32", "float64",
452  "char", "uchar", "short", "ushort",
453  "int", "uint", "float", "double",
454  "list", NULL
455 }; /* order matches e_ply_type enum */
456 
457 /* ----------------------------------------------------------------------
458  * Property reading callback argument
459  *
460  * element: name of element being processed
461  * property: name of property being processed
462  * nelements: number of elements of this kind in file
463  * instance_index: index current element of this kind being processed
464  * length: number of values in current list (or 1 for scalars)
465  * value_index: index of current value int this list (or 0 for scalars)
466  * value: value of property
467  * pdata/idata: user data defined with ply_set_cb
468  *
469  * Returns handle to PLY file if succesful, NULL otherwise.
470  * ---------------------------------------------------------------------- */
472  p_ply_element element;
474  p_ply_property property;
476  double value;
477  void *pdata;
478  long idata;
479 };
480 
481 /* ----------------------------------------------------------------------
482  * Property information
483  *
484  * name: name of this property
485  * type: type of this property (list or type of scalar value)
486  * length_type, value_type: type of list property count and values
487  * read_cb: function to be called when this property is called
488  *
489  * Returns 1 if should continue processing file, 0 if should abort.
490  * ---------------------------------------------------------------------- */
492  char name[WORDSIZE];
493  e_ply_type type, value_type, length_type;
495  void *pdata;
496  long idata;
497 };
498 
499 /* ----------------------------------------------------------------------
500  * Element information
501  *
502  * name: name of this property
503  * ninstances: number of elements of this type in file
504  * property: property descriptions for this element
505  * nproperty: number of properties in this element
506  *
507  * Returns 1 if should continue processing file, 0 if should abort.
508  * ---------------------------------------------------------------------- */
510  char name[WORDSIZE];
512  p_ply_property property;
514 };
515 
516 /* ----------------------------------------------------------------------
517  * Input/output driver
518  *
519  * Depending on file mode, different functions are used to read/write
520  * property fields. The drivers make it transparent to read/write in ascii,
521  * big endian or little endian cases.
522  * ---------------------------------------------------------------------- */
523 typedef int (*p_ply_ihandler)(p_ply ply, double *value);
524 typedef int (*p_ply_ichunk)(p_ply ply, void *anydata, size_t size);
526  p_ply_ihandler ihandler[16];
528  const char *name;
529 };
531 
532 typedef int (*p_ply_ohandler)(p_ply ply, double value);
533 typedef int (*p_ply_ochunk)(p_ply ply, void *anydata, size_t size);
535  p_ply_ohandler ohandler[16];
537  const char *name;
538 };
540 
541 /* ----------------------------------------------------------------------
542  * Ply file handle.
543  *
544  * io_mode: read or write (from e_ply_io_mode)
545  * storage_mode: mode of file associated with handle (from e_ply_storage_mode)
546  * element: elements description for this file
547  * nelement: number of different elements in file
548  * comment: comments for this file
549  * ncomments: number of comments in file
550  * obj_info: obj_info items for this file
551  * nobj_infos: number of obj_info items in file
552  * fp: file pointer associated with ply file
553  * rn: skip extra char after end_header?
554  * buffer: last word/chunck of data read from ply file
555  * buffer_first, buffer_last: interval of untouched good data in buffer
556  * buffer_token: start of parsed token (line or word) in buffer
557  * idriver, odriver: input driver used to get property fields from file
558  * argument: storage space for callback arguments
559  * welement, wproperty: element/property type being written
560  * winstance_index: index of instance of current element being written
561  * wvalue_index: index of list property value being written
562  * wlength: number of values in list property being written
563  * error_cb: error callback
564  * pdata/idata: user data defined with ply_open/ply_create
565  * ---------------------------------------------------------------------- */
566 struct t_ply_ {
569  p_ply_element element;
570  long nelements;
571  char *comment;
572  long ncomments;
573  char *obj_info;
575  FILE *fp;
576  int rn;
577  char buffer[BUFFERSIZE];
578  size_t buffer_first, buffer_token, buffer_last;
582  long welement, wproperty;
583  long winstance_index, wvalue_index, wlength;
585  void *pdata;
586  long idata;
587 };
588 
589 /* ----------------------------------------------------------------------
590  * I/O functions and drivers
591  * ---------------------------------------------------------------------- */
592 static int ply_read_word(p_ply ply);
593 static int ply_check_word(p_ply ply);
594 static void ply_finish_word(p_ply ply, size_t size);
595 static int ply_read_line(p_ply ply);
596 static int ply_check_line(p_ply ply);
597 static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size);
598 static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size);
599 static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size);
600 static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size);
601 static void ply_reverse(void *anydata, size_t size);
602 
603 /* ----------------------------------------------------------------------
604  * String functions
605  * ---------------------------------------------------------------------- */
606 static int ply_find_string(const char *item, const char* const list[]);
607 static p_ply_element ply_find_element(p_ply ply, const char *name);
608 static p_ply_property ply_find_property(p_ply_element element,
609  const char *name);
610 
611 /* ----------------------------------------------------------------------
612  * Header parsing
613  * ---------------------------------------------------------------------- */
614 static int ply_read_header_magic(p_ply ply);
615 static int ply_read_header_format(p_ply ply);
616 static int ply_read_header_comment(p_ply ply);
617 static int ply_read_header_obj_info(p_ply ply);
618 static int ply_read_header_property(p_ply ply);
619 static int ply_read_header_element(p_ply ply);
620 
621 /* ----------------------------------------------------------------------
622  * Error handling
623  * ---------------------------------------------------------------------- */
624 static void ply_error_cb(p_ply ply, const char *message);
625 static void ply_ferror(p_ply ply, const char *fmt, ...);
626 
627 /* ----------------------------------------------------------------------
628  * Memory allocation and initialization
629  * ---------------------------------------------------------------------- */
630 static void ply_init(p_ply ply);
631 static void ply_element_init(p_ply_element element);
632 static void ply_property_init(p_ply_property property);
633 static p_ply ply_alloc(void);
634 static p_ply_element ply_grow_element(p_ply ply);
635 static p_ply_property ply_grow_property(p_ply ply, p_ply_element element);
636 static void *ply_grow_array(p_ply ply, void **pointer, long *nmemb, long size);
637 
638 /* ----------------------------------------------------------------------
639  * Special functions
640  * ---------------------------------------------------------------------- */
642 static int ply_type_check(void);
643 
644 /* ----------------------------------------------------------------------
645  * Auxiliary read functions
646  * ---------------------------------------------------------------------- */
647 static int ply_read_element(p_ply ply, p_ply_element element,
648  p_ply_argument argument);
649 static int ply_read_property(p_ply ply, p_ply_element element,
650  p_ply_property property, p_ply_argument argument);
651 static int ply_read_list_property(p_ply ply, p_ply_element element,
652  p_ply_property property, p_ply_argument argument);
653 static int ply_read_scalar_property(p_ply ply, p_ply_element element,
654  p_ply_property property, p_ply_argument argument);
655 
656 /* ----------------------------------------------------------------------
657  * Buffer support functions
658  * ---------------------------------------------------------------------- */
659 /* pointers to tokenized word and line in buffer */
660 #define BWORD(p) (p->buffer + p->buffer_token)
661 #define BLINE(p) (p->buffer + p->buffer_token)
662 
663 /* pointer to start of untouched bytes in buffer */
664 #define BFIRST(p) (p->buffer + p->buffer_first)
665 
666 /* number of bytes untouched in buffer */
667 #define BSIZE(p) (p->buffer_last - p->buffer_first)
668 
669 /* consumes data from buffer */
670 #define BSKIP(p, s) (p->buffer_first += s)
671 
672 /* refills the buffer */
673 static int BREFILL(p_ply ply) {
674  /* move untouched data to beginning of buffer */
675  size_t size = BSIZE(ply);
676  memmove(ply->buffer, BFIRST(ply), size);
677  ply->buffer_last = size;
678  ply->buffer_first = ply->buffer_token = 0;
679  /* fill remaining with new data */
680  size = fread(ply->buffer+size, 1, BUFFERSIZE-size-1, ply->fp);
681  /* place sentinel so we can use str* functions with buffer */
682  ply->buffer[BUFFERSIZE-1] = '\0';
683  /* check if read failed */
684  if (size <= 0) return 0;
685  /* increase size to account for new data */
686  ply->buffer_last += size;
687  return 1;
688 }
689 
690 /* We don't care about end-of-line, generally, because we
691  * separate words by any white-space character.
692  * Unfortunately, in binary mode, right after 'end_header',
693  * we have to know *exactly* how many characters to skip */
694 /* We use the end-of-line marker after the 'ply' magic
695  * number to figure out what to do */
696 static int ply_read_header_magic(p_ply ply) {
697  char *magic = ply->buffer;
698  if (!BREFILL(ply)) {
699  ply->error_cb(ply, "Unable to read magic number from file");
700  return 0;
701  }
702  /* check if it is ply */
703  if (magic[0] != 'p' || magic[1] != 'l' || magic[2] != 'y'
704  || !isspace(magic[3])) {
705  ply->error_cb(ply, "Wrong magic number. Expected 'ply'");
706  return 0;
707  }
708  /* figure out if we have to skip the extra character
709  * after header when we reach the binary part of file */
710  ply->rn = magic[3] == '\r' && magic[4] == '\n';
711  BSKIP(ply, 3);
712  return 1;
713 }
714 
715 /* ----------------------------------------------------------------------
716  * Input handlers
717  * ---------------------------------------------------------------------- */
718 static int iascii_int8(p_ply ply, double *value) {
719  char *end;
720  if (!ply_read_word(ply)) return 0;
721  *value = strtol(BWORD(ply), &end, 10);
722  if (*end || *value > PLY_INT8_MAX || *value < PLY_INT8_MIN) return 0;
723  return 1;
724 }
725 
726 static int iascii_uint8(p_ply ply, double *value) {
727  char *end;
728  if (!ply_read_word(ply)) return 0;
729  *value = strtol(BWORD(ply), &end, 10);
730  if (*end || *value > PLY_UINT8_MAX || *value < 0) return 0;
731  return 1;
732 }
733 
734 static int iascii_int16(p_ply ply, double *value) {
735  char *end;
736  if (!ply_read_word(ply)) return 0;
737  *value = strtol(BWORD(ply), &end, 10);
738  if (*end || *value > PLY_INT16_MAX || *value < PLY_INT16_MIN) return 0;
739  return 1;
740 }
741 
742 static int iascii_uint16(p_ply ply, double *value) {
743  char *end;
744  if (!ply_read_word(ply)) return 0;
745  *value = strtol(BWORD(ply), &end, 10);
746  if (*end || *value > PLY_UINT16_MAX || *value < 0) return 0;
747  return 1;
748 }
749 
750 static int iascii_int32(p_ply ply, double *value) {
751  char *end;
752  if (!ply_read_word(ply)) return 0;
753  *value = strtol(BWORD(ply), &end, 10);
754  if (*end || *value > PLY_INT32_MAX || *value < PLY_INT32_MIN) return 0;
755  return 1;
756 }
757 
758 static int iascii_uint32(p_ply ply, double *value) {
759  char *end;
760  if (!ply_read_word(ply)) return 0;
761  *value = strtol(BWORD(ply), &end, 10);
762  if (*end || *value > PLY_UINT32_MAX || *value < 0) return 0;
763  return 1;
764 }
765 
766 static int iascii_float32(p_ply ply, double *value) {
767  char *end;
768  if (!ply_read_word(ply)) return 0;
769  *value = strtod(BWORD(ply), &end);
770  if (*end || *value < -FLT_MAX || *value > FLT_MAX) return 0;
771  return 1;
772 }
773 
774 static int iascii_float64(p_ply ply, double *value) {
775  char *end;
776  if (!ply_read_word(ply)) return 0;
777  *value = strtod(BWORD(ply), &end);
778  if (*end || *value < -DBL_MAX || *value > DBL_MAX) return 0;
779  return 1;
780 }
781 
782 static int ibinary_int8(p_ply ply, double *value) {
783  t_ply_int8 int8;
784  if (!ply->idriver->ichunk(ply, &int8, 1)) return 0;
785  *value = int8;
786  return 1;
787 }
788 
789 static int ibinary_uint8(p_ply ply, double *value) {
790  t_ply_uint8 uint8;
791  if (!ply->idriver->ichunk(ply, &uint8, 1)) return 0;
792  *value = uint8;
793  return 1;
794 }
795 
796 static int ibinary_int16(p_ply ply, double *value) {
797  t_ply_int16 int16;
798  if (!ply->idriver->ichunk(ply, &int16, sizeof(int16))) return 0;
799  *value = int16;
800  return 1;
801 }
802 
803 static int ibinary_uint16(p_ply ply, double *value) {
804  t_ply_uint16 uint16;
805  if (!ply->idriver->ichunk(ply, &uint16, sizeof(uint16))) return 0;
806  *value = uint16;
807  return 1;
808 }
809 
810 static int ibinary_int32(p_ply ply, double *value) {
811  t_ply_int32 int32;
812  if (!ply->idriver->ichunk(ply, &int32, sizeof(int32))) return 0;
813  *value = int32;
814  return 1;
815 }
816 
817 static int ibinary_uint32(p_ply ply, double *value) {
818  t_ply_uint32 uint32;
819  if (!ply->idriver->ichunk(ply, &uint32, sizeof(uint32))) return 0;
820  *value = uint32;
821  return 1;
822 }
823 
824 static int ibinary_float32(p_ply ply, double *value) {
825  float float32;
826  if (!ply->idriver->ichunk(ply, &float32, sizeof(float32))) return 0;
827  *value = float32;
828  return 1;
829 }
830 
831 static int ibinary_float64(p_ply ply, double *value) {
832  return ply->idriver->ichunk(ply, value, sizeof(double));
833 }
834 
835 /* ----------------------------------------------------------------------
836  * Output handlers
837  * ---------------------------------------------------------------------- */
838 static int oascii_int8(p_ply ply, double value) {
839  if (value > PLY_INT8_MAX || value < PLY_INT8_MIN) return 0;
840  return fprintf(ply->fp, "%d", (t_ply_int8) value) > 0;
841 }
842 
843 static int oascii_uint8(p_ply ply, double value) {
844  if (value > PLY_UINT8_MAX || value < 0) return 0;
845  return fprintf(ply->fp, "%d", (t_ply_uint8) value) > 0;
846 }
847 
848 static int oascii_int16(p_ply ply, double value) {
849  if (value > PLY_INT16_MAX || value < PLY_INT16_MIN) return 0;
850  return fprintf(ply->fp, "%d", (t_ply_int16) value) > 0;
851 }
852 
853 static int oascii_uint16(p_ply ply, double value) {
854  if (value > PLY_UINT16_MAX || value < 0) return 0;
855  return fprintf(ply->fp, "%d", (t_ply_uint16) value) > 0;
856 }
857 
858 static int oascii_int32(p_ply ply, double value) {
859  if (value > PLY_INT32_MAX || value < PLY_INT32_MIN) return 0;
860  return fprintf(ply->fp, "%d", (t_ply_int32) value) > 0;
861 }
862 
863 static int oascii_uint32(p_ply ply, double value) {
864  if (value > PLY_UINT32_MAX || value < 0) return 0;
865  return fprintf(ply->fp, "%d", (t_ply_uint32) value) > 0;
866 }
867 
868 static int oascii_float32(p_ply ply, double value) {
869  if (value < -FLT_MAX || value > FLT_MAX) return 0;
870  return fprintf(ply->fp, "%g", (float) value) > 0;
871 }
872 
873 static int oascii_float64(p_ply ply, double value) {
874  if (value < -DBL_MAX || value > DBL_MAX) return 0;
875  return fprintf(ply->fp, "%g", value) > 0;
876 }
877 
878 static int obinary_int8(p_ply ply, double value) {
879  t_ply_int8 int8 = (t_ply_int8) value;
880  if (value > PLY_INT8_MAX || value < PLY_INT8_MIN) return 0;
881  return ply->odriver->ochunk(ply, &int8, sizeof(int8));
882 }
883 
884 static int obinary_uint8(p_ply ply, double value) {
885  t_ply_uint8 uint8 = (t_ply_uint8) value;
886  if (value > PLY_UINT8_MAX || value < 0) return 0;
887  return ply->odriver->ochunk(ply, &uint8, sizeof(uint8));
888 }
889 
890 static int obinary_int16(p_ply ply, double value) {
891  t_ply_int16 int16 = (t_ply_int16) value;
892  if (value > PLY_INT16_MAX || value < PLY_INT16_MIN) return 0;
893  return ply->odriver->ochunk(ply, &int16, sizeof(int16));
894 }
895 
896 static int obinary_uint16(p_ply ply, double value) {
897  t_ply_uint16 uint16 = (t_ply_uint16) value;
898  if (value > PLY_UINT16_MAX || value < 0) return 0;
899  return ply->odriver->ochunk(ply, &uint16, sizeof(uint16));
900 }
901 
902 static int obinary_int32(p_ply ply, double value) {
903  t_ply_int32 int32 = (t_ply_int32) value;
904  if (value > PLY_INT32_MAX || value < PLY_INT32_MIN) return 0;
905  return ply->odriver->ochunk(ply, &int32, sizeof(int32));
906 }
907 
908 static int obinary_uint32(p_ply ply, double value) {
909  t_ply_uint32 uint32 = (t_ply_uint32) value;
910  if (value > PLY_UINT32_MAX || value < 0) return 0;
911  return ply->odriver->ochunk(ply, &uint32, sizeof(uint32));
912 }
913 
914 static int obinary_float32(p_ply ply, double value) {
915  float float32 = (float) value;
916  if (value > FLT_MAX || value < -FLT_MAX) return 0;
917  return ply->odriver->ochunk(ply, &float32, sizeof(float32));
918 }
919 
920 static int obinary_float64(p_ply ply, double value) {
921  return ply->odriver->ochunk(ply, &value, sizeof(value));
922 }
923 
924 /* ----------------------------------------------------------------------
925  * Constants
926  * ---------------------------------------------------------------------- */
931  iascii_int32, iascii_uint32, iascii_float32, iascii_float64
932  }, /* order matches e_ply_type enum */
933  NULL,
934  "ascii input"
935 };
936 
941  ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64
942  }, /* order matches e_ply_type enum */
944  "binary input"
945 };
946 
951  ibinary_int32, ibinary_uint32, ibinary_float32, ibinary_float64
952  }, /* order matches e_ply_type enum */
954  "reverse binary input"
955 };
956 
961  oascii_int32, oascii_uint32, oascii_float32, oascii_float64
962  }, /* order matches e_ply_type enum */
963  NULL,
964  "ascii output"
965 };
966 
971  obinary_int32, obinary_uint32, obinary_float32, obinary_float64
972  }, /* order matches e_ply_type enum */
974  "binary output"
975 };
976 
981  obinary_int32, obinary_uint32, obinary_float32, obinary_float64
982  }, /* order matches e_ply_type enum */
984  "reverse binary output"
985 };
986 
987 /* ----------------------------------------------------------------------
988  * Exported functions
989  * ---------------------------------------------------------------------- */
990 /* ----------------------------------------------------------------------
991  * Read support functions
992  * ---------------------------------------------------------------------- */
993 inline p_ply ply_open(const char *name, p_ply_error_cb error_cb,
994  long idata, void *pdata) {
995  FILE *fp = NULL;
996  p_ply ply = ply_alloc();
997  if (error_cb == NULL) error_cb = ply_error_cb;
998  if (!ply) {
999  error_cb(NULL, "Out of memory");
1000  return NULL;
1001  }
1002  ply->idata = idata;
1003  ply->pdata = pdata;
1004  ply->io_mode = PLY_READ;
1005  ply->error_cb = error_cb;
1006  if (!ply_type_check()) {
1007  error_cb(ply, "Incompatible type system");
1008  free(ply);
1009  return NULL;
1010  }
1011  assert(name);
1012  fp = fopen(name, "rb");
1013  if (!fp) {
1014  error_cb(ply, "Unable to open file");
1015  free(ply);
1016  return NULL;
1017  }
1018  ply->fp = fp;
1019  return ply;
1020 }
1021 
1022 inline int ply_read_header(p_ply ply) {
1023  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1024  if (!ply_read_header_magic(ply)) return 0;
1025  if (!ply_read_word(ply)) return 0;
1026  /* parse file format */
1027  if (!ply_read_header_format(ply)) {
1028  ply_ferror(ply, "Invalid file format");
1029  return 0;
1030  }
1031  /* parse elements, comments or obj_infos until the end of header */
1032  while (strcmp(BWORD(ply), "end_header")) {
1033  if (!ply_read_header_comment(ply) &&
1034  !ply_read_header_element(ply) &&
1035  !ply_read_header_obj_info(ply)) {
1036  ply_ferror(ply, "Unexpected token '%s'", BWORD(ply));
1037  return 0;
1038  }
1039  }
1040  /* skip extra character? */
1041  if (ply->rn) {
1042  if (BSIZE(ply) < 1 && !BREFILL(ply)) {
1043  ply_ferror(ply, "Unexpected end of file");
1044  return 0;
1045  }
1046  BSKIP(ply, 1);
1047  }
1048  return 1;
1049 }
1050 
1051 inline long ply_set_read_cb(p_ply ply, const char *element_name,
1052  const char* property_name, p_ply_read_cb read_cb,
1053  void *pdata, long idata) {
1054  p_ply_element element = NULL;
1055  p_ply_property property = NULL;
1056  assert(ply && element_name && property_name);
1057  element = ply_find_element(ply, element_name);
1058  if (!element) return 0;
1059  property = ply_find_property(element, property_name);
1060  if (!property) return 0;
1061  property->read_cb = read_cb;
1062  property->pdata = pdata;
1063  property->idata = idata;
1064  return (int) element->ninstances;
1065 }
1066 
1067 inline int ply_read(p_ply ply) {
1068  long i;
1069  p_ply_argument argument;
1070  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1071  argument = &ply->argument;
1072  /* for each element type */
1073  for (i = 0; i < ply->nelements; i++) {
1074  p_ply_element element = &ply->element[i];
1075  argument->element = element;
1076  if (!ply_read_element(ply, element, argument))
1077  return 0;
1078  }
1079  return 1;
1080 }
1081 
1082 /* ----------------------------------------------------------------------
1083  * Write support functions
1084  * ---------------------------------------------------------------------- */
1085 inline p_ply ply_create(const char *name, e_ply_storage_mode storage_mode,
1086  p_ply_error_cb error_cb, long idata, void *pdata) {
1087  FILE *fp = NULL;
1088  p_ply ply = ply_alloc();
1089  if (error_cb == NULL) error_cb = ply_error_cb;
1090  if (!ply) {
1091  error_cb(NULL, "Out of memory");
1092  return NULL;
1093  }
1094  if (!ply_type_check()) {
1095  error_cb(ply, "Incompatible type system");
1096  free(ply);
1097  return NULL;
1098  }
1099  assert(name && storage_mode <= PLY_DEFAULT);
1100  fp = fopen(name, "wb");
1101  if (!fp) {
1102  error_cb(ply, "Unable to create file");
1103  free(ply);
1104  return NULL;
1105  }
1106  ply->idata = idata;
1107  ply->pdata = pdata;
1108  ply->io_mode = PLY_WRITE;
1109  if (storage_mode == PLY_DEFAULT) storage_mode = ply_arch_endian();
1110  if (storage_mode == PLY_ASCII) ply->odriver = &ply_odriver_ascii;
1111  else if (storage_mode == ply_arch_endian())
1112  ply->odriver = &ply_odriver_binary;
1113  else ply->odriver = &ply_odriver_binary_reverse;
1114  ply->storage_mode = storage_mode;
1115  ply->fp = fp;
1116  ply->error_cb = error_cb;
1117  return ply;
1118 }
1119 
1120 inline int ply_add_element(p_ply ply, const char *name, long ninstances) {
1121  p_ply_element element = NULL;
1122  assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
1123  assert(name && strlen(name) < WORDSIZE && ninstances >= 0);
1124  if (strlen(name) >= WORDSIZE || ninstances < 0) {
1125  ply_ferror(ply, "Invalid arguments");
1126  return 0;
1127  }
1128  element = ply_grow_element(ply);
1129  if (!element) return 0;
1130  strcpy(element->name, name);
1131  element->ninstances = ninstances;
1132  return 1;
1133 }
1134 
1135 inline int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type) {
1136  p_ply_element element = NULL;
1137  p_ply_property property = NULL;
1138  assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
1139  assert(name && strlen(name) < WORDSIZE);
1140  assert(type < PLY_LIST);
1141  if (strlen(name) >= WORDSIZE || type >= PLY_LIST) {
1142  ply_ferror(ply, "Invalid arguments");
1143  return 0;
1144  }
1145  element = &ply->element[ply->nelements-1];
1146  property = ply_grow_property(ply, element);
1147  if (!property) return 0;
1148  strcpy(property->name, name);
1149  property->type = type;
1150  return 1;
1151 }
1152 
1153 inline int ply_add_list_property(p_ply ply, const char *name,
1154  e_ply_type length_type, e_ply_type value_type) {
1155  p_ply_element element = NULL;
1156  p_ply_property property = NULL;
1157  assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
1158  assert(name && strlen(name) < WORDSIZE);
1159  if (strlen(name) >= WORDSIZE) {
1160  ply_ferror(ply, "Invalid arguments");
1161  return 0;
1162  }
1163  assert(length_type < PLY_LIST);
1164  assert(value_type < PLY_LIST);
1165  if (length_type >= PLY_LIST || value_type >= PLY_LIST) {
1166  ply_ferror(ply, "Invalid arguments");
1167  return 0;
1168  }
1169  element = &ply->element[ply->nelements-1];
1170  property = ply_grow_property(ply, element);
1171  if (!property) return 0;
1172  strcpy(property->name, name);
1173  property->type = PLY_LIST;
1174  property->length_type = length_type;
1175  property->value_type = value_type;
1176  return 1;
1177 }
1178 
1179 inline int ply_add_property(p_ply ply, const char *name, e_ply_type type,
1180  e_ply_type length_type, e_ply_type value_type) {
1181  if (type == PLY_LIST)
1182  return ply_add_list_property(ply, name, length_type, value_type);
1183  else
1184  return ply_add_scalar_property(ply, name, type);
1185 }
1186 
1187 inline int ply_add_comment(p_ply ply, const char *comment) {
1188  char *new_comment = NULL;
1189  assert(ply && comment && strlen(comment) < LINESIZE);
1190  if (!comment || strlen(comment) >= LINESIZE) {
1191  ply_ferror(ply, "Invalid arguments");
1192  return 0;
1193  }
1194  new_comment = (char *) ply_grow_array(ply, (void **) &ply->comment,
1195  &ply->ncomments, LINESIZE);
1196  if (!new_comment) return 0;
1197  strcpy(new_comment, comment);
1198  return 1;
1199 }
1200 
1201 inline int ply_add_obj_info(p_ply ply, const char *obj_info) {
1202  char *new_obj_info = NULL;
1203  assert(ply && obj_info && strlen(obj_info) < LINESIZE);
1204  if (!obj_info || strlen(obj_info) >= LINESIZE) {
1205  ply_ferror(ply, "Invalid arguments");
1206  return 0;
1207  }
1208  new_obj_info = (char *) ply_grow_array(ply, (void **) &ply->obj_info,
1209  &ply->nobj_infos, LINESIZE);
1210  if (!new_obj_info) return 0;
1211  strcpy(new_obj_info, obj_info);
1212  return 1;
1213 }
1214 
1215 inline int ply_write_header(p_ply ply) {
1216  long i, j;
1217  assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
1218  assert(ply->element || ply->nelements == 0);
1219  assert(!ply->element || ply->nelements > 0);
1220  if (fprintf(ply->fp, "ply\nformat %s 1.0\n",
1221  ply_storage_mode_list[ply->storage_mode]) <= 0) goto error;
1222  for (i = 0; i < ply->ncomments; i++)
1223  if (fprintf(ply->fp, "comment %s\n", ply->comment + LINESIZE*i) <= 0)
1224  goto error;
1225  for (i = 0; i < ply->nobj_infos; i++)
1226  if (fprintf(ply->fp, "obj_info %s\n", ply->obj_info + LINESIZE*i) <= 0)
1227  goto error;
1228  for (i = 0; i < ply->nelements; i++) {
1229  p_ply_element element = &ply->element[i];
1230  assert(element->property || element->nproperties == 0);
1231  assert(!element->property || element->nproperties > 0);
1232  if (fprintf(ply->fp, "element %s %ld\n", element->name,
1233  element->ninstances) <= 0) goto error;
1234  for (j = 0; j < element->nproperties; j++) {
1235  p_ply_property property = &element->property[j];
1236  if (property->type == PLY_LIST) {
1237  if (fprintf(ply->fp, "property list %s %s %s\n",
1240  property->name) <= 0) goto error;
1241  } else {
1242  if (fprintf(ply->fp, "property %s %s\n",
1244  property->name) <= 0) goto error;
1245  }
1246  }
1247  }
1248  return fprintf(ply->fp, "end_header\n") > 0;
1249 error:
1250  ply_ferror(ply, "Error writing to file");
1251  return 0;
1252 }
1253 
1254 inline int ply_write(p_ply ply, double value) {
1255  p_ply_element element = NULL;
1256  p_ply_property property = NULL;
1257  int type = -1;
1258  int breakafter = 0;
1259  int spaceafter = 1;
1260  if (ply->welement > ply->nelements) return 0;
1261  element = &ply->element[ply->welement];
1262  if (ply->wproperty > element->nproperties) return 0;
1263  property = &element->property[ply->wproperty];
1264  if (property->type == PLY_LIST) {
1265  if (ply->wvalue_index == 0) {
1266  type = property->length_type;
1267  ply->wlength = (long) value;
1268  } else type = property->value_type;
1269  } else {
1270  type = property->type;
1271  ply->wlength = 0;
1272  }
1273  if (!ply->odriver->ohandler[type](ply, value)) {
1274  ply_ferror(ply, "Failed writing %s of %s %d (%s: %s)",
1275  property->name, element->name,
1276  ply->winstance_index,
1277  ply->odriver->name, ply_type_list[type]);
1278  return 0;
1279  }
1280  ply->wvalue_index++;
1281  if (ply->wvalue_index > ply->wlength) {
1282  ply->wvalue_index = 0;
1283  ply->wproperty++;
1284  }
1285  if (ply->wproperty >= element->nproperties) {
1286  ply->wproperty = 0;
1287  ply->winstance_index++;
1288  breakafter = 1;
1289  spaceafter = 0;
1290  }
1291  if (ply->winstance_index >= element->ninstances) {
1292  ply->winstance_index = 0;
1293  do {
1294  ply->welement++;
1295  element = &ply->element[ply->welement];
1296  } while (ply->welement < ply->nelements && !element->ninstances);
1297  }
1298  if (ply->storage_mode == PLY_ASCII) {
1299  return (!spaceafter || putc(' ', ply->fp) > 0) &&
1300  (!breakafter || putc('\n', ply->fp) > 0);
1301  } else {
1302  return 1;
1303  }
1304 }
1305 
1306 inline int ply_close(p_ply ply) {
1307  long i;
1308  assert(ply && ply->fp);
1309  assert(ply->element || ply->nelements == 0);
1310  assert(!ply->element || ply->nelements > 0);
1311  /* write last chunk to file */
1312  if (ply->io_mode == PLY_WRITE &&
1313  fwrite(ply->buffer, 1, ply->buffer_last, ply->fp) < ply->buffer_last) {
1314  ply_ferror(ply, "Error closing up");
1315  return 0;
1316  }
1317  fclose(ply->fp);
1318  /* free all memory used by handle */
1319  if (ply->element) {
1320  for (i = 0; i < ply->nelements; i++) {
1321  p_ply_element element = &ply->element[i];
1322  if (element->property) free(element->property);
1323  }
1324  free(ply->element);
1325  }
1326  if (ply->obj_info) free(ply->obj_info);
1327  if (ply->comment) free(ply->comment);
1328  free(ply);
1329  return 1;
1330 }
1331 
1332 /* ----------------------------------------------------------------------
1333  * Query support functions
1334  * ---------------------------------------------------------------------- */
1335 inline p_ply_element ply_get_next_element(p_ply ply,
1336  p_ply_element last) {
1337  assert(ply);
1338  if (!last) return ply->element;
1339  last++;
1340  if (last < ply->element + ply->nelements) return last;
1341  else return NULL;
1342 }
1343 
1344 inline int ply_get_element_info(p_ply_element element, const char** name,
1345  long *ninstances) {
1346  assert(element);
1347  if (name) *name = element->name;
1348  if (ninstances) *ninstances = (long) element->ninstances;
1349  return 1;
1350 }
1351 
1352 inline p_ply_property ply_get_next_property(p_ply_element element,
1353  p_ply_property last) {
1354  assert(element);
1355  if (!last) return element->property;
1356  last++;
1357  if (last < element->property + element->nproperties) return last;
1358  else return NULL;
1359 }
1360 
1361 inline int ply_get_property_info(p_ply_property property, const char** name,
1362  e_ply_type *type, e_ply_type *length_type, e_ply_type *value_type) {
1363  assert(property);
1364  if (name) *name = property->name;
1365  if (type) *type = property->type;
1366  if (length_type) *length_type = property->length_type;
1367  if (value_type) *value_type = property->value_type;
1368  return 1;
1369 
1370 }
1371 
1372 inline const char *ply_get_next_comment(p_ply ply, const char *last) {
1373  assert(ply);
1374  if (!last) return ply->comment;
1375  last += LINESIZE;
1376  if (last < ply->comment + LINESIZE*ply->ncomments) return last;
1377  else return NULL;
1378 }
1379 
1380 inline const char *ply_get_next_obj_info(p_ply ply, const char *last) {
1381  assert(ply);
1382  if (!last) return ply->obj_info;
1383  last += LINESIZE;
1384  if (last < ply->obj_info + LINESIZE*ply->nobj_infos) return last;
1385  else return NULL;
1386 }
1387 
1388 /* ----------------------------------------------------------------------
1389  * Callback argument support functions
1390  * ---------------------------------------------------------------------- */
1391 inline int ply_get_argument_element(p_ply_argument argument,
1392  p_ply_element *element, long *instance_index) {
1393  assert(argument);
1394  if (!argument) return 0;
1395  if (element) *element = argument->element;
1396  if (instance_index) *instance_index = argument->instance_index;
1397  return 1;
1398 }
1399 
1400 inline int ply_get_argument_property(p_ply_argument argument,
1401  p_ply_property *property, long *length, long *value_index) {
1402  assert(argument);
1403  if (!argument) return 0;
1404  if (property) *property = argument->property;
1405  if (length) *length = argument->length;
1406  if (value_index) *value_index = argument->value_index;
1407  return 1;
1408 }
1409 
1410 inline int ply_get_argument_user_data(p_ply_argument argument, void **pdata,
1411  long *idata) {
1412  assert(argument);
1413  if (!argument) return 0;
1414  if (pdata) *pdata = argument->pdata;
1415  if (idata) *idata = argument->idata;
1416  return 1;
1417 }
1418 
1419 inline double ply_get_argument_value(p_ply_argument argument) {
1420  assert(argument);
1421  if (!argument) return 0.0;
1422  return argument->value;
1423 }
1424 
1425 inline int ply_get_ply_user_data(p_ply ply, void **pdata, long *idata) {
1426  assert(ply);
1427  if (!ply) return 0;
1428  if (pdata) *pdata = ply->pdata;
1429  if (idata) *idata = ply->idata;
1430  return 1;
1431 }
1432 
1433 /* ----------------------------------------------------------------------
1434  * Internal functions
1435  * ---------------------------------------------------------------------- */
1436 static int ply_read_list_property(p_ply ply, p_ply_element element,
1437  p_ply_property property, p_ply_argument argument) {
1438  int l;
1439  p_ply_read_cb read_cb = property->read_cb;
1440  p_ply_ihandler *driver = ply->idriver->ihandler;
1441  /* get list length */
1442  p_ply_ihandler handler = driver[property->length_type];
1443  double length;
1444  if (!handler(ply, &length)) {
1445  ply_ferror(ply, "Error reading '%s' of '%s' number %d",
1446  property->name, element->name, argument->instance_index);
1447  return 0;
1448  }
1449  /* invoke callback to pass length in value field */
1450  argument->length = (long) length;
1451  argument->value_index = -1;
1452  argument->value = length;
1453  if (read_cb && !read_cb(argument)) {
1454  ply_ferror(ply, "Aborted by user");
1455  return 0;
1456  }
1457  /* read list values */
1458  handler = driver[property->value_type];
1459  /* for each value in list */
1460  for (l = 0; l < (long) length; l++) {
1461  /* read value from file */
1462  argument->value_index = l;
1463  if (!handler(ply, &argument->value)) {
1464  ply_ferror(ply, "Error reading value number %d of '%s' of "
1465  "'%s' number %d", l+1, property->name,
1466  element->name, argument->instance_index);
1467  return 0;
1468  }
1469  /* invoke callback to pass value */
1470  if (read_cb && !read_cb(argument)) {
1471  ply_ferror(ply, "Aborted by user");
1472  return 0;
1473  }
1474  }
1475  return 1;
1476 }
1477 
1478 static int ply_read_scalar_property(p_ply ply, p_ply_element element,
1479  p_ply_property property, p_ply_argument argument) {
1480  p_ply_read_cb read_cb = property->read_cb;
1481  p_ply_ihandler *driver = ply->idriver->ihandler;
1482  p_ply_ihandler handler = driver[property->type];
1483  argument->length = 1;
1484  argument->value_index = 0;
1485  if (!handler(ply, &argument->value)) {
1486  ply_ferror(ply, "Error reading '%s' of '%s' number %d",
1487  property->name, element->name, argument->instance_index);
1488  return 0;
1489  }
1490  if (read_cb && !read_cb(argument)) {
1491  ply_ferror(ply, "Aborted by user");
1492  return 0;
1493  }
1494  return 1;
1495 }
1496 
1497 static int ply_read_property(p_ply ply, p_ply_element element,
1498  p_ply_property property, p_ply_argument argument) {
1499  if (property->type == PLY_LIST)
1500  return ply_read_list_property(ply, element, property, argument);
1501  else
1502  return ply_read_scalar_property(ply, element, property, argument);
1503 }
1504 
1505 static int ply_read_element(p_ply ply, p_ply_element element,
1506  p_ply_argument argument) {
1507  long j, k;
1508  /* for each element of this type */
1509  for (j = 0; j < element->ninstances; j++) {
1510  argument->instance_index = j;
1511  /* for each property */
1512  for (k = 0; k < element->nproperties; k++) {
1513  p_ply_property property = &element->property[k];
1514  argument->property = property;
1515  argument->pdata = property->pdata;
1516  argument->idata = property->idata;
1517  if (!ply_read_property(ply, element, property, argument))
1518  return 0;
1519  }
1520  }
1521  return 1;
1522 }
1523 
1524 static int ply_find_string(const char *item, const char* const list[]) {
1525  int i;
1526  assert(item && list);
1527  for (i = 0; list[i]; i++)
1528  if (!strcmp(list[i], item)) return i;
1529  return -1;
1530 }
1531 
1532 static p_ply_element ply_find_element(p_ply ply, const char *name) {
1533  p_ply_element element;
1534  int i, nelements;
1535  assert(ply && name);
1536  element = ply->element;
1537  nelements = ply->nelements;
1538  assert(element || nelements == 0);
1539  assert(!element || nelements > 0);
1540  for (i = 0; i < nelements; i++)
1541  if (!strcmp(element[i].name, name)) return &element[i];
1542  return NULL;
1543 }
1544 
1545 static p_ply_property ply_find_property(p_ply_element element,
1546  const char *name) {
1547  p_ply_property property;
1548  int i, nproperties;
1549  assert(element && name);
1550  property = element->property;
1551  nproperties = element->nproperties;
1552  assert(property || nproperties == 0);
1553  assert(!property || nproperties > 0);
1554  for (i = 0; i < nproperties; i++)
1555  if (!strcmp(property[i].name, name)) return &property[i];
1556  return NULL;
1557 }
1558 
1559 static int ply_check_word(p_ply ply) {
1560  size_t size = strlen(BWORD(ply));
1561  if (size >= WORDSIZE) {
1562  ply_ferror(ply, "Word too long");
1563  return 0;
1564  } else if (size == 0) {
1565  ply_ferror(ply, "Unexpected end of file");
1566  return 0;
1567  }
1568  return 1;
1569 }
1570 
1571 static int ply_read_word(p_ply ply) {
1572  size_t t = 0;
1573  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1574  /* skip leading blanks */
1575  while (1) {
1576  t = strspn(BFIRST(ply), " \n\r\t");
1577  /* check if all buffer was made of blanks */
1578  if (t >= BSIZE(ply)) {
1579  if (!BREFILL(ply)) {
1580  ply_ferror(ply, "Unexpected end of file");
1581  return 0;
1582  }
1583  } else break;
1584  }
1585  BSKIP(ply, t);
1586  /* look for a space after the current word */
1587  t = strcspn(BFIRST(ply), " \n\r\t");
1588  /* if we didn't reach the end of the buffer, we are done */
1589  if (t < BSIZE(ply)) {
1590  ply_finish_word(ply, t);
1591  return ply_check_word(ply);
1592  }
1593  /* otherwise, try to refill buffer */
1594  if (!BREFILL(ply)) {
1595  /* if we reached the end of file, try to do with what we have */
1596  ply_finish_word(ply, t);
1597  return ply_check_word(ply);
1598  /* ply_ferror(ply, "Unexpected end of file"); */
1599  /* return 0; */
1600  }
1601  /* keep looking from where we left */
1602  t += strcspn(BFIRST(ply) + t, " \n\r\t");
1603  /* check if the token is too large for our buffer */
1604  if (t >= BSIZE(ply)) {
1605  ply_ferror(ply, "Token too large");
1606  return 0;
1607  }
1608  /* we are done */
1609  ply_finish_word(ply, t);
1610  return ply_check_word(ply);
1611 }
1612 
1613 static void ply_finish_word(p_ply ply, size_t size) {
1614  ply->buffer_token = ply->buffer_first;
1615  BSKIP(ply, size);
1616  *BFIRST(ply) = '\0';
1617  BSKIP(ply, 1);
1618 }
1619 
1620 static int ply_check_line(p_ply ply) {
1621  if (strlen(BLINE(ply)) >= LINESIZE) {
1622  ply_ferror(ply, "Line too long");
1623  return 0;
1624  }
1625  return 1;
1626 }
1627 
1628 static int ply_read_line(p_ply ply) {
1629  const char *end = NULL;
1630  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1631  /* look for a end of line */
1632  end = strchr(BFIRST(ply), '\n');
1633  /* if we didn't reach the end of the buffer, we are done */
1634  if (end) {
1635  ply->buffer_token = ply->buffer_first;
1636  BSKIP(ply, end - BFIRST(ply));
1637  *BFIRST(ply) = '\0';
1638  BSKIP(ply, 1);
1639  return ply_check_line(ply);
1640  } else {
1641  end = ply->buffer + BSIZE(ply);
1642  /* otherwise, try to refill buffer */
1643  if (!BREFILL(ply)) {
1644  ply_ferror(ply, "Unexpected end of file");
1645  return 0;
1646  }
1647  }
1648  /* keep looking from where we left */
1649  end = strchr(end, '\n');
1650  /* check if the token is too large for our buffer */
1651  if (!end) {
1652  ply_ferror(ply, "Token too large");
1653  return 0;
1654  }
1655  /* we are done */
1656  ply->buffer_token = ply->buffer_first;
1657  BSKIP(ply, end - BFIRST(ply));
1658  *BFIRST(ply) = '\0';
1659  BSKIP(ply, 1);
1660  return ply_check_line(ply);
1661 }
1662 
1663 static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size) {
1664  char *buffer = (char *) anybuffer;
1665  size_t i = 0;
1666  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1667  assert(ply->buffer_first <= ply->buffer_last);
1668  while (i < size) {
1669  if (ply->buffer_first < ply->buffer_last) {
1670  buffer[i] = ply->buffer[ply->buffer_first];
1671  ply->buffer_first++;
1672  i++;
1673  } else {
1674  ply->buffer_first = 0;
1675  ply->buffer_last = fread(ply->buffer, 1, BUFFERSIZE, ply->fp);
1676  if (ply->buffer_last <= 0) return 0;
1677  }
1678  }
1679  return 1;
1680 }
1681 
1682 static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size) {
1683  char *buffer = (char *) anybuffer;
1684  size_t i = 0;
1685  assert(ply && ply->fp && ply->io_mode == PLY_WRITE);
1686  assert(ply->buffer_last <= BUFFERSIZE);
1687  while (i < size) {
1688  if (ply->buffer_last < BUFFERSIZE) {
1689  ply->buffer[ply->buffer_last] = buffer[i];
1690  ply->buffer_last++;
1691  i++;
1692  } else {
1693  ply->buffer_last = 0;
1694  if (fwrite(ply->buffer, 1, BUFFERSIZE, ply->fp) < BUFFERSIZE)
1695  return 0;
1696  }
1697  }
1698  return 1;
1699 }
1700 
1701 static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size) {
1702  int ret = 0;
1703  ply_reverse(anybuffer, size);
1704  ret = ply_write_chunk(ply, anybuffer, size);
1705  ply_reverse(anybuffer, size);
1706  return ret;
1707 }
1708 
1709 static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size) {
1710  if (!ply_read_chunk(ply, anybuffer, size)) return 0;
1711  ply_reverse(anybuffer, size);
1712  return 1;
1713 }
1714 
1715 static void ply_reverse(void *anydata, size_t size) {
1716  char *data = (char *) anydata;
1717  char temp;
1718  size_t i;
1719  for (i = 0; i < size/2; i++) {
1720  temp = data[i];
1721  data[i] = data[size-i-1];
1722  data[size-i-1] = temp;
1723  }
1724 }
1725 
1726 static void ply_init(p_ply ply) {
1727  ply->element = NULL;
1728  ply->nelements = 0;
1729  ply->comment = NULL;
1730  ply->ncomments = 0;
1731  ply->obj_info = NULL;
1732  ply->nobj_infos = 0;
1733  ply->idriver = NULL;
1734  ply->odriver = NULL;
1735  ply->buffer[0] = '\0';
1736  ply->buffer_first = ply->buffer_last = ply->buffer_token = 0;
1737  ply->welement = 0;
1738  ply->wproperty = 0;
1739  ply->winstance_index = 0;
1740  ply->wlength = 0;
1741  ply->wvalue_index = 0;
1742 }
1743 
1744 static void ply_element_init(p_ply_element element) {
1745  element->name[0] = '\0';
1746  element->ninstances = 0;
1747  element->property = NULL;
1748  element->nproperties = 0;
1749 }
1750 
1751 static void ply_property_init(p_ply_property property) {
1752  property->name[0] = '\0';
1753  property->type = static_cast<e_ply_type>(-1);
1754  property->length_type = static_cast<e_ply_type>(-1);
1755  property->value_type = static_cast<e_ply_type>(-1);
1756  property->read_cb = (p_ply_read_cb) NULL;
1757  property->pdata = NULL;
1758  property->idata = 0;
1759 }
1760 
1761 static p_ply ply_alloc(void) {
1762  p_ply ply = (p_ply) calloc(1, sizeof(t_ply_));
1763  if (!ply) return NULL;
1764  ply_init(ply);
1765  return ply;
1766 }
1767 
1768 static void *ply_grow_array(p_ply ply, void **pointer,
1769  long *nmemb, long size) {
1770  void *temp = *pointer;
1771  long count = *nmemb + 1;
1772  if (!temp) temp = malloc(count*size);
1773  else temp = realloc(temp, count*size);
1774  if (!temp) {
1775  ply_ferror(ply, "Out of memory");
1776  return NULL;
1777  }
1778  *pointer = temp;
1779  *nmemb = count;
1780  return (char *) temp + (count-1) * size;
1781 }
1782 
1783 static p_ply_element ply_grow_element(p_ply ply) {
1784  p_ply_element element = NULL;
1785  assert(ply);
1786  assert(ply->element || ply->nelements == 0);
1787  assert(!ply->element || ply->nelements > 0);
1788  element = (p_ply_element) ply_grow_array(ply, (void **) &ply->element,
1789  &ply->nelements, sizeof(t_ply_element_));
1790  if (!element) return NULL;
1791  ply_element_init(element);
1792  return element;
1793 }
1794 
1795 static p_ply_property ply_grow_property(p_ply ply, p_ply_element element) {
1796  p_ply_property property = NULL;
1797  assert(ply);
1798  assert(element);
1799  assert(element->property || element->nproperties == 0);
1800  assert(!element->property || element->nproperties > 0);
1801  property = (p_ply_property) ply_grow_array(ply,
1802  (void **) &element->property,
1803  &element->nproperties, sizeof(t_ply_property_));
1804  if (!property) return NULL;
1806  return property;
1807 }
1808 
1809 static int ply_read_header_format(p_ply ply) {
1810  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1811  if (strcmp(BWORD(ply), "format")) return 0;
1812  if (!ply_read_word(ply)) return 0;
1814  if (ply->storage_mode == (e_ply_storage_mode) (-1)) return 0;
1815  if (ply->storage_mode == PLY_ASCII) ply->idriver = &ply_idriver_ascii;
1816  else if (ply->storage_mode == ply_arch_endian())
1817  ply->idriver = &ply_idriver_binary;
1818  else ply->idriver = &ply_idriver_binary_reverse;
1819  if (!ply_read_word(ply)) return 0;
1820  if (strcmp(BWORD(ply), "1.0")) return 0;
1821  if (!ply_read_word(ply)) return 0;
1822  return 1;
1823 }
1824 
1825 static int ply_read_header_comment(p_ply ply) {
1826  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1827  if (strcmp(BWORD(ply), "comment")) return 0;
1828  if (!ply_read_line(ply)) return 0;
1829  if (!ply_add_comment(ply, BLINE(ply))) return 0;
1830  if (!ply_read_word(ply)) return 0;
1831  return 1;
1832 }
1833 
1834 static int ply_read_header_obj_info(p_ply ply) {
1835  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1836  if (strcmp(BWORD(ply), "obj_info")) return 0;
1837  if (!ply_read_line(ply)) return 0;
1838  if (!ply_add_obj_info(ply, BLINE(ply))) return 0;
1839  if (!ply_read_word(ply)) return 0;
1840  return 1;
1841 }
1842 
1843 static int ply_read_header_property(p_ply ply) {
1844  p_ply_element element = NULL;
1845  p_ply_property property = NULL;
1846  /* make sure it is a property */
1847  if (strcmp(BWORD(ply), "property")) return 0;
1848  element = &ply->element[ply->nelements-1];
1849  property = ply_grow_property(ply, element);
1850  if (!property) return 0;
1851  /* get property type */
1852  if (!ply_read_word(ply)) return 0;
1853  property->type = static_cast<e_ply_type>(ply_find_string(BWORD(ply), ply_type_list));
1854  if (property->type == (e_ply_type) (-1)) return 0;
1855  if (property->type == PLY_LIST) {
1856  /* if it's a list, we need the base types */
1857  if (!ply_read_word(ply)) return 0;
1858  property->length_type = static_cast<e_ply_type>(ply_find_string(BWORD(ply), ply_type_list));
1859  if (property->length_type == (e_ply_type) (-1)) return 0;
1860  if (!ply_read_word(ply)) return 0;
1861  property->value_type = static_cast<e_ply_type>(ply_find_string(BWORD(ply), ply_type_list));
1862  if (property->value_type == (e_ply_type) (-1)) return 0;
1863  }
1864  /* get property name */
1865  if (!ply_read_word(ply)) return 0;
1866  strcpy(property->name, BWORD(ply));
1867  if (!ply_read_word(ply)) return 0;
1868  return 1;
1869 }
1870 
1871 static int ply_read_header_element(p_ply ply) {
1872  p_ply_element element = NULL;
1873  long dummy;
1874  assert(ply && ply->fp && ply->io_mode == PLY_READ);
1875  if (strcmp(BWORD(ply), "element")) return 0;
1876  /* allocate room for new element */
1877  element = ply_grow_element(ply);
1878  if (!element) return 0;
1879  /* get element name */
1880  if (!ply_read_word(ply)) return 0;
1881  strcpy(element->name, BWORD(ply));
1882  /* get number of elements of this type */
1883  if (!ply_read_word(ply)) return 0;
1884  if (sscanf(BWORD(ply), "%ld", &dummy) != 1) {
1885  ply_ferror(ply, "Expected number got '%s'", BWORD(ply));
1886  return 0;
1887  }
1888  element->ninstances = dummy;
1889  /* get all properties for this element */
1890  if (!ply_read_word(ply)) return 0;
1891  while (ply_read_header_property(ply) ||
1893  /* do nothing */;
1894  return 1;
1895 }
1896 
1897 static void ply_error_cb(p_ply ply, const char *message) {
1898  (void) ply;
1899  fprintf(stderr, "RPly: %s\n", message);
1900 }
1901 
1902 static void ply_ferror(p_ply ply, const char *fmt, ...) {
1903  char buffer[1024];
1904  va_list ap;
1905  va_start(ap, fmt);
1906  vsprintf(buffer, fmt, ap);
1907  va_end(ap);
1908  ply->error_cb(ply, buffer);
1909 }
1910 
1912  unsigned long i = 1;
1913  unsigned char *s = (unsigned char *) &i;
1914  if (*s == 1) return PLY_LITTLE_ENDIAN;
1915  else return PLY_BIG_ENDIAN;
1916 }
1917 
1918 static int ply_type_check(void) {
1919  assert(sizeof(t_ply_int8) == 1);
1920  assert(sizeof(t_ply_uint8) == 1);
1921  assert(sizeof(t_ply_int16) == 2);
1922  assert(sizeof(t_ply_uint16) == 2);
1923  assert(sizeof(t_ply_int32) == 4);
1924  assert(sizeof(t_ply_uint32) == 4);
1925  assert(sizeof(float) == 4);
1926  assert(sizeof(double) == 8);
1927  if (sizeof(t_ply_int8) != 1) return 0;
1928  if (sizeof(t_ply_uint8) != 1) return 0;
1929  if (sizeof(t_ply_int16) != 2) return 0;
1930  if (sizeof(t_ply_uint16) != 2) return 0;
1931  if (sizeof(t_ply_int32) != 4) return 0;
1932  if (sizeof(t_ply_uint32) != 4) return 0;
1933  if (sizeof(float) != 4) return 0;
1934  if (sizeof(double) != 8) return 0;
1935  return 1;
1936 }
1937 
1938 /* ----------------------------------------------------------------------
1939  * Copyright (C) 2003-2011 Diego Nehab. All rights reserved.
1940  * Copyright (C) 2014 Thiago Perrotta. All rights reserved.
1941  *
1942  * Permission is hereby granted, free of charge, to any person obtaining
1943  * a copy of this software and associated documentation files (the
1944  * "Software"), to deal in the Software without restriction, including
1945  * without limitation the rights to use, copy, modify, merge, publish,
1946  * distribute, sublicense, and/or sell copies of the Software, and to
1947  * permit persons to whom the Software is furnished to do so, subject to
1948  * the following conditions:
1949  *
1950  * The above copyright notice and this permission notice shall be
1951  * included in all copies or substantial portions of the Software.
1952  *
1953  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1954  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1955  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1956  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1957  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1958  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1959  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1960  * ---------------------------------------------------------------------- */
1961 
1962 #endif /* RPLY_H */
1963 
Definition: rply.hpp:123
#define BWORD(p)
Definition: rply.hpp:660
int ply_add_list_property(p_ply ply, const char *name, e_ply_type length_type, e_ply_type value_type)
Definition: rply.hpp:1153
static int ibinary_uint16(p_ply ply, double *value)
Definition: rply.hpp:803
static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size)
Definition: rply.hpp:1701
Definition: rply.hpp:566
static int oascii_int32(p_ply ply, double value)
Definition: rply.hpp:858
char name[WORDSIZE]
Definition: rply.hpp:492
p_ply_property ply_get_next_property(p_ply_element element, p_ply_property last)
Definition: rply.hpp:1352
static int ply_read_header_property(p_ply ply)
Definition: rply.hpp:1843
static void ply_init(p_ply ply)
Definition: rply.hpp:1726
static int iascii_int8(p_ply ply, double *value)
Definition: rply.hpp:718
Definition: rply.hpp:441
Definition: rply.hpp:534
int ply_get_argument_user_data(p_ply_argument argument, void **pdata, long *idata)
Definition: rply.hpp:1410
Definition: rply.hpp:122
int(* p_ply_ochunk)(p_ply ply, void *anydata, size_t size)
Definition: rply.hpp:533
static p_ply_property ply_grow_property(p_ply ply, p_ply_element element)
Definition: rply.hpp:1795
static int oascii_int16(p_ply ply, double value)
Definition: rply.hpp:848
static int ply_read_header_magic(p_ply ply)
Definition: rply.hpp:696
static int obinary_uint32(p_ply ply, double value)
Definition: rply.hpp:908
static int BREFILL(p_ply ply)
Definition: rply.hpp:673
static p_ply_element ply_find_element(p_ply ply, const char *name)
Definition: rply.hpp:1532
static const char *const ply_storage_mode_list[]
Definition: rply.hpp:445
p_ply_ochunk ochunk
Definition: rply.hpp:536
int ply_get_ply_user_data(p_ply ply, void **pdata, long *idata)
Definition: rply.hpp:1425
static int iascii_float64(p_ply ply, double *value)
Definition: rply.hpp:774
uint16_t t_ply_uint16
Definition: rply.hpp:61
p_ply_property property
Definition: rply.hpp:512
static void ply_finish_word(p_ply ply, size_t size)
Definition: rply.hpp:1613
const int WORDSIZE
Definition: rply.hpp:436
Definition: rply.hpp:125
static int obinary_int8(p_ply ply, double value)
Definition: rply.hpp:878
void(* p_ply_error_cb)(p_ply ply, const char *message)
Definition: rply.hpp:134
Definition: rply.hpp:122
Definition: rply.hpp:124
static int ply_check_word(p_ply ply)
Definition: rply.hpp:1559
char * obj_info
Definition: rply.hpp:573
static int obinary_int16(p_ply ply, double value)
Definition: rply.hpp:890
Definition: rply.hpp:124
#define BLINE(p)
Definition: rply.hpp:661
Definition: rply.hpp:121
char * comment
Definition: rply.hpp:571
static int oascii_int8(p_ply ply, double value)
Definition: rply.hpp:838
int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type)
Definition: rply.hpp:1135
void * pdata
Definition: rply.hpp:477
e_ply_type length_type
Definition: rply.hpp:493
long ncomments
Definition: rply.hpp:572
int ply_write(p_ply ply, double value)
Definition: rply.hpp:1254
const int LINESIZE
Definition: rply.hpp:437
const int BUFFERSIZE
Definition: rply.hpp:438
static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size)
Definition: rply.hpp:1709
static int ibinary_int32(p_ply ply, double *value)
Definition: rply.hpp:810
p_ply_element element
Definition: rply.hpp:569
int(* p_ply_ihandler)(p_ply ply, double *value)
Definition: rply.hpp:523
p_ply_read_cb read_cb
Definition: rply.hpp:494
Definition: rply.hpp:122
int32_t t_ply_int32
Definition: rply.hpp:59
int(* p_ply_ichunk)(p_ply ply, void *anydata, size_t size)
Definition: rply.hpp:524
static int ply_type_check(void)
Definition: rply.hpp:1918
const char * ply_get_next_obj_info(p_ply ply, const char *last)
Definition: rply.hpp:1380
p_ply_ihandler ihandler[16]
Definition: rply.hpp:526
static void ply_property_init(p_ply_property property)
Definition: rply.hpp:1751
static p_ply ply_alloc(void)
Definition: rply.hpp:1761
struct t_ply_argument_ * p_ply_argument
Definition: rply.hpp:109
static int ply_read_word(p_ply ply)
Definition: rply.hpp:1571
static int oascii_float32(p_ply ply, double value)
Definition: rply.hpp:868
Definition: rply.hpp:123
size_t buffer_last
Definition: rply.hpp:578
#define PLY_INT16_MAX
Definition: rply.hpp:92
static int ibinary_uint8(p_ply ply, double *value)
Definition: rply.hpp:789
Definition: rply.hpp:124
static int ply_read_line(p_ply ply)
Definition: rply.hpp:1628
int ply_read(p_ply ply)
Definition: rply.hpp:1067
Definition: rply.hpp:509
static int iascii_uint16(p_ply ply, double *value)
Definition: rply.hpp:742
#define PLY_INT8_MIN
Definition: rply.hpp:89
void * pdata
Definition: rply.hpp:495
#define PLY_UINT8_MAX
Definition: rply.hpp:95
static int iascii_int16(p_ply ply, double *value)
Definition: rply.hpp:734
static int ibinary_uint32(p_ply ply, double *value)
Definition: rply.hpp:817
static t_ply_idriver ply_idriver_ascii
Definition: rply.hpp:927
Definition: rply.hpp:122
long value_index
Definition: rply.hpp:475
Definition: rply.hpp:114
static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size)
Definition: rply.hpp:1663
t_ply_odriver * p_ply_odriver
Definition: rply.hpp:539
static int iascii_int32(p_ply ply, double *value)
Definition: rply.hpp:750
Definition: rply.hpp:124
static t_ply_odriver ply_odriver_ascii
Definition: rply.hpp:957
static void ply_reverse(void *anydata, size_t size)
Definition: rply.hpp:1715
char buffer[BUFFERSIZE]
Definition: rply.hpp:577
static int ibinary_float64(p_ply ply, double *value)
Definition: rply.hpp:831
Definition: rply.hpp:123
static int ply_read_list_property(p_ply ply, p_ply_element element, p_ply_property property, p_ply_argument argument)
Definition: rply.hpp:1436
p_ply ply_create(const char *name, e_ply_storage_mode storage_mode, p_ply_error_cb error_cb, long idata, void *pdata)
Definition: rply.hpp:1085
int(* p_ply_read_cb)(p_ply_argument argument)
Definition: rply.hpp:172
uint8_t t_ply_uint8
Definition: rply.hpp:60
static int obinary_uint8(p_ply ply, double value)
Definition: rply.hpp:884
double ply_get_argument_value(p_ply_argument argument)
Definition: rply.hpp:1419
const char * ply_get_next_comment(p_ply ply, const char *last)
Definition: rply.hpp:1372
int ply_add_element(p_ply ply, const char *name, long ninstances)
Definition: rply.hpp:1120
p_ply_idriver idriver
Definition: rply.hpp:579
double value
Definition: rply.hpp:476
int ply_get_property_info(p_ply_property property, const char **name, e_ply_type *type, e_ply_type *length_type, e_ply_type *value_type)
Definition: rply.hpp:1361
void * pdata
Definition: rply.hpp:585
static int ibinary_float32(p_ply ply, double *value)
Definition: rply.hpp:824
static int obinary_int32(p_ply ply, double value)
Definition: rply.hpp:902
static t_ply_idriver ply_idriver_binary
Definition: rply.hpp:937
Definition: rply.hpp:491
uint32_t t_ply_uint32
Definition: rply.hpp:62
e_ply_type type
Definition: rply.hpp:493
static p_ply_element ply_grow_element(p_ply ply)
Definition: rply.hpp:1783
struct t_ply_element_ * p_ply_element
Definition: rply.hpp:107
int8_t t_ply_int8
Definition: rply.hpp:57
size_t buffer_first
Definition: rply.hpp:578
int ply_add_obj_info(p_ply ply, const char *obj_info)
Definition: rply.hpp:1201
long nobj_infos
Definition: rply.hpp:574
static void ply_element_init(p_ply_element element)
Definition: rply.hpp:1744
static e_ply_storage_mode ply_arch_endian(void)
Definition: rply.hpp:1911
int ply_close(p_ply ply)
Definition: rply.hpp:1306
long welement
Definition: rply.hpp:582
char name[WORDSIZE]
Definition: rply.hpp:510
t_ply_argument_ argument
Definition: rply.hpp:581
static int obinary_uint16(p_ply ply, double value)
Definition: rply.hpp:896
p_ply_error_cb error_cb
Definition: rply.hpp:584
#define BSKIP(p, s)
Definition: rply.hpp:670
long winstance_index
Definition: rply.hpp:583
#define PLY_UINT16_MAX
Definition: rply.hpp:96
static void * ply_grow_array(p_ply ply, void **pointer, long *nmemb, long size)
Definition: rply.hpp:1768
Definition: rply.hpp:121
p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata, void *pdata)
Definition: rply.hpp:993
static int ply_read_header_comment(p_ply ply)
Definition: rply.hpp:1825
int ply_write_header(p_ply ply)
Definition: rply.hpp:1215
struct t_ply_property_ * p_ply_property
Definition: rply.hpp:108
long wproperty
Definition: rply.hpp:582
long instance_index
Definition: rply.hpp:473
#define PLY_INT32_MAX
Definition: rply.hpp:94
#define PLY_INT16_MIN
Definition: rply.hpp:91
e_ply_type value_type
Definition: rply.hpp:493
static t_ply_odriver ply_odriver_binary_reverse
Definition: rply.hpp:977
int ply_get_argument_property(p_ply_argument argument, p_ply_property *property, long *length, long *value_index)
Definition: rply.hpp:1400
struct t_ply_ * p_ply
Definition: rply.hpp:106
static int iascii_uint8(p_ply ply, double *value)
Definition: rply.hpp:726
#define PLY_UINT32_MAX
Definition: rply.hpp:97
p_ply_ichunk ichunk
Definition: rply.hpp:527
Definition: rply.hpp:471
long wlength
Definition: rply.hpp:583
static t_ply_idriver ply_idriver_binary_reverse
Definition: rply.hpp:947
long wvalue_index
Definition: rply.hpp:583
e_ply_storage_mode storage_mode
Definition: rply.hpp:568
size_t buffer_token
Definition: rply.hpp:578
Definition: rply.hpp:442
#define PLY_INT32_MIN
Definition: rply.hpp:93
FILE * fp
Definition: rply.hpp:575
e_ply_type
Definition: rply.hpp:120
long length
Definition: rply.hpp:475
static const char *const ply_type_list[]
Definition: rply.hpp:449
static int oascii_uint16(p_ply ply, double value)
Definition: rply.hpp:853
long idata
Definition: rply.hpp:478
int ply_add_property(p_ply ply, const char *name, e_ply_type type, e_ply_type length_type, e_ply_type value_type)
Definition: rply.hpp:1179
int ply_read_header(p_ply ply)
Definition: rply.hpp:1022
static int ibinary_int16(p_ply ply, double *value)
Definition: rply.hpp:796
p_ply_odriver odriver
Definition: rply.hpp:580
static int ply_read_element(p_ply ply, p_ply_element element, p_ply_argument argument)
Definition: rply.hpp:1505
static int oascii_float64(p_ply ply, double value)
Definition: rply.hpp:873
static int ibinary_int8(p_ply ply, double *value)
Definition: rply.hpp:782
static p_ply_property ply_find_property(p_ply_element element, const char *name)
Definition: rply.hpp:1545
e_ply_io_mode
Definition: rply.hpp:440
static void ply_error_cb(p_ply ply, const char *message)
Definition: rply.hpp:1897
Definition: rply.hpp:121
int16_t t_ply_int16
Definition: rply.hpp:58
Definition: rply.hpp:115
p_ply_element element
Definition: rply.hpp:472
long ninstances
Definition: rply.hpp:511
long ply_set_read_cb(p_ply ply, const char *element_name, const char *property_name, p_ply_read_cb read_cb, void *pdata, long idata)
Definition: rply.hpp:1051
int ply_get_element_info(p_ply_element element, const char **name, long *ninstances)
Definition: rply.hpp:1344
static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size)
Definition: rply.hpp:1682
Definition: rply.hpp:525
static int ply_find_string(const char *item, const char *const list[])
Definition: rply.hpp:1524
static int ply_check_line(p_ply ply)
Definition: rply.hpp:1620
#define PLY_INT8_MAX
Definition: rply.hpp:90
static int ply_read_property(p_ply ply, p_ply_element element, p_ply_property property, p_ply_argument argument)
Definition: rply.hpp:1497
static t_ply_odriver ply_odriver_binary
Definition: rply.hpp:967
e_ply_storage_mode
Definition: rply.hpp:112
const char * name
Definition: rply.hpp:537
#define BSIZE(p)
Definition: rply.hpp:667
p_ply_element ply_get_next_element(p_ply ply, p_ply_element last)
Definition: rply.hpp:1335
p_ply_property property
Definition: rply.hpp:474
Definition: rply.hpp:116
static int iascii_uint32(p_ply ply, double *value)
Definition: rply.hpp:758
static int obinary_float64(p_ply ply, double value)
Definition: rply.hpp:920
t_ply_idriver * p_ply_idriver
Definition: rply.hpp:530
Definition: rply.hpp:113
Definition: rply.hpp:121
long idata
Definition: rply.hpp:586
int(* p_ply_ohandler)(p_ply ply, double value)
Definition: rply.hpp:532
static int ply_read_header_format(p_ply ply)
Definition: rply.hpp:1809
#define BFIRST(p)
Definition: rply.hpp:664
static int oascii_uint32(p_ply ply, double value)
Definition: rply.hpp:863
static int ply_read_header_obj_info(p_ply ply)
Definition: rply.hpp:1834
int ply_get_argument_element(p_ply_argument argument, p_ply_element *element, long *instance_index)
Definition: rply.hpp:1391
p_ply_ohandler ohandler[16]
Definition: rply.hpp:535
int rn
Definition: rply.hpp:576
static int ply_read_scalar_property(p_ply ply, p_ply_element element, p_ply_property property, p_ply_argument argument)
Definition: rply.hpp:1478
static int iascii_float32(p_ply ply, double *value)
Definition: rply.hpp:766
static int obinary_float32(p_ply ply, double value)
Definition: rply.hpp:914
int ply_add_comment(p_ply ply, const char *comment)
Definition: rply.hpp:1187
static int oascii_uint8(p_ply ply, double value)
Definition: rply.hpp:843
e_ply_io_mode io_mode
Definition: rply.hpp:567
const char * name
Definition: rply.hpp:528
Definition: rply.hpp:123
long nproperties
Definition: rply.hpp:513
long idata
Definition: rply.hpp:496
static void ply_ferror(p_ply ply, const char *fmt,...)
Definition: rply.hpp:1902
static int ply_read_header_element(p_ply ply)
Definition: rply.hpp:1871
long nelements
Definition: rply.hpp:570