1 #ifndef IGL_PLY_H
2 #define IGL_PLY_H
3 /*
4 
5 Header for PLY polygon files.
6 
7 - Greg Turk, March 1994
8 
9 A PLY file contains a single polygonal _object_.
10 
11 An object is composed of lists of _elements_.  Typical elements are
12 vertices, faces, edges and materials.
13 
14 Each type of element for a given object has one or more _properties_
15 associated with the element type.  For instance, a vertex element may
16 have as properties three floating-point values x,y,z and three unsigned
17 chars for red, green and blue.
18 
19 ---------------------------------------------------------------
20 
21 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
22 Junior University.  All rights reserved.
23 
24 Permission to use, copy, modify and distribute this software and its
25 documentation for any purpose is hereby granted without fee, provided
26 that the above copyright notice and this permission notice appear in
27 all copies of this software and that you do not sell the software.
28 
29 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
31 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
32 
33 */
34 
35 /*
36 --------------------------------------------------------------------------------
37 Joao Fradinho Oliveira, July 2005
38 Copyright (c) 2005 University College London
39 copyright conditions as above
40 
41 update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
42 --------------------------------------------------------------------------------
43 
44 ply_open_for_reading
45 
46 * was changed to always open files in binary mode, files written in ascii can also be
47 read with this binary mode.
48 
49 * allows opening of filenames that are alias files in macintosh
50 
51 * code tested on pc and mac
52 
53 
54 get_words
55 
56 * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
57 accordingly for the next read.
58 
59 
60 NOTES:
61 The ply file, has always an ascii part for the header, and a binary or ascii
62 part for the data.
63 The header part in ascii, dictates that linebreaks are used, this make models
64 operating system dependent, as a line break in unix is indicated with the escape character \n,
65 on a macintosh, with \r, and on a pc with \r\n  <--2 unsigned chars, 2 bytes, instead of 1 byte.
66 
67 get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
68 properly to target OSs with binary files.
69 
70 */
71 
72 #ifndef __PLY_H__
73 #define __PLY_H__
74 
75 
76 
77 #include <stdlib.h>
78 #include <stdio.h>
79 #include <stddef.h>
80 #include <string.h>
81 
82 namespace igl {
83     namespace ply {
84 
85 #define PLY_ASCII         1      /* ascii PLY file */
86 #define PLY_BINARY_BE     2      /* binary PLY file, big endian */
87 #define PLY_BINARY_LE     3      /* binary PLY file, little endian */
88 #define PLY_BINARY_NATIVE 4      /* binary PLY file, same endianness as
89 				    current architecture */
90 
91 #define PLY_OKAY    0           /* ply routine worked okay */
92 #define PLY_ERROR  -1           /* error in ply routine */
93 
94 /* scalar data types supported by PLY format */
95 
96 #define PLY_START_TYPE 0
97 #define PLY_CHAR       1
98 #define PLY_SHORT      2
99 #define PLY_INT        3
100 #define PLY_UCHAR      4
101 #define PLY_USHORT     5
102 #define PLY_UINT       6
103 #define PLY_FLOAT      7
104 #define PLY_DOUBLE     8
105 #define PLY_END_TYPE   9
106 
107 #define  PLY_SCALAR  0
108 #define  PLY_LIST    1
109 
110 
111 
112 
113 typedef struct PlyProperty {    /* description of a property */
114 
115   const char *name;                           /* property name */
116   int external_type;                    /* file's data type */
117   int internal_type;                    /* program's data type */
118   int offset;                           /* offset bytes of prop in a struct */
119 
120   int is_list;                          /* 1 = list, 0 = scalar */
121   int count_external;                   /* file's count type */
122   int count_internal;                   /* program's count type */
123   int count_offset;                     /* offset byte for list count */
124 
125 } PlyProperty;
126 
127 typedef struct PlyElement {     /* description of an element */
128   const char *name;                   /* element name */
129   int num;                      /* number of elements in this object */
130   int size;                     /* size of element (bytes) or -1 if variable */
131   int nprops;                   /* number of properties for this element */
132   PlyProperty **props;          /* list of properties in the file */
133   char *store_prop;             /* flags: property wanted by user? */
134   int other_offset;             /* offset to un-asked-for props, or -1 if none*/
135   int other_size;               /* size of other_props structure */
136 } PlyElement;
137 
138 typedef struct PlyOtherProp {   /* describes other properties in an element */
139   const char *name;                   /* element name */
140   int size;                     /* size of other_props */
141   int nprops;                   /* number of properties in other_props */
142   PlyProperty **props;          /* list of properties in other_props */
143 } PlyOtherProp;
144 
145 typedef struct OtherData { /* for storing other_props for an other element */
146   void *other_props;
147 } OtherData;
148 
149 typedef struct OtherElem {     /* data for one "other" element */
150   char *elem_name;             /* names of other elements */
151   int elem_count;              /* count of instances of each element */
152   OtherData **other_data;      /* actual property data for the elements */
153   PlyOtherProp *other_props;   /* description of the property data */
154 } OtherElem;
155 
156 typedef struct PlyOtherElems {  /* "other" elements, not interpreted by user */
157   int num_elems;                /* number of other elements */
158   OtherElem *other_list;        /* list of data for other elements */
159 } PlyOtherElems;
160 
161 typedef struct PlyFile {        /* description of PLY file */
162   FILE *fp;                     /* file pointer */
163   int file_type;                /* ascii or binary */
164   float version;                /* version number of file */
165   int nelems;                   /* number of elements of object */
166   PlyElement **elems;           /* list of elements */
167   int num_comments;             /* number of comments */
168   char **comments;              /* list of comments */
169   int num_obj_info;             /* number of items of object information */
170   char **obj_info;              /* list of object info items */
171   PlyElement *which_elem;       /* which element we're currently writing */
172   PlyOtherElems *other_elems;   /* "other" elements from a PLY file */
173 } PlyFile;
174 
175 /* memory allocation */
176 extern char *my_alloc();
177 #define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
178 
179 #ifndef ALLOCN
180 #define REALLOCN(PTR,TYPE,OLD_N,NEW_N)							\
181         {										\
182 	    if ((OLD_N) == 0)                                           		\
183 	    {   ALLOCN((PTR),TYPE,(NEW_N));}                            		\
184 	    else									\
185 	    {								    		\
186 	       (PTR) = (TYPE *)realloc((PTR),(NEW_N)*sizeof(TYPE));			\
187 	       if (((PTR) == NULL) && ((NEW_N) != 0))					\
188 	       {									\
189 		   fprintf(stderr, "Memory reallocation failed on line %d in %s\n", 	\
190 		           __LINE__, __FILE__);                             		\
191 		   fprintf(stderr, "  tried to reallocate %d->%d\n",       		\
192 			   (OLD_N), (NEW_N));                              		\
193 		   exit(-1);								\
194 	       }									\
195 	       if ((NEW_N)>(OLD_N))							\
196 		   memset((char *)(PTR)+(OLD_N)*sizeof(TYPE), 0,			\
197 		          ((NEW_N)-(OLD_N))*sizeof(TYPE));				\
198 	    }										\
199 	}
200 
201 #define  ALLOCN(PTR,TYPE,N) 					\
202 	{ (PTR) = (TYPE *) calloc(((unsigned)(N)),sizeof(TYPE));\
203 	  if ((PTR) == NULL) {    				\
204 	  fprintf(stderr, "Memory allocation failed on line %d in %s\n", \
205 		 __LINE__, __FILE__);                           \
206 	  exit(-1);                                             \
207 	  }							\
208 	}
209 
210 
211 #define FREE(PTR)  { free((PTR)); (PTR) = NULL; }
212 #endif
213 
214 
215 /*** delcaration of routines ***/
216 
217 inline int get_native_binary_type2();
218 
219 inline PlyFile *ply_write(FILE *, int,const char **, int);
220 inline PlyFile *ply_open_for_writing(char *, int,const char **, int, float *);
221 inline void ply_describe_element(PlyFile *, const char *, int, int, PlyProperty *);
222 inline void ply_describe_property(PlyFile *, const char *, PlyProperty *);
223 inline void ply_element_count(PlyFile *, const char *, int);
224 inline void ply_header_complete(PlyFile *);
225 inline void ply_put_element_setup(PlyFile *, const char *);
226 inline void ply_put_element(PlyFile *, void *, int*);
227 inline void ply_put_comment(PlyFile *, char *);
228 inline void ply_put_obj_info(PlyFile *, char *);
229 inline PlyFile *ply_read(FILE *, int *, char ***);
230 inline PlyFile *ply_open_for_reading( const char *, int *, char ***, int *, float *);
231 inline PlyProperty **ply_get_element_description(PlyFile *, const char *, int*, int*);
232 inline void ply_get_element_setup( PlyFile *, const char *, int, PlyProperty *);
233 inline void ply_get_property(PlyFile *, const char *, PlyProperty *);
234 inline PlyOtherProp *ply_get_other_properties(PlyFile *, const char *, int);
235 inline void ply_get_element(PlyFile *, void *, int *);
236 inline char **ply_get_comments(PlyFile *, int *);
237 inline char **ply_get_obj_info(PlyFile *, int *);
238 inline void ply_close(PlyFile *);
239 inline void ply_get_info(PlyFile *, float *, int *);
240 inline PlyOtherElems *ply_get_other_element (PlyFile *, const char *, int);
241 inline void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
242 inline void ply_put_other_elements (PlyFile *);
243 inline void ply_free_other_elements (PlyOtherElems *);
244 inline void ply_describe_other_properties(PlyFile *, PlyOtherProp *, int);
245 
246 inline int equal_strings(const char *, const char *);
247 
248 
249 }
250 }
251 #endif /* !__PLY_H__ */
252 /*
253 
254 The interface routines for reading and writing PLY polygon files.
255 
256 Greg Turk, February 1994
257 
258 ---------------------------------------------------------------
259 
260 A PLY file contains a single polygonal _object_.
261 
262 An object is composed of lists of _elements_.  Typical elements are
263 vertices, faces, edges and materials.
264 
265 Each type of element for a given object has one or more _properties_
266 associated with the element type.  For instance, a vertex element may
267 have as properties the floating-point values x,y,z and the three unsigned
268 chars representing red, green and blue.
269 
270 ---------------------------------------------------------------
271 
272 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
273 Junior University.  All rights reserved.
274 
275 Permission to use, copy, modify and distribute this software and its
276 documentation for any purpose is hereby granted without fee, provided
277 that the above copyright notice and this permission notice appear in
278 all copies of this software and that you do not sell the software.
279 
280 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
281 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
282 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
283 
284 */
285 
286 /*
287 --------------------------------------------------------------------------------
288 Joao Fradinho Oliveira, July 2005
289 University College London
290 
291 update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
292 --------------------------------------------------------------------------------
293 
294 ply_open_for_reading
295 
296 * was changed to always open files in binary mode, files written in ascii can also be
297 read with this binary mode.
298 
299 * allows opening of filenames that are alias files in macintosh
300 
301 * code tested on pc and mac
302 
303 
304 get_words
305 
306 * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
307 accordingly for the next read.
308 
309 
310 NOTES:
311 The ply file, has always an ascii part for the header, and a binary or ascii
312 part for the data.
313 The header part in ascii, dictates that linebreaks are used, this make models
314 operating system dependent, as a line break in unix is indicated with the escape character \n,
315 on a macintosh, with \r, and on a pc with \r\n  <--2 unsigned chars, 2 bytes, instead of 1 byte.
316 
317 get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
318 properly to target OSs with binary files.
319 
320 */
321 
322 #include <stdio.h>
323 #include <stdlib.h>
324 #include <math.h>
325 #include <string.h>
326 //#include "ply.h"
327 
328 
329 namespace igl {
330     namespace ply {
331 
332 
333 // Use unnamed namespace to avoid duplicate symbols
334 /*
335 namespace
336 {
337 const char *type_names[] = {
338 "invalid",
339 "char", "short", "int",
340 "uchar", "ushort", "uint",
341 "float", "double",
342 };
343 
344 //  names of scalar types
345 const char *alt_type_names[] = {
346 "invalid",
347 "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
348 };
349 
350 int ply_type_size[] = {
351   0, 1, 2, 4, 1, 2, 4, 4, 8
352 };
353 }
354 
355 typedef union
356 {
357       int  int_value;
358       char byte_values[sizeof(int)];
359 } endian_test_type;
360 
361 
362 namespace
363 {
364 static int native_binary_type = -1;
365 static int types_checked = 0;
366 }
367 */
368 
369 #define NO_OTHER_PROPS  -1
370 
371 #define DONT_STORE_PROP  0
372 #define STORE_PROP       1
373 
374 #define OTHER_PROP       0
375 #define NAMED_PROP       1
376 
377 /* returns 1 if strings are equal, 0 if not */
378 inline int equal_strings(const char *, const char *);
379 
380 /* find an element in a plyfile's list */
381 inline PlyElement *find_element(PlyFile *, const char *);
382 
383 /* find a property in an element's list */
384 inline PlyProperty *find_property(PlyElement *, const char *, int *);
385 
386 /* write to a file the word describing a PLY file data type */
387 inline void write_scalar_type (FILE *, int);
388 
389 /* read a line from a file and break it up into separate words */
390 inline char **get_words(FILE *, int *, char **);
391 inline char **old_get_words(FILE *, int *);
392 
393 /* write an item to a file */
394 inline void write_binary_item(FILE *, int, int, unsigned int, double, int, int*);
395 inline void write_ascii_item(FILE *, int, unsigned int, double, int);
396 inline double old_write_ascii_item(FILE *, char *, int);
397 
398 /* add information to a PLY file descriptor */
399 inline void add_element(PlyFile *, char **);
400 inline void add_property(PlyFile *, char **);
401 inline void add_comment(PlyFile *, char *);
402 inline void add_obj_info(PlyFile *, char *);
403 
404 /* copy a property */
405 inline void copy_property(PlyProperty *, PlyProperty *);
406 
407 /* store a value into where a pointer and a type specify */
408 inline void store_item(char *, int, int, unsigned int, double);
409 
410 /* return the value of a stored item */
411 inline void get_stored_item( void *, int, int *, unsigned int *, double *);
412 
413 /* return the value stored in an item, given ptr to it and its type */
414 inline double get_item_value(char *, int);
415 
416 /* get binary or ascii item and store it according to ptr and type */
417 inline void get_ascii_item(char *, int, int *, unsigned int *, double *);
418 inline void get_binary_item(FILE *, int, int, int *, unsigned int *, double *, int*);
419 
420 /* get a bunch of elements from a file */
421 inline void ascii_get_element(PlyFile *, char *);
422 inline void binary_get_element(PlyFile *, char *, int*);
423 
424 /* memory allocation */
425 inline char *my_alloc(int, int, const char *);
426 
427 /* byte ordering */
428 inline void get_native_binary_type(int*);
429 inline void swap_bytes(char *, int);
430 
431 inline int check_types();
432 
433 
434 /*************/
435 /*  Writing  */
436 /*************/
437 
438 
439 /******************************************************************************
440 Given a file pointer, get ready to write PLY data to the file.
441 
442 Entry:
443   fp         - the given file pointer
444   nelems     - number of elements in object
445   elem_names - list of element names
446   file_type  - file type, either ascii or binary
447 
448 Exit:
449   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
450 ******************************************************************************/
451 
ply_write(FILE * fp,int nelems,const char ** elem_names,int file_type)452 inline PlyFile *ply_write(
453   FILE *fp,
454   int nelems,
455   const char **elem_names,
456   int file_type
457 )
458 {
459   int i;
460   PlyFile *plyfile;
461   PlyElement *elem;
462 
463   /* check for NULL file pointer */
464   if (fp == NULL)
465     return (NULL);
466 
467 	int native_binary_type = -1;
468 	int types_checked = 0;
469   if (native_binary_type == -1)
470      native_binary_type = get_native_binary_type2();
471   if (!types_checked)
472      types_checked = check_types();
473 
474   /* create a record for this object */
475 
476   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
477   if (file_type == PLY_BINARY_NATIVE)
478      plyfile->file_type = native_binary_type;
479   else
480      plyfile->file_type = file_type;
481   plyfile->num_comments = 0;
482   plyfile->num_obj_info = 0;
483   plyfile->nelems = nelems;
484   plyfile->version = 1.0;
485   plyfile->fp = fp;
486   plyfile->other_elems = NULL;
487 
488   /* tuck aside the names of the elements */
489 
490   plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
491   for (i = 0; i < nelems; i++) {
492     elem = (PlyElement *) myalloc (sizeof (PlyElement));
493     plyfile->elems[i] = elem;
494     elem->name = strdup (elem_names[i]);
495     elem->num = 0;
496     elem->nprops = 0;
497   }
498 
499   /* return pointer to the file descriptor */
500   return (plyfile);
501 }
502 
503 
504 /******************************************************************************
505 Open a polygon file for writing.
506 
507 Entry:
508   filename   - name of file to read from
509   nelems     - number of elements in object
510   elem_names - list of element names
511   file_type  - file type, either ascii or binary
512 
513 Exit:
514   version - version number of PLY file
515   returns a file identifier, used to refer to this file, or NULL if error
516 ******************************************************************************/
517 
ply_open_for_writing(const char * filename,int nelems,const char ** elem_names,int file_type,float * version)518 inline PlyFile *ply_open_for_writing(
519   const char *filename,
520   int nelems,
521   const char **elem_names,
522   int file_type,
523   float *version
524 )
525 {
526   PlyFile *plyfile;
527   char *name;
528   FILE *fp;
529 
530   /* tack on the extension .ply, if necessary */
531 
532   name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
533   strcpy (name, filename);
534   if (strlen (name) < 4 ||
535       strcmp (name + strlen (name) - 4, ".ply") != 0)
536       strcat (name, ".ply");
537 
538   /* open the file for writing */
539 
540   fp = fopen (name, "w");
541   if (fp == NULL) {
542     return (NULL);
543   }
544 
545   /* create the actual PlyFile structure */
546 
547   plyfile = ply_write (fp, nelems, elem_names, file_type);
548   if (plyfile == NULL)
549     return (NULL);
550 
551   /* say what PLY file version number we're writing */
552   *version = plyfile->version;
553 
554   /* return pointer to the file descriptor */
555   return (plyfile);
556 }
557 
558 
559 /******************************************************************************
560 Describe an element, including its properties and how many will be written
561 to the file.
562 
563 Entry:
564   plyfile   - file identifier
565   elem_name - name of element that information is being specified about
566   nelems    - number of elements of this type to be written
567   nprops    - number of properties contained in the element
568   prop_list - list of properties
569 ******************************************************************************/
570 
ply_describe_element(PlyFile * plyfile,const char * elem_name,int nelems,int nprops,PlyProperty * prop_list)571 inline void ply_describe_element(
572   PlyFile *plyfile,
573   const char *elem_name,
574   int nelems,
575   int nprops,
576   PlyProperty *prop_list
577 )
578 {
579   int i;
580   PlyElement *elem;
581   PlyProperty *prop;
582 
583   /* look for appropriate element */
584   elem = find_element (plyfile, elem_name);
585   if (elem == NULL) {
586     fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
587     exit (-1);
588   }
589 
590   elem->num = nelems;
591 
592   /* copy the list of properties */
593 
594   elem->nprops = nprops;
595   elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
596   elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
597 
598   for (i = 0; i < nprops; i++) {
599     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
600     elem->props[i] = prop;
601     elem->store_prop[i] = NAMED_PROP;
602     copy_property (prop, &prop_list[i]);
603   }
604 }
605 
606 
607 /******************************************************************************
608 Describe a property of an element.
609 
610 Entry:
611   plyfile   - file identifier
612   elem_name - name of element that information is being specified about
613   prop      - the new property
614 ******************************************************************************/
615 
ply_describe_property(PlyFile * plyfile,const char * elem_name,PlyProperty * prop)616 inline void ply_describe_property(
617   PlyFile *plyfile,
618   const char *elem_name,
619   PlyProperty *prop
620 )
621 {
622   PlyElement *elem;
623   PlyProperty *elem_prop;
624 
625   /* look for appropriate element */
626   elem = find_element (plyfile, elem_name);
627   if (elem == NULL) {
628     fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
629             elem_name);
630     return;
631   }
632 
633   /* create room for new property */
634 
635   if (elem->nprops == 0) {
636     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
637     elem->store_prop = (char *) myalloc (sizeof (char));
638     elem->nprops = 1;
639   }
640   else {
641     elem->nprops++;
642     elem->props = (PlyProperty **)
643                   realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
644     elem->store_prop = (char *)
645                   realloc (elem->store_prop, sizeof (char) * elem->nprops);
646   }
647 
648   /* copy the new property */
649 
650   elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
651   elem->props[elem->nprops - 1] = elem_prop;
652   elem->store_prop[elem->nprops - 1] = NAMED_PROP;
653   copy_property (elem_prop, prop);
654 }
655 
656 
657 /******************************************************************************
658 Describe what the "other" properties are that are to be stored, and where
659 they are in an element.
660 ******************************************************************************/
661 
ply_describe_other_properties(PlyFile * plyfile,PlyOtherProp * other,int offset)662 inline void ply_describe_other_properties(
663   PlyFile *plyfile,
664   PlyOtherProp *other,
665   int offset
666 )
667 {
668   int i;
669   PlyElement *elem;
670   PlyProperty *prop;
671 
672   /* look for appropriate element */
673   elem = find_element (plyfile, other->name);
674   if (elem == NULL) {
675     fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
676             other->name);
677     return;
678   }
679 
680   /* create room for other properties */
681 
682   if (elem->nprops == 0) {
683     elem->props = (PlyProperty **)
684                   myalloc (sizeof (PlyProperty *) * other->nprops);
685     elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
686     elem->nprops = 0;
687   }
688   else {
689     int newsize;
690     newsize = elem->nprops + other->nprops;
691     elem->props = (PlyProperty **)
692                   realloc (elem->props, sizeof (PlyProperty *) * newsize);
693     elem->store_prop = (char *)
694                   realloc (elem->store_prop, sizeof (char) * newsize);
695   }
696 
697   /* copy the other properties */
698 
699   for (i = 0; i < other->nprops; i++) {
700     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
701     copy_property (prop, other->props[i]);
702     elem->props[elem->nprops] = prop;
703     elem->store_prop[elem->nprops] = OTHER_PROP;
704     elem->nprops++;
705   }
706 
707   /* save other info about other properties */
708   elem->other_size = other->size;
709   elem->other_offset = offset;
710 }
711 
712 
713 /******************************************************************************
714 State how many of a given element will be written.
715 
716 Entry:
717   plyfile   - file identifier
718   elem_name - name of element that information is being specified about
719   nelems    - number of elements of this type to be written
720 ******************************************************************************/
721 
ply_element_count(PlyFile * plyfile,const char * elem_name,int nelems)722 inline void ply_element_count(
723   PlyFile *plyfile,
724   const char *elem_name,
725   int nelems
726 )
727 {
728   PlyElement *elem;
729 
730   /* look for appropriate element */
731   elem = find_element (plyfile, elem_name);
732   if (elem == NULL) {
733     fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
734     exit (-1);
735   }
736 
737   elem->num = nelems;
738 }
739 
740 
741 /******************************************************************************
742 Signal that we've described everything a PLY file's header and that the
743 header should be written to the file.
744 
745 Entry:
746   plyfile - file identifier
747 ******************************************************************************/
748 
ply_header_complete(PlyFile * plyfile)749 inline void ply_header_complete(PlyFile *plyfile)
750 {
751   int i,j;
752   FILE *fp = plyfile->fp;
753   PlyElement *elem;
754   PlyProperty *prop;
755 
756   fprintf (fp, "ply\n");
757 
758   switch (plyfile->file_type) {
759     case PLY_ASCII:
760       fprintf (fp, "format ascii 1.0\n");
761       break;
762     case PLY_BINARY_BE:
763       fprintf (fp, "format binary_big_endian 1.0\n");
764       break;
765     case PLY_BINARY_LE:
766       fprintf (fp, "format binary_little_endian 1.0\n");
767       break;
768     default:
769       fprintf (stderr, "ply_header_complete: bad file type = %d\n",
770                plyfile->file_type);
771       exit (-1);
772   }
773 
774   /* write out the comments */
775 
776   for (i = 0; i < plyfile->num_comments; i++)
777     fprintf (fp, "comment %s\n", plyfile->comments[i]);
778 
779   /* write out object information */
780 
781   for (i = 0; i < plyfile->num_obj_info; i++)
782     fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
783 
784   /* write out information about each element */
785 
786   for (i = 0; i < plyfile->nelems; i++) {
787 
788     elem = plyfile->elems[i];
789     fprintf (fp, "element %s %d\n", elem->name, elem->num);
790 
791     /* write out each property */
792     for (j = 0; j < elem->nprops; j++) {
793       prop = elem->props[j];
794       if (prop->is_list) {
795         fprintf (fp, "property list ");
796         write_scalar_type (fp, prop->count_external);
797         fprintf (fp, " ");
798         write_scalar_type (fp, prop->external_type);
799         fprintf (fp, " %s\n", prop->name);
800       }
801       else {
802         fprintf (fp, "property ");
803         write_scalar_type (fp, prop->external_type);
804         fprintf (fp, " %s\n", prop->name);
805       }
806     }
807   }
808 
809   fprintf (fp, "end_header\n");
810 }
811 
812 
813 /******************************************************************************
814 Specify which elements are going to be written.  This should be called
815 before a call to the routine ply_put_element().
816 
817 Entry:
818   plyfile   - file identifier
819   elem_name - name of element we're talking about
820 ******************************************************************************/
821 
ply_put_element_setup(PlyFile * plyfile,const char * elem_name)822 inline void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
823 {
824   PlyElement *elem;
825 
826   elem = find_element (plyfile, elem_name);
827   if (elem == NULL) {
828     fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
829     exit (-1);
830   }
831 
832   plyfile->which_elem = elem;
833 }
834 
835 
836 /******************************************************************************
837 Write an element to the file.  This routine assumes that we're
838 writing the type of element specified in the last call to the routine
839 ply_put_element_setup().
840 
841 Entry:
842   plyfile  - file identifier
843   elem_ptr - pointer to the element
844 ******************************************************************************/
845 
ply_put_element(PlyFile * plyfile,void * elem_ptr,int * native_binary_type)846 inline void ply_put_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
847 {
848   int j,k;
849   FILE *fp = plyfile->fp;
850   PlyElement *elem;
851   PlyProperty *prop;
852   char *elem_data,*item;
853   char **item_ptr;
854   int list_count;
855   int item_size;
856   int int_val;
857   unsigned int uint_val;
858   double double_val;
859   char **other_ptr;
860 
861   elem = plyfile->which_elem;
862   elem_data = (char *)elem_ptr;
863   other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
864 
865   /* write out either to an ascii or binary file */
866 	int ply_type_size[] = {
867 	  0, 1, 2, 4, 1, 2, 4, 4, 8
868 	};
869 
870   if (plyfile->file_type == PLY_ASCII) {
871 
872     /* write an ascii file */
873 
874     /* write out each property of the element */
875     for (j = 0; j < elem->nprops; j++) {
876       prop = elem->props[j];
877       if (elem->store_prop[j] == OTHER_PROP)
878         elem_data = *other_ptr;
879       else
880         elem_data = (char *)elem_ptr;
881       if (prop->is_list) {
882         item = elem_data + prop->count_offset;
883         get_stored_item ((void *) item, prop->count_internal,
884                          &int_val, &uint_val, &double_val);
885         write_ascii_item (fp, int_val, uint_val, double_val,
886                           prop->count_external);
887         list_count = uint_val;
888         item_ptr = (char **) (elem_data + prop->offset);
889         item = item_ptr[0];
890         item_size = ply_type_size[prop->internal_type];
891         for (k = 0; k < list_count; k++) {
892           get_stored_item ((void *) item, prop->internal_type,
893                            &int_val, &uint_val, &double_val);
894           write_ascii_item (fp, int_val, uint_val, double_val,
895                             prop->external_type);
896           item += item_size;
897         }
898       }
899       else {
900         item = elem_data + prop->offset;
901         get_stored_item ((void *) item, prop->internal_type,
902                          &int_val, &uint_val, &double_val);
903         write_ascii_item (fp, int_val, uint_val, double_val,
904                           prop->external_type);
905       }
906     }
907 
908     fprintf (fp, "\n");
909   }
910   else {
911 
912     /* write a binary file */
913 
914     /* write out each property of the element */
915     for (j = 0; j < elem->nprops; j++) {
916       prop = elem->props[j];
917       if (elem->store_prop[j] == OTHER_PROP)
918         elem_data = *other_ptr;
919       else
920         elem_data = (char *)elem_ptr;
921       if (prop->is_list) {
922         item = elem_data + prop->count_offset;
923         item_size = ply_type_size[prop->count_internal];
924         get_stored_item ((void *) item, prop->count_internal,
925                          &int_val, &uint_val, &double_val);
926         write_binary_item (fp, plyfile->file_type, int_val, uint_val,
927 			   double_val, prop->count_external, native_binary_type);
928         list_count = uint_val;
929         item_ptr = (char **) (elem_data + prop->offset);
930         item = item_ptr[0];
931         item_size = ply_type_size[prop->internal_type];
932         for (k = 0; k < list_count; k++) {
933           get_stored_item ((void *) item, prop->internal_type,
934                            &int_val, &uint_val, &double_val);
935           write_binary_item (fp, plyfile->file_type, int_val, uint_val,
936 			     double_val, prop->external_type, native_binary_type);
937           item += item_size;
938         }
939       }
940       else {
941         item = elem_data + prop->offset;
942         item_size = ply_type_size[prop->internal_type];
943         get_stored_item ((void *) item, prop->internal_type,
944                          &int_val, &uint_val, &double_val);
945         write_binary_item (fp, plyfile->file_type, int_val, uint_val,
946 			   double_val, prop->external_type, native_binary_type);
947       }
948     }
949 
950   }
951 }
952 
953 
954 /******************************************************************************
955 Specify a comment that will be written in the header.
956 
957 Entry:
958   plyfile - file identifier
959   comment - the comment to be written
960 ******************************************************************************/
961 
ply_put_comment(PlyFile * plyfile,char * comment)962 inline void ply_put_comment(PlyFile *plyfile, char *comment)
963 {
964   /* (re)allocate space for new comment */
965   if (plyfile->num_comments == 0)
966     plyfile->comments = (char **) myalloc (sizeof (char *));
967   else
968     plyfile->comments = (char **) realloc (plyfile->comments,
969                          sizeof (char *) * (plyfile->num_comments + 1));
970 
971   /* add comment to list */
972   plyfile->comments[plyfile->num_comments] = strdup (comment);
973   plyfile->num_comments++;
974 }
975 
976 
977 /******************************************************************************
978 Specify a piece of object information (arbitrary text) that will be written
979 in the header.
980 
981 Entry:
982   plyfile  - file identifier
983   obj_info - the text information to be written
984 ******************************************************************************/
985 
ply_put_obj_info(PlyFile * plyfile,char * obj_info)986 inline void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
987 {
988   /* (re)allocate space for new info */
989   if (plyfile->num_obj_info == 0)
990     plyfile->obj_info = (char **) myalloc (sizeof (char *));
991   else
992     plyfile->obj_info = (char **) realloc (plyfile->obj_info,
993                          sizeof (char *) * (plyfile->num_obj_info + 1));
994 
995   /* add info to list */
996   plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
997   plyfile->num_obj_info++;
998 }
999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 /*************/
1007 /*  Reading  */
1008 /*************/
1009 
1010 
1011 
1012 /******************************************************************************
1013 Given a file pointer, get ready to read PLY data from the file.
1014 
1015 Entry:
1016   fp - the given file pointer
1017 
1018 Exit:
1019   nelems     - number of elements in object
1020   elem_names - list of element names
1021   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
1022 ******************************************************************************/
1023 
ply_read(FILE * fp,int * nelems,char *** elem_names)1024 inline PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
1025 {
1026   int i,j;
1027   PlyFile *plyfile;
1028   int nwords;
1029   char **words;
1030   char **elist;
1031   PlyElement *elem;
1032   char *orig_line;
1033 
1034   /* check for NULL file pointer */
1035   if (fp == NULL)
1036     return (NULL);
1037 
1038 	int native_binary_type = -1;
1039 	int types_checked = 0;
1040 
1041   if (native_binary_type == -1)
1042      native_binary_type = get_native_binary_type2();
1043   if (!types_checked)
1044      types_checked = check_types();
1045 
1046   /* create record for this object */
1047 
1048   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
1049   plyfile->nelems = 0;
1050   plyfile->comments = NULL;
1051   plyfile->num_comments = 0;
1052   plyfile->obj_info = NULL;
1053   plyfile->num_obj_info = 0;
1054   plyfile->fp = fp;
1055   plyfile->other_elems = NULL;
1056 
1057   /* read and parse the file's header */
1058 
1059   words = get_words (plyfile->fp, &nwords, &orig_line);
1060   if (nwords == 0 || !words || !equal_strings (words[0], "ply"))
1061   {
1062        if (words)
1063 	 free(words);
1064 
1065 
1066       return (NULL);
1067   }
1068 
1069   while (words) {
1070 
1071     /* parse words */
1072 
1073     if (equal_strings (words[0], "format")) {
1074       if (nwords != 3) {
1075 	free(words);
1076 	return (NULL);
1077       }
1078       if (equal_strings (words[1], "ascii"))
1079         plyfile->file_type = PLY_ASCII;
1080       else if (equal_strings (words[1], "binary_big_endian"))
1081         plyfile->file_type = PLY_BINARY_BE;
1082       else if (equal_strings (words[1], "binary_little_endian"))
1083         plyfile->file_type = PLY_BINARY_LE;
1084       else {
1085 	free(words);
1086         return (NULL);
1087       }
1088       plyfile->version = atof (words[2]);
1089     }
1090     else if (equal_strings (words[0], "element"))
1091       add_element (plyfile, words);
1092     else if (equal_strings (words[0], "property"))
1093       add_property (plyfile, words);
1094     else if (equal_strings (words[0], "comment"))
1095       add_comment (plyfile, orig_line);
1096     else if (equal_strings (words[0], "obj_info"))
1097       add_obj_info (plyfile, orig_line);
1098     else if (equal_strings (words[0], "end_header")) {
1099       free(words);
1100       break;
1101     }
1102 
1103     /* free up words space */
1104     free (words);
1105 
1106     words = get_words (plyfile->fp, &nwords, &orig_line);
1107   }
1108 
1109   /* create tags for each property of each element, to be used */
1110   /* later to say whether or not to store each property for the user */
1111 
1112   for (i = 0; i < plyfile->nelems; i++) {
1113     elem = plyfile->elems[i];
1114     elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
1115     for (j = 0; j < elem->nprops; j++)
1116       elem->store_prop[j] = DONT_STORE_PROP;
1117     elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
1118   }
1119 
1120   /* set return values about the elements */
1121 
1122   elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
1123   for (i = 0; i < plyfile->nelems; i++)
1124     elist[i] = strdup (plyfile->elems[i]->name);
1125 
1126   *elem_names = elist;
1127   *nelems = plyfile->nelems;
1128 
1129   /* return a pointer to the file's information */
1130 
1131   return (plyfile);
1132 }
1133 
1134 
1135 /******************************************************************************
1136 Open a polygon file for reading.
1137 
1138 Entry:
1139   filename - name of file to read from
1140 
1141 Exit:
1142   nelems     - number of elements in object
1143   elem_names - list of element names
1144   file_type  - file type, either ascii or binary
1145   version    - version number of PLY file
1146   returns a file identifier, used to refer to this file, or NULL if error
1147 ******************************************************************************/
1148 
ply_open_for_reading(char * filename,int * nelems,char *** elem_names,int * file_type,float * version)1149 inline PlyFile *ply_open_for_reading(
1150   char *filename,
1151   int *nelems,
1152   char ***elem_names,
1153   int *file_type,
1154   float *version
1155 )
1156 {
1157   FILE *fp;
1158   PlyFile *plyfile;
1159   //char *name;
1160 
1161 
1162 
1163    /* tack on the extension .ply, if necessary */
1164 
1165   // removing below, to handle also macintosh alias filenames
1166   //name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
1167   //strcpy (name, filename);
1168   //if (strlen (name) < 4 ||
1169   //    strcmp (name + strlen (name) - 4, ".ply") != 0)
1170   //    strcat (name, ".ply");
1171 
1172   /* open the file for reading */
1173 
1174   //fp = fopen (name, "r");
1175 
1176   //opening file in binary, ascii data can be read in binary with get_words
1177   fp = fopen (filename, "rb");
1178 
1179   if (fp == NULL)
1180     return (NULL);
1181 
1182   /* create the PlyFile data structure */
1183 
1184   plyfile = ply_read (fp, nelems, elem_names);
1185 
1186   /* determine the file type and version */
1187 
1188   *file_type = plyfile->file_type;
1189   *version = plyfile->version;
1190 
1191   /* return a pointer to the file's information */
1192 
1193   return (plyfile);
1194 }
1195 
1196 
1197 /******************************************************************************
1198 Get information about a particular element.
1199 
1200 Entry:
1201   plyfile   - file identifier
1202   elem_name - name of element to get information about
1203 
1204 Exit:
1205   nelems   - number of elements of this type in the file
1206   nprops   - number of properties
1207   returns a list of properties, or NULL if the file doesn't contain that elem
1208 ******************************************************************************/
1209 
ply_get_element_description(PlyFile * plyfile,const char * elem_name,int * nelems,int * nprops)1210 inline PlyProperty **ply_get_element_description(
1211   PlyFile *plyfile,
1212   const char *elem_name,
1213   int *nelems,
1214   int *nprops
1215 )
1216 {
1217   int i;
1218   PlyElement *elem;
1219   PlyProperty *prop;
1220   PlyProperty **prop_list;
1221 
1222   /* find information about the element */
1223   elem = find_element (plyfile, elem_name);
1224   if (elem == NULL)
1225     return (NULL);
1226 
1227   *nelems = elem->num;
1228   *nprops = elem->nprops;
1229 
1230   /* make a copy of the element's property list */
1231   prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
1232   for (i = 0; i < elem->nprops; i++) {
1233     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
1234     copy_property (prop, elem->props[i]);
1235     prop_list[i] = prop;
1236   }
1237 
1238   /* return this duplicate property list */
1239   return (prop_list);
1240 }
1241 
1242 
1243 /******************************************************************************
1244 Specify which properties of an element are to be returned.  This should be
1245 called before a call to the routine ply_get_element().
1246 
1247 Entry:
1248   plyfile   - file identifier
1249   elem_name - which element we're talking about
1250   nprops    - number of properties
1251   prop_list - list of properties
1252 ******************************************************************************/
1253 
ply_get_element_setup(PlyFile * plyfile,const char * elem_name,int nprops,PlyProperty * prop_list)1254 inline void ply_get_element_setup(
1255   PlyFile *plyfile,
1256   const char *elem_name,
1257   int nprops,
1258   PlyProperty *prop_list
1259 )
1260 {
1261   int i;
1262   PlyElement *elem;
1263   PlyProperty *prop;
1264   int index;
1265 
1266   /* find information about the element */
1267   elem = find_element (plyfile, elem_name);
1268   plyfile->which_elem = elem;
1269 
1270   /* deposit the property information into the element's description */
1271   for (i = 0; i < nprops; i++) {
1272 
1273     /* look for actual property */
1274     prop = find_property (elem, prop_list[i].name, &index);
1275     if (prop == NULL) {
1276       fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
1277                prop_list[i].name, elem_name);
1278       continue;
1279     }
1280 
1281     /* store its description */
1282     prop->internal_type = prop_list[i].internal_type;
1283     prop->offset = prop_list[i].offset;
1284     prop->count_internal = prop_list[i].count_internal;
1285     prop->count_offset = prop_list[i].count_offset;
1286 
1287     /* specify that the user wants this property */
1288     elem->store_prop[index] = STORE_PROP;
1289   }
1290 }
1291 
1292 
1293 /******************************************************************************
1294 Specify a property of an element that is to be returned.  This should be
1295 called (usually multiple times) before a call to the routine ply_get_element().
1296 This routine should be used in preference to the less flexible old routine
1297 called ply_get_element_setup().
1298 
1299 Entry:
1300   plyfile   - file identifier
1301   elem_name - which element we're talking about
1302   prop      - property to add to those that will be returned
1303 ******************************************************************************/
1304 
ply_get_property(PlyFile * plyfile,const char * elem_name,PlyProperty * prop)1305 inline void ply_get_property(
1306   PlyFile *plyfile,
1307   const char *elem_name,
1308   PlyProperty *prop
1309 )
1310 {
1311   PlyElement *elem;
1312   PlyProperty *prop_ptr;
1313   int index;
1314 
1315   /* find information about the element */
1316   elem = find_element (plyfile, elem_name);
1317   plyfile->which_elem = elem;
1318 
1319   /* deposit the property information into the element's description */
1320 
1321   prop_ptr = find_property (elem, prop->name, &index);
1322   if (prop_ptr == NULL) {
1323     fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
1324              prop->name, elem_name);
1325     return;
1326   }
1327   prop_ptr->internal_type  = prop->internal_type;
1328   prop_ptr->offset         = prop->offset;
1329   prop_ptr->count_internal = prop->count_internal;
1330   prop_ptr->count_offset   = prop->count_offset;
1331 
1332   /* specify that the user wants this property */
1333   elem->store_prop[index] = STORE_PROP;
1334 }
1335 
1336 
1337 /******************************************************************************
1338 Read one element from the file.  This routine assumes that we're reading
1339 the type of element specified in the last call to the routine
1340 ply_get_element_setup().
1341 
1342 Entry:
1343   plyfile  - file identifier
1344   elem_ptr - pointer to location where the element information should be put
1345 ******************************************************************************/
1346 
ply_get_element(PlyFile * plyfile,void * elem_ptr,int * native_binary_type)1347 inline void ply_get_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
1348 {
1349   if (plyfile->file_type == PLY_ASCII)
1350     ascii_get_element (plyfile, (char *) elem_ptr);
1351   else
1352     binary_get_element (plyfile, (char *) elem_ptr, native_binary_type);
1353 }
1354 
1355 
1356 /******************************************************************************
1357 Extract the comments from the header information of a PLY file.
1358 
1359 Entry:
1360   plyfile - file identifier
1361 
1362 Exit:
1363   num_comments - number of comments returned
1364   returns a pointer to a list of comments
1365 ******************************************************************************/
1366 
ply_get_comments(PlyFile * plyfile,int * num_comments)1367 inline char **ply_get_comments(PlyFile *plyfile, int *num_comments)
1368 {
1369   *num_comments = plyfile->num_comments;
1370   return (plyfile->comments);
1371 }
1372 
1373 
1374 /******************************************************************************
1375 Extract the object information (arbitrary text) from the header information
1376 of a PLY file.
1377 
1378 Entry:
1379   plyfile - file identifier
1380 
1381 Exit:
1382   num_obj_info - number of lines of text information returned
1383   returns a pointer to a list of object info lines
1384 ******************************************************************************/
1385 
ply_get_obj_info(PlyFile * plyfile,int * num_obj_info)1386 inline char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
1387 {
1388   *num_obj_info = plyfile->num_obj_info;
1389   return (plyfile->obj_info);
1390 }
1391 
1392 
1393 /******************************************************************************
1394 Make ready for "other" properties of an element-- those properties that
1395 the user has not explicitly asked for, but that are to be stashed away
1396 in a special structure to be carried along with the element's other
1397 information.
1398 
1399 Entry:
1400   plyfile - file identifier
1401   elem    - element for which we want to save away other properties
1402 ******************************************************************************/
1403 
setup_other_props(PlyElement * elem)1404 inline void setup_other_props(PlyElement *elem)
1405 {
1406   int i;
1407   PlyProperty *prop;
1408   int size = 0;
1409   int type_size;
1410 
1411   /* Examine each property in decreasing order of size. */
1412   /* We do this so that all data types will be aligned by */
1413   /* word, half-word, or whatever within the structure. */
1414 	int ply_type_size[] = {
1415 	  0, 1, 2, 4, 1, 2, 4, 4, 8
1416 	};
1417 
1418   for (type_size = 8; type_size > 0; type_size /= 2) {
1419 
1420     /* add up the space taken by each property, and save this information */
1421     /* away in the property descriptor */
1422 
1423     for (i = 0; i < elem->nprops; i++) {
1424 
1425       /* don't bother with properties we've been asked to store explicitly */
1426       if (elem->store_prop[i])
1427         continue;
1428 
1429       prop = elem->props[i];
1430 
1431       /* internal types will be same as external */
1432       prop->internal_type = prop->external_type;
1433       prop->count_internal = prop->count_external;
1434 
1435       /* check list case */
1436       if (prop->is_list) {
1437 
1438         /* pointer to list */
1439         if (type_size == sizeof (void *)) {
1440           prop->offset = size;
1441           size += sizeof (void *);    /* always use size of a pointer here */
1442         }
1443 
1444         /* count of number of list elements */
1445         if (type_size == ply_type_size[prop->count_external]) {
1446           prop->count_offset = size;
1447           size += ply_type_size[prop->count_external];
1448         }
1449       }
1450       /* not list */
1451       else if (type_size == ply_type_size[prop->external_type]) {
1452         prop->offset = size;
1453         size += ply_type_size[prop->external_type];
1454       }
1455     }
1456 
1457   }
1458 
1459   /* save the size for the other_props structure */
1460   elem->other_size = size;
1461 }
1462 
1463 
1464 /******************************************************************************
1465 Specify that we want the "other" properties of an element to be tucked
1466 away within the user's structure.  The user needn't be concerned for how
1467 these properties are stored.
1468 
1469 Entry:
1470   plyfile   - file identifier
1471   elem_name - name of element that we want to store other_props in
1472   offset    - offset to where other_props will be stored inside user's structure
1473 
1474 Exit:
1475   returns pointer to structure containing description of other_props
1476 ******************************************************************************/
1477 
ply_get_other_properties(PlyFile * plyfile,const char * elem_name,int offset)1478 inline PlyOtherProp *ply_get_other_properties(
1479   PlyFile *plyfile,
1480   const char *elem_name,
1481   int offset
1482 )
1483 {
1484   int i;
1485   PlyElement *elem;
1486   PlyOtherProp *other;
1487   PlyProperty *prop;
1488   int nprops;
1489 
1490   /* find information about the element */
1491   elem = find_element (plyfile, elem_name);
1492   if (elem == NULL) {
1493     fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
1494              elem_name);
1495     return (NULL);
1496   }
1497 
1498   /* remember that this is the "current" element */
1499   plyfile->which_elem = elem;
1500 
1501   /* save the offset to where to store the other_props */
1502   elem->other_offset = offset;
1503 
1504   /* place the appropriate pointers, etc. in the element's property list */
1505   setup_other_props (elem);
1506 
1507   /* create structure for describing other_props */
1508   other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
1509   other->name = strdup (elem_name);
1510 #if 0
1511   if (elem->other_offset == NO_OTHER_PROPS) {
1512     other->size = 0;
1513     other->props = NULL;
1514     other->nprops = 0;
1515     return (other);
1516   }
1517 #endif
1518   other->size = elem->other_size;
1519   other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
1520 
1521   /* save descriptions of each "other" property */
1522   nprops = 0;
1523   for (i = 0; i < elem->nprops; i++) {
1524     if (elem->store_prop[i])
1525       continue;
1526     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
1527     copy_property (prop, elem->props[i]);
1528     other->props[nprops] = prop;
1529     nprops++;
1530   }
1531   other->nprops = nprops;
1532 
1533 #if 1
1534   /* set other_offset pointer appropriately if there are NO other properties */
1535   if (other->nprops == 0) {
1536     elem->other_offset = NO_OTHER_PROPS;
1537   }
1538 #endif
1539 
1540   /* return structure */
1541   return (other);
1542 }
1543 
1544 
1545 
1546 
1547 /*************************/
1548 /*  Other Element Stuff  */
1549 /*************************/
1550 
1551 
1552 
1553 
1554 /******************************************************************************
1555 Grab all the data for an element that a user does not want to explicitly
1556 read in.
1557 
1558 Entry:
1559   plyfile    - pointer to file
1560   elem_name  - name of element whose data is to be read in
1561   elem_count - number of instances of this element stored in the file
1562 
1563 Exit:
1564   returns pointer to ALL the "other" element data for this PLY file
1565 ******************************************************************************/
1566 
ply_get_other_element(PlyFile * plyfile,char * elem_name,int elem_count)1567 inline PlyOtherElems *ply_get_other_element (
1568   PlyFile *plyfile,
1569   char *elem_name,
1570   int elem_count
1571 )
1572 {
1573   int i;
1574   PlyElement *elem;
1575   PlyOtherElems *other_elems;
1576   OtherElem *other;
1577 
1578   /* look for appropriate element */
1579   elem = find_element (plyfile, elem_name);
1580   if (elem == NULL) {
1581     fprintf (stderr,
1582              "ply_get_other_element: can't find element '%s'\n", elem_name);
1583     exit (-1);
1584   }
1585 
1586   /* create room for the new "other" element, initializing the */
1587   /* other data structure if necessary */
1588 
1589   if (plyfile->other_elems == NULL) {
1590     plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
1591     other_elems = plyfile->other_elems;
1592     other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
1593     other = &(other_elems->other_list[0]);
1594     other_elems->num_elems = 1;
1595   }
1596   else {
1597     other_elems = plyfile->other_elems;
1598     other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
1599                               sizeof (OtherElem) * (other_elems->num_elems + 1));
1600     other = &(other_elems->other_list[other_elems->num_elems]);
1601     other_elems->num_elems++;
1602   }
1603 
1604   /* count of element instances in file */
1605   other->elem_count = elem_count;
1606 
1607   /* save name of element */
1608   other->elem_name = strdup (elem_name);
1609 
1610   /* create a list to hold all the current elements */
1611   other->other_data = (OtherData **)
1612                   malloc (sizeof (OtherData *) * other->elem_count);
1613 
1614   /* set up for getting elements */
1615   other->other_props = ply_get_other_properties (plyfile, elem_name,
1616                          offsetof(OtherData,other_props));
1617 
1618   /* grab all these elements */
1619   int native_binary_type = get_native_binary_type2();
1620   for (i = 0; i < other->elem_count; i++) {
1621     /* grab and element from the file */
1622     other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
1623     ply_get_element (plyfile, (void *) other->other_data[i], &native_binary_type);
1624   }
1625 
1626   /* return pointer to the other elements data */
1627   return (other_elems);
1628 }
1629 
1630 
1631 /******************************************************************************
1632 Pass along a pointer to "other" elements that we want to save in a given
1633 PLY file.  These other elements were presumably read from another PLY file.
1634 
1635 Entry:
1636   plyfile     - file pointer in which to store this other element info
1637   other_elems - info about other elements that we want to store
1638 ******************************************************************************/
1639 
ply_describe_other_elements(PlyFile * plyfile,PlyOtherElems * other_elems)1640 inline void ply_describe_other_elements (
1641   PlyFile *plyfile,
1642   PlyOtherElems *other_elems
1643 )
1644 {
1645   int i;
1646   OtherElem *other;
1647   PlyElement *elem;
1648 
1649   /* ignore this call if there is no other element */
1650   if (other_elems == NULL)
1651     return;
1652 
1653   /* save pointer to this information */
1654   plyfile->other_elems = other_elems;
1655 
1656   /* describe the other properties of this element */
1657   /* store them in the main element list as elements with
1658      only other properties */
1659 
1660   REALLOCN(plyfile->elems, PlyElement *,
1661 	   plyfile->nelems, plyfile->nelems + other_elems->num_elems);
1662   for (i = 0; i < other_elems->num_elems; i++) {
1663       other = &(other_elems->other_list[i]);
1664       elem = (PlyElement *) myalloc (sizeof (PlyElement));
1665       plyfile->elems[plyfile->nelems++] = elem;
1666       elem->name = strdup (other->elem_name);
1667       elem->num = other->elem_count;
1668       elem->nprops = 0;
1669       ply_describe_other_properties (plyfile, other->other_props,
1670 				     offsetof(OtherData,other_props));
1671   }
1672 }
1673 
1674 
1675 /******************************************************************************
1676 Write out the "other" elements specified for this PLY file.
1677 
1678 Entry:
1679   plyfile - pointer to PLY file to write out other elements for
1680 ******************************************************************************/
1681 
ply_put_other_elements(PlyFile * plyfile,int * native_binary_type)1682 inline void ply_put_other_elements (PlyFile *plyfile, int *native_binary_type)
1683 {
1684   int i,j;
1685   OtherElem *other;
1686 
1687   /* make sure we have other elements to write */
1688   if (plyfile->other_elems == NULL)
1689     return;
1690 
1691   /* write out the data for each "other" element */
1692 
1693   for (i = 0; i < plyfile->other_elems->num_elems; i++) {
1694 
1695     other = &(plyfile->other_elems->other_list[i]);
1696     ply_put_element_setup (plyfile, other->elem_name);
1697 
1698     /* write out each instance of the current element */
1699     for (j = 0; j < other->elem_count; j++)
1700       ply_put_element (plyfile, (void *) other->other_data[j], native_binary_type);
1701   }
1702 }
1703 
1704 
1705 /******************************************************************************
1706 Free up storage used by an "other" elements data structure.
1707 
1708 Entry:
1709   other_elems - data structure to free up
1710 ******************************************************************************/
1711 
ply_free_other_elements(PlyOtherElems * other_elems)1712 inline void ply_free_other_elements (PlyOtherElems *other_elems)
1713 {
1714   // Alec:
1715   //other_elems = other_elems;
1716   delete(other_elems);
1717 }
1718 
1719 
1720 
1721 /*******************/
1722 /*  Miscellaneous  */
1723 /*******************/
1724 
1725 
1726 
1727 /******************************************************************************
1728 Close a PLY file.
1729 
1730 Entry:
1731   plyfile - identifier of file to close
1732 ******************************************************************************/
1733 
ply_close(PlyFile * plyfile)1734 inline void ply_close(PlyFile *plyfile)
1735 {
1736   fclose (plyfile->fp);
1737   // Alec:
1738   plyfile->fp = NULL;
1739 
1740   /* free up memory associated with the PLY file */
1741   free (plyfile);
1742 }
1743 
1744 
1745 /******************************************************************************
1746 Get version number and file type of a PlyFile.
1747 
1748 Entry:
1749   ply - pointer to PLY file
1750 
1751 Exit:
1752   version - version of the file
1753   file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
1754 ******************************************************************************/
1755 
ply_get_info(PlyFile * ply,float * version,int * file_type)1756 inline void ply_get_info(PlyFile *ply, float *version, int *file_type)
1757 {
1758   if (ply == NULL)
1759     return;
1760 
1761   *version = ply->version;
1762   *file_type = ply->file_type;
1763 }
1764 
1765 
1766 /******************************************************************************
1767 Compare two strings.  Returns 1 if they are the same, 0 if not.
1768 ******************************************************************************/
1769 
equal_strings(const char * s1,const char * s2)1770 inline int equal_strings(const char *s1, const char *s2)
1771 {
1772 
1773   while (*s1 && *s2)
1774     if (*s1++ != *s2++)
1775       return (0);
1776 
1777   if (*s1 != *s2)
1778     return (0);
1779   else
1780     return (1);
1781 }
1782 
1783 
1784 /******************************************************************************
1785 Find an element from the element list of a given PLY object.
1786 
1787 Entry:
1788   plyfile - file id for PLY file
1789   element - name of element we're looking for
1790 
1791 Exit:
1792   returns the element, or NULL if not found
1793 ******************************************************************************/
1794 
find_element(PlyFile * plyfile,const char * element)1795 inline PlyElement *find_element(PlyFile *plyfile, const char *element)
1796 {
1797   int i;
1798 
1799   for (i = 0; i < plyfile->nelems; i++)
1800     if (equal_strings (element, plyfile->elems[i]->name))
1801       return (plyfile->elems[i]);
1802 
1803   return (NULL);
1804 }
1805 
1806 
1807 /******************************************************************************
1808 Find a property in the list of properties of a given element.
1809 
1810 Entry:
1811   elem      - pointer to element in which we want to find the property
1812   prop_name - name of property to find
1813 
1814 Exit:
1815   index - index to position in list
1816   returns a pointer to the property, or NULL if not found
1817 ******************************************************************************/
1818 
find_property(PlyElement * elem,const char * prop_name,int * index)1819 inline PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
1820 {
1821   int i;
1822 
1823   for (i = 0; i < elem->nprops; i++)
1824     if (equal_strings (prop_name, elem->props[i]->name)) {
1825       *index = i;
1826       return (elem->props[i]);
1827     }
1828 
1829   *index = -1;
1830   return (NULL);
1831 }
1832 
1833 
1834 /******************************************************************************
1835 Read an element from an ascii file.
1836 
1837 Entry:
1838   plyfile  - file identifier
1839   elem_ptr - pointer to element
1840 ******************************************************************************/
1841 
ascii_get_element(PlyFile * plyfile,char * elem_ptr)1842 inline void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
1843 {
1844 	int ply_type_size[] = {
1845 	  0, 1, 2, 4, 1, 2, 4, 4, 8
1846 	};
1847 
1848   int j,k;
1849   PlyElement *elem;
1850   PlyProperty *prop;
1851   char **words;
1852   int nwords;
1853   int which_word;
1854   char *elem_data,*item=NULL;
1855   char *item_ptr;
1856   int item_size;
1857   int int_val;
1858   unsigned int uint_val;
1859   double double_val;
1860   int list_count;
1861   int store_it;
1862   char **store_array;
1863   char *orig_line;
1864   char *other_data=NULL;
1865   int other_flag;
1866 
1867   /* the kind of element we're reading currently */
1868   elem = plyfile->which_elem;
1869 
1870   /* do we need to setup for other_props? */
1871 
1872   if (elem->other_offset != NO_OTHER_PROPS) {
1873     char **ptr;
1874     other_flag = 1;
1875     /* make room for other_props */
1876     other_data = (char *) myalloc (elem->other_size);
1877     /* store pointer in user's structure to the other_props */
1878     ptr = (char **) (elem_ptr + elem->other_offset);
1879     *ptr = other_data;
1880   }
1881   else
1882     other_flag = 0;
1883 
1884   /* read in the element */
1885 
1886   words = get_words (plyfile->fp, &nwords, &orig_line);
1887   if (words == NULL) {
1888     fprintf (stderr, "ply_get_element: unexpected end of file\n");
1889     exit (-1);
1890   }
1891 
1892   which_word = 0;
1893 
1894   for (j = 0; j < elem->nprops; j++) {
1895 
1896     prop = elem->props[j];
1897     store_it = (elem->store_prop[j] | other_flag);
1898 
1899     /* store either in the user's structure or in other_props */
1900   //  if (elem->store_prop[j])
1901       elem_data = elem_ptr;
1902     //else
1903       //elem_data = other_data;
1904 
1905     if (prop->is_list) {       /* a list */
1906 
1907       /* get and store the number of items in the list */
1908       get_ascii_item (words[which_word++], prop->count_external,
1909                       &int_val, &uint_val, &double_val);
1910       if (store_it) {
1911         item = elem_data + prop->count_offset;
1912         store_item(item, prop->count_internal, int_val, uint_val, double_val);
1913       }
1914 
1915       /* allocate space for an array of items and store a ptr to the array */
1916       list_count = int_val;
1917       item_size = ply_type_size[prop->internal_type];
1918       store_array = (char **) (elem_data + prop->offset);
1919 
1920       if (list_count == 0) {
1921         if (store_it)
1922           *store_array = NULL;
1923       }
1924       else {
1925         if (store_it) {
1926           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
1927 
1928           item = item_ptr;
1929           *store_array = item_ptr;
1930         }
1931 
1932         /* read items and store them into the array */
1933         for (k = 0; k < list_count; k++) {
1934           get_ascii_item (words[which_word++], prop->external_type,
1935                           &int_val, &uint_val, &double_val);
1936           if (store_it) {
1937             store_item (item, prop->internal_type,
1938                         int_val, uint_val, double_val);
1939             item += item_size;
1940           }
1941         }
1942       }
1943 
1944     }
1945     else {                     /* not a list */
1946       get_ascii_item (words[which_word++], prop->external_type,
1947                       &int_val, &uint_val, &double_val);
1948       if (store_it) {
1949         item = elem_data + prop->offset;
1950         store_item (item, prop->internal_type, int_val, uint_val, double_val);
1951       }
1952     }
1953 
1954   }
1955 
1956   free (words);
1957 }
1958 
1959 
1960 /******************************************************************************
1961 Read an element from a binary file.
1962 
1963 Entry:
1964   plyfile  - file identifier
1965   elem_ptr - pointer to an element
1966 ******************************************************************************/
1967 
binary_get_element(PlyFile * plyfile,char * elem_ptr,int * native_binary_type)1968 inline void binary_get_element(PlyFile *plyfile, char *elem_ptr, int *native_binary_type)
1969 {
1970   int j,k;
1971   PlyElement *elem;
1972   PlyProperty *prop;
1973   FILE *fp = plyfile->fp;
1974   char *elem_data,*item=NULL;
1975   char *item_ptr;
1976   int item_size;
1977   int int_val;
1978   unsigned int uint_val;
1979   double double_val;
1980   int list_count;
1981   int store_it;
1982   char **store_array;
1983   char *other_data=NULL;
1984   int other_flag;
1985 
1986 	int ply_type_size[] = {
1987 	  0, 1, 2, 4, 1, 2, 4, 4, 8
1988 	};
1989 
1990 
1991   /* the kind of element we're reading currently */
1992   elem = plyfile->which_elem;
1993 
1994   /* do we need to setup for other_props? */
1995 
1996   if (elem->other_offset != NO_OTHER_PROPS) {
1997     char **ptr;
1998     other_flag = 1;
1999     /* make room for other_props */
2000     other_data = (char *) myalloc (elem->other_size);
2001     /* store pointer in user's structure to the other_props */
2002     ptr = (char **) (elem_ptr + elem->other_offset);
2003     *ptr = other_data;
2004   }
2005   else
2006     other_flag = 0;
2007 
2008   /* read in a number of elements */
2009 
2010   for (j = 0; j < elem->nprops; j++) {
2011 
2012     prop = elem->props[j];
2013     store_it = (elem->store_prop[j] | other_flag);
2014 
2015     /* store either in the user's structure or in other_props */
2016 //    if (elem->store_prop[j])
2017       elem_data = elem_ptr;
2018 //    else
2019 //      elem_data = other_data;
2020 
2021     if (prop->is_list) {       /* a list */
2022 
2023       /* get and store the number of items in the list */
2024       get_binary_item (fp, plyfile->file_type, prop->count_external,
2025                       &int_val, &uint_val, &double_val, native_binary_type);
2026       if (store_it) {
2027         item = elem_data + prop->count_offset;
2028         store_item(item, prop->count_internal, int_val, uint_val, double_val);
2029       }
2030 
2031       /* allocate space for an array of items and store a ptr to the array */
2032       list_count = int_val;
2033 
2034       item_size = ply_type_size[prop->internal_type];
2035       store_array = (char **) (elem_data + prop->offset);
2036       if (list_count == 0) {
2037         if (store_it)
2038           *store_array = NULL;
2039       }
2040       else {
2041         if (store_it) {
2042           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
2043 
2044           item = item_ptr;
2045           *store_array = item_ptr;
2046         }
2047 
2048         // read items and store them into the array
2049         for (k = 0; k < list_count; k++) {
2050           get_binary_item (fp, plyfile->file_type, prop->external_type,
2051                           &int_val, &uint_val, &double_val, native_binary_type);
2052           if (store_it) {
2053              store_item (item, prop->internal_type,
2054                        int_val, uint_val, double_val);
2055             item += item_size;
2056           }
2057         }
2058 
2059 
2060 
2061       }
2062 
2063     }
2064     else {                     /* not a list */
2065       get_binary_item (fp, plyfile->file_type, prop->external_type,
2066                       &int_val, &uint_val, &double_val, native_binary_type);
2067       if (store_it) {
2068         item = elem_data + prop->offset;
2069         store_item (item, prop->internal_type, int_val, uint_val, double_val);
2070       }
2071     }
2072 
2073   }
2074 }
2075 
2076 
2077 /******************************************************************************
2078 Write to a file the word that represents a PLY data type.
2079 
2080 Entry:
2081   fp   - file pointer
2082   code - code for type
2083 ******************************************************************************/
2084 
write_scalar_type(FILE * fp,int code)2085 inline void write_scalar_type (FILE *fp, int code)
2086 {
2087   /* make sure this is a valid code */
2088 
2089   if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
2090     fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
2091     exit (-1);
2092   }
2093 
2094   /* write the code to a file */
2095 	const char *type_names[] = {
2096 	"invalid",
2097 	"char", "short", "int",
2098 	"uchar", "ushort", "uint",
2099 	"float", "double",
2100 	};
2101 
2102 
2103   fprintf (fp, "%s", type_names[code]);
2104 }
2105 
2106 /******************************************************************************
2107   Reverse the order in an array of bytes.  This is the conversion from big
2108   endian to little endian and vice versa
2109 
2110 Entry:
2111   bytes     - array of bytes to reverse (in place)
2112   num_bytes - number of bytes in array
2113 ******************************************************************************/
2114 
swap_bytes(char * bytes,int num_bytes)2115 inline void swap_bytes(char *bytes, int num_bytes)
2116 {
2117     int i;
2118     char temp;
2119 
2120     for (i=0; i < num_bytes/2; i++)
2121     {
2122 	temp = bytes[i];
2123 	bytes[i] = bytes[(num_bytes-1)-i];
2124 	bytes[(num_bytes-1)-i] = temp;
2125     }
2126 }
2127 
2128 /******************************************************************************
2129   Find out if this machine is big endian or little endian
2130 
2131   Exit:
2132     set global variable, native_binary_type =
2133                               either PLY_BINARY_BE or PLY_BINARY_LE
2134 
2135 ******************************************************************************/
2136 
get_native_binary_type(int * native_binary_type)2137 inline void get_native_binary_type(int *native_binary_type)
2138 {
2139     typedef union
2140 	{
2141 	      int  int_value;
2142 	      char byte_values[sizeof(int)];
2143 	} endian_test_type;
2144 
2145 
2146 	endian_test_type test;
2147 
2148 	test.int_value = 0;
2149     test.int_value = 1;
2150     if (test.byte_values[0] == 1)
2151        *native_binary_type = PLY_BINARY_LE;
2152     else if (test.byte_values[sizeof(int)-1] == 1)
2153        *native_binary_type = PLY_BINARY_BE;
2154     else
2155     {
2156 	fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
2157 	fprintf(stderr, "ply: Exiting...\n");
2158 	exit(1);
2159     }
2160 }
2161 
get_native_binary_type2()2162 inline int get_native_binary_type2()
2163 {
2164 	typedef union
2165 	{
2166 	      int  int_value;
2167 	      char byte_values[sizeof(int)];
2168 	} endian_test_type;
2169 
2170 
2171     endian_test_type test;
2172 
2173     test.int_value = 0;
2174     test.int_value = 1;
2175     if (test.byte_values[0] == 1)
2176        return PLY_BINARY_LE;
2177     else if (test.byte_values[sizeof(int)-1] == 1)
2178        return PLY_BINARY_BE;
2179     else
2180     {
2181 	fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
2182 	fprintf(stderr, "ply: Exiting...\n");
2183 	exit(1);
2184     }
2185 }
2186 
2187 /******************************************************************************
2188   Verify that all the native types are the sizes we need
2189 
2190 
2191 ******************************************************************************/
2192 
check_types()2193 inline int check_types()
2194 {
2195 	int ply_type_size[] = {
2196 	  0, 1, 2, 4, 1, 2, 4, 4, 8
2197 	};
2198 
2199     if ((ply_type_size[PLY_CHAR] != sizeof(char)) ||
2200 	(ply_type_size[PLY_SHORT] != sizeof(short)) ||
2201 	(ply_type_size[PLY_INT] != sizeof(int)) ||
2202 	(ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) ||
2203 	(ply_type_size[PLY_USHORT] != sizeof(unsigned short)) ||
2204 	(ply_type_size[PLY_UINT] != sizeof(unsigned int)) ||
2205 	(ply_type_size[PLY_FLOAT] != sizeof(float)) ||
2206 	(ply_type_size[PLY_DOUBLE] != sizeof(double)))
2207     {
2208 	fprintf(stderr, "ply: Type sizes do not match built-in types\n");
2209 	fprintf(stderr, "ply: Exiting...\n");
2210 	exit(1);
2211     }
2212 
2213 	return 1;
2214 }
2215 
2216 /******************************************************************************
2217 Get a text line from a file and break it up into words.
2218 
2219 IMPORTANT: The calling routine call "free" on the returned pointer once
2220 finished with it.
2221 
2222 Entry:
2223   fp - file to read from
2224 
2225 Exit:
2226   nwords    - number of words returned
2227   orig_line - the original line of characters
2228   returns a list of words from the line, or NULL if end-of-file
2229 ******************************************************************************/
2230 
get_words(FILE * fp,int * nwords,char ** orig_line)2231 inline char **get_words(FILE *fp, int *nwords, char **orig_line)
2232 {
2233   #define BIG_STRING 4096
2234   char str[BIG_STRING];
2235   char str_copy[BIG_STRING];
2236   char **words;
2237   int max_words = 10;
2238   int num_words = 0;
2239   char *ptr,*ptr2;
2240   char *result;
2241 
2242   fpos_t pos; //keep track of file pointer
2243   int nbytes;
2244   int nonUNIX;
2245   nonUNIX=0;
2246   nbytes=0;
2247   fgetpos(fp, &pos);
2248 
2249   words = (char **) myalloc (sizeof (char *) * max_words);
2250 
2251   /* read in a line */
2252   result = fgets (str, BIG_STRING, fp);
2253   if (result == NULL) {
2254     *nwords = 0;
2255     *orig_line = NULL;
2256     return (NULL);
2257   }
2258 
2259   /* convert line-feed and tabs into spaces */
2260   /* (this guarantees that there will be a space before the */
2261   /*  null character at the end of the string) */
2262 
2263   str[BIG_STRING-2] = ' ';
2264   str[BIG_STRING-1] = '\0';
2265 
2266   for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
2267     *ptr2 = *ptr;
2268     nbytes++;
2269     if (*ptr == '\t') {
2270       *ptr = ' ';
2271       *ptr2 = ' ';
2272     }
2273     else if (*ptr == '\n') {
2274       *ptr = ' '; //has to have a space, to be caught later when grouping words
2275       *ptr2 = '\0';
2276       break;
2277     }
2278     else if (*ptr == '\r')
2279     {	  //MAC line break
2280       nonUNIX=1;
2281       if(*(ptr+1)=='\n')		  //actuall PC line break
2282       {
2283       	nbytes++;
2284       }
2285 
2286      *ptr = ' ';
2287 
2288      *(ptr+1) = '\0';	//when reading mac, best end string here
2289      *ptr2 = '\0'; 		//note a pc \r is followed by \n
2290 
2291       break;
2292     }
2293   }
2294 
2295 
2296   /*check to see if a PC or MAC header was detected instead of UNIX*/
2297   if(nonUNIX==1)
2298   {
2299   	fsetpos(fp, &pos);
2300   	fseek(fp, nbytes, SEEK_CUR);
2301   }
2302 
2303   /* find the words in the line */
2304 
2305   ptr = str;
2306   while (*ptr != '\0') {
2307 
2308     /* jump over leading spaces */
2309     while (*ptr == ' ')
2310       ptr++;
2311 
2312     /* break if we reach the end */
2313     if (*ptr == '\0')
2314       break;
2315 
2316     /* save pointer to beginning of word */
2317     if (num_words >= max_words) {
2318       max_words += 10;
2319       words = (char **) realloc (words, sizeof (char *) * max_words);
2320     }
2321     words[num_words++] = ptr;
2322 
2323     /* jump over non-spaces */
2324     while (*ptr != ' ')
2325       ptr++;
2326 
2327     /* place a null character here to mark the end of the word */
2328     *ptr++ = '\0';
2329   }
2330 
2331   /* return the list of words */
2332   *nwords = num_words;
2333   *orig_line = str_copy;
2334   return (words);
2335 }
2336 
2337 /*
2338 char **get_words(FILE *fp, int *nwords, char **orig_line)
2339 {
2340 #define BIG_STRING 4096
2341   static char str[BIG_STRING];
2342   static char str_copy[BIG_STRING];
2343   char **words;
2344   int max_words = 10;
2345   int num_words = 0;
2346   char *ptr,*ptr2;
2347   char *result;
2348 
2349   words = (char **) myalloc (sizeof (char *) * max_words);
2350 
2351   // read in a line
2352   result = fgets (str, BIG_STRING, fp);
2353   if (result == NULL) {
2354     *nwords = 0;
2355     *orig_line = NULL;
2356     return (NULL);
2357   }
2358 
2359   // convert line-feed and tabs into spaces
2360   // (this guarantees that there will be a space before the
2361   //  null character at the end of the string)
2362 
2363   str[BIG_STRING-2] = ' ';
2364   str[BIG_STRING-1] = '\0';
2365 
2366   for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
2367     *ptr2 = *ptr;
2368     if (*ptr == '\t') {
2369       *ptr = ' ';
2370       *ptr2 = ' ';
2371     }
2372     else if (*ptr == '\n') {
2373       *ptr = ' ';
2374       *ptr2 = '\0';
2375       break;
2376     }
2377     else if (*ptr == '\r') {
2378       *ptr = '\0';
2379       *ptr2 = '\0'; //note don't break yet, on a pc \r is followed by \n
2380     }
2381   }
2382 
2383   // find the words in the line
2384 
2385   ptr = str;
2386   while (*ptr != '\0') {
2387 
2388     // jump over leading spaces
2389     while (*ptr == ' ')
2390       ptr++;
2391 
2392     // break if we reach the end
2393     if (*ptr == '\0')
2394       break;
2395 
2396     // save pointer to beginning of word
2397     if (num_words >= max_words) {
2398       max_words += 10;
2399       words = (char **) realloc (words, sizeof (char *) * max_words);
2400     }
2401     words[num_words++] = ptr;
2402 
2403     // jump over non-spaces
2404     while (*ptr != ' ')
2405       ptr++;
2406 
2407     // place a null character here to mark the end of the word
2408     *ptr++ = '\0';
2409   }
2410 
2411   // return the list of words
2412   *nwords = num_words;
2413   *orig_line = str_copy;
2414   return (words);
2415 }*/
2416 
2417 /******************************************************************************
2418 Return the value of an item, given a pointer to it and its type.
2419 
2420 Entry:
2421   item - pointer to item
2422   type - data type that "item" points to
2423 
2424 Exit:
2425   returns a double-precision float that contains the value of the item
2426 ******************************************************************************/
2427 
get_item_value(char * item,int type)2428 inline double get_item_value(char *item, int type)
2429 {
2430   unsigned char *puchar;
2431   char *pchar;
2432   short int *pshort;
2433   unsigned short int *pushort;
2434   int *pint;
2435   unsigned int *puint;
2436   float *pfloat;
2437   double *pdouble;
2438   int int_value;
2439   unsigned int uint_value;
2440   double double_value;
2441 
2442   switch (type) {
2443     case PLY_CHAR:
2444       pchar = (char *) item;
2445       int_value = *pchar;
2446       return ((double) int_value);
2447     case PLY_UCHAR:
2448       puchar = (unsigned char *) item;
2449       int_value = *puchar;
2450       return ((double) int_value);
2451     case PLY_SHORT:
2452       pshort = (short int *) item;
2453       int_value = *pshort;
2454       return ((double) int_value);
2455     case PLY_USHORT:
2456       pushort = (unsigned short int *) item;
2457       int_value = *pushort;
2458       return ((double) int_value);
2459     case PLY_INT:
2460       pint = (int *) item;
2461       int_value = *pint;
2462       return ((double) int_value);
2463     case PLY_UINT:
2464       puint = (unsigned int *) item;
2465       uint_value = *puint;
2466       return ((double) uint_value);
2467     case PLY_FLOAT:
2468       pfloat = (float *) item;
2469       double_value = *pfloat;
2470       return (double_value);
2471     case PLY_DOUBLE:
2472       pdouble = (double *) item;
2473       double_value = *pdouble;
2474       return (double_value);
2475     default:
2476       fprintf (stderr, "get_item_value: bad type = %d\n", type);
2477       exit (-1);
2478   }
2479 }
2480 
2481 
2482 /******************************************************************************
2483 Write out an item to a file as raw binary bytes.
2484 
2485 Entry:
2486   fp         - file to write to
2487   int_val    - integer version of item
2488   uint_val   - unsigned integer version of item
2489   double_val - double-precision float version of item
2490   type       - data type to write out
2491 ******************************************************************************/
2492 
write_binary_item(FILE * fp,int file_type,int int_val,unsigned int uint_val,double double_val,int type,int * native_binary_type)2493 inline void write_binary_item(
2494   FILE *fp,
2495   int file_type,
2496   int int_val,
2497   unsigned int uint_val,
2498   double double_val,
2499   int type,
2500   int *native_binary_type
2501 )
2502 {
2503   unsigned char uchar_val;
2504   char char_val;
2505   unsigned short ushort_val;
2506   short short_val;
2507   float float_val;
2508   void  *value;
2509 
2510   switch (type) {
2511     case PLY_CHAR:
2512       char_val = int_val;
2513       value = &char_val;
2514       break;
2515     case PLY_SHORT:
2516       short_val = int_val;
2517       value = &short_val;
2518       break;
2519     case PLY_INT:
2520       value = &int_val;
2521       break;
2522     case PLY_UCHAR:
2523       uchar_val = uint_val;
2524       value = &uchar_val;
2525       break;
2526     case PLY_USHORT:
2527       ushort_val = uint_val;
2528       value = &ushort_val;
2529       break;
2530     case PLY_UINT:
2531       value = &uint_val;
2532       break;
2533     case PLY_FLOAT:
2534       float_val = double_val;
2535       value = &float_val;
2536       break;
2537     case PLY_DOUBLE:
2538       value = &double_val;
2539       break;
2540     default:
2541       fprintf (stderr, "write_binary_item: bad type = %d\n", type);
2542       exit (-1);
2543   }
2544 	int ply_type_size[] = {
2545 	  0, 1, 2, 4, 1, 2, 4, 4, 8
2546 	};
2547 
2548   if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
2549      swap_bytes((char *)value, ply_type_size[type]);
2550 
2551   if (fwrite (value, ply_type_size[type], 1, fp) != 1)
2552   {
2553       fprintf(stderr, "PLY ERROR: fwrite() failed -- aborting.\n");
2554       exit(1);
2555   }
2556 }
2557 
2558 
2559 /******************************************************************************
2560 Write out an item to a file as ascii characters.
2561 
2562 Entry:
2563   fp         - file to write to
2564   int_val    - integer version of item
2565   uint_val   - unsigned integer version of item
2566   double_val - double-precision float version of item
2567   type       - data type to write out
2568 ******************************************************************************/
2569 
write_ascii_item(FILE * fp,int int_val,unsigned int uint_val,double double_val,int type)2570 inline void write_ascii_item(
2571   FILE *fp,
2572   int int_val,
2573   unsigned int uint_val,
2574   double double_val,
2575   int type
2576 )
2577 {
2578   switch (type) {
2579     case PLY_CHAR:
2580     case PLY_SHORT:
2581     case PLY_INT:
2582       if (fprintf (fp, "%d ", int_val) <= 0)
2583       {
2584 	  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2585 	  exit(1);
2586       }
2587       break;
2588     case PLY_UCHAR:
2589     case PLY_USHORT:
2590     case PLY_UINT:
2591       if (fprintf (fp, "%u ", uint_val) <= 0)
2592       {
2593 	  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2594 	  exit(1);
2595       }
2596       break;
2597     case PLY_FLOAT:
2598     case PLY_DOUBLE:
2599       if (fprintf (fp, "%g ", double_val) <= 0)
2600       {
2601 	  fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2602 	  exit(1);
2603       }
2604       break;
2605     default:
2606       fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
2607       exit (-1);
2608   }
2609 }
2610 
2611 
2612 /******************************************************************************
2613 Write out an item to a file as ascii characters.
2614 
2615 Entry:
2616   fp   - file to write to
2617   item - pointer to item to write
2618   type - data type that "item" points to
2619 
2620 Exit:
2621   returns a double-precision float that contains the value of the written item
2622 ******************************************************************************/
2623 
old_write_ascii_item(FILE * fp,char * item,int type)2624 inline double old_write_ascii_item(FILE *fp, char *item, int type)
2625 {
2626   unsigned char *puchar;
2627   char *pchar;
2628   short int *pshort;
2629   unsigned short int *pushort;
2630   int *pint;
2631   unsigned int *puint;
2632   float *pfloat;
2633   double *pdouble;
2634   int int_value;
2635   unsigned int uint_value;
2636   double double_value;
2637 
2638   switch (type) {
2639     case PLY_CHAR:
2640       pchar = (char *) item;
2641       int_value = *pchar;
2642       fprintf (fp, "%d ", int_value);
2643       return ((double) int_value);
2644     case PLY_UCHAR:
2645       puchar = (unsigned char *) item;
2646       int_value = *puchar;
2647       fprintf (fp, "%d ", int_value);
2648       return ((double) int_value);
2649     case PLY_SHORT:
2650       pshort = (short int *) item;
2651       int_value = *pshort;
2652       fprintf (fp, "%d ", int_value);
2653       return ((double) int_value);
2654     case PLY_USHORT:
2655       pushort = (unsigned short int *) item;
2656       int_value = *pushort;
2657       fprintf (fp, "%d ", int_value);
2658       return ((double) int_value);
2659     case PLY_INT:
2660       pint = (int *) item;
2661       int_value = *pint;
2662       fprintf (fp, "%d ", int_value);
2663       return ((double) int_value);
2664     case PLY_UINT:
2665       puint = (unsigned int *) item;
2666       uint_value = *puint;
2667       fprintf (fp, "%u ", uint_value);
2668       return ((double) uint_value);
2669     case PLY_FLOAT:
2670       pfloat = (float *) item;
2671       double_value = *pfloat;
2672       fprintf (fp, "%g ", double_value);
2673       return (double_value);
2674     case PLY_DOUBLE:
2675       pdouble = (double *) item;
2676       double_value = *pdouble;
2677       fprintf (fp, "%g ", double_value);
2678       return (double_value);
2679     default:
2680       fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
2681       exit (-1);
2682   }
2683 }
2684 
2685 
2686 /******************************************************************************
2687 Get the value of an item that is in memory, and place the result
2688 into an integer, an unsigned integer and a double.
2689 
2690 Entry:
2691   ptr  - pointer to the item
2692   type - data type supposedly in the item
2693 
2694 Exit:
2695   int_val    - integer value
2696   uint_val   - unsigned integer value
2697   double_val - double-precision floating point value
2698 ******************************************************************************/
2699 
get_stored_item(void * ptr,int type,int * int_val,unsigned int * uint_val,double * double_val)2700 inline void get_stored_item(
2701   void *ptr,
2702   int type,
2703   int *int_val,
2704   unsigned int *uint_val,
2705   double *double_val
2706 )
2707 {
2708   switch (type) {
2709     case PLY_CHAR:
2710       *int_val = *((char *) ptr);
2711       *uint_val = *int_val;
2712       *double_val = *int_val;
2713       break;
2714     case PLY_UCHAR:
2715       *uint_val = *((unsigned char *) ptr);
2716       *int_val = *uint_val;
2717       *double_val = *uint_val;
2718       break;
2719     case PLY_SHORT:
2720       *int_val = *((short int *) ptr);
2721       *uint_val = *int_val;
2722       *double_val = *int_val;
2723       break;
2724     case PLY_USHORT:
2725       *uint_val = *((unsigned short int *) ptr);
2726       *int_val = *uint_val;
2727       *double_val = *uint_val;
2728       break;
2729     case PLY_INT:
2730       *int_val = *((int *) ptr);
2731       *uint_val = *int_val;
2732       *double_val = *int_val;
2733       break;
2734     case PLY_UINT:
2735       *uint_val = *((unsigned int *) ptr);
2736       *int_val = *uint_val;
2737       *double_val = *uint_val;
2738       break;
2739     case PLY_FLOAT:
2740       *double_val = *((float *) ptr);
2741       *int_val = (int) *double_val;
2742       *uint_val = (unsigned int) *double_val;
2743       break;
2744     case PLY_DOUBLE:
2745       *double_val = *((double *) ptr);
2746       *int_val = (int) *double_val;
2747       *uint_val = (unsigned int) *double_val;
2748       break;
2749     default:
2750       fprintf (stderr, "get_stored_item: bad type = %d\n", type);
2751       exit (-1);
2752   }
2753 }
2754 
2755 
2756 /******************************************************************************
2757 Get the value of an item from a binary file, and place the result
2758 into an integer, an unsigned integer and a double.
2759 
2760 Entry:
2761   fp   - file to get item from
2762   type - data type supposedly in the word
2763 
2764 Exit:
2765   int_val    - integer value
2766   uint_val   - unsigned integer value
2767   double_val - double-precision floating point value
2768 ******************************************************************************/
2769 
get_binary_item(FILE * fp,int file_type,int type,int * int_val,unsigned int * uint_val,double * double_val,int * native_binary_type)2770 inline void get_binary_item(
2771   FILE *fp,
2772   int file_type,
2773   int type,
2774   int *int_val,
2775   unsigned int *uint_val,
2776   double *double_val,
2777   int *native_binary_type
2778 )
2779 {
2780   char c[8];
2781   void *ptr;
2782 
2783   ptr = (void *) c;
2784 	int ply_type_size[] = {
2785 	  0, 1, 2, 4, 1, 2, 4, 4, 8
2786 	};
2787 
2788   if (fread (ptr, ply_type_size[type], 1, fp) != 1)
2789   {
2790       fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n");
2791       exit(1);
2792   }
2793 
2794 
2795   if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
2796      swap_bytes((char *)ptr, ply_type_size[type]);
2797 
2798   switch (type) {
2799     case PLY_CHAR:
2800       *int_val = *((char *) ptr);
2801       *uint_val = *int_val;
2802       *double_val = *int_val;
2803       break;
2804     case PLY_UCHAR:
2805       *uint_val = *((unsigned char *) ptr);
2806       *int_val = *uint_val;
2807       *double_val = *uint_val;
2808       break;
2809     case PLY_SHORT:
2810       *int_val = *((short int *) ptr);
2811       *uint_val = *int_val;
2812       *double_val = *int_val;
2813       break;
2814     case PLY_USHORT:
2815       *uint_val = *((unsigned short int *) ptr);
2816       *int_val = *uint_val;
2817       *double_val = *uint_val;
2818       break;
2819     case PLY_INT:
2820       *int_val = *((int *) ptr);
2821       *uint_val = *int_val;
2822       *double_val = *int_val;
2823       break;
2824     case PLY_UINT:
2825       *uint_val = *((unsigned int *) ptr);
2826       *int_val = *uint_val;
2827       *double_val = *uint_val;
2828       break;
2829     case PLY_FLOAT:
2830       *double_val = *((float *) ptr);
2831       *int_val = (int) *double_val;
2832       *uint_val = (unsigned int) *double_val;
2833       break;
2834     case PLY_DOUBLE:
2835       *double_val = *((double *) ptr);
2836       *int_val = (int) *double_val;
2837       *uint_val = (unsigned int) *double_val;
2838       break;
2839     default:
2840       fprintf (stderr, "get_binary_item: bad type = %d\n", type);
2841       exit (-1);
2842   }
2843 }
2844 
2845 
2846 /******************************************************************************
2847 Extract the value of an item from an ascii word, and place the result
2848 into an integer, an unsigned integer and a double.
2849 
2850 Entry:
2851   word - word to extract value from
2852   type - data type supposedly in the word
2853 
2854 Exit:
2855   int_val    - integer value
2856   uint_val   - unsigned integer value
2857   double_val - double-precision floating point value
2858 ******************************************************************************/
2859 
get_ascii_item(char * word,int type,int * int_val,unsigned int * uint_val,double * double_val)2860 inline void get_ascii_item(
2861   char *word,
2862   int type,
2863   int *int_val,
2864   unsigned int *uint_val,
2865   double *double_val
2866 )
2867 {
2868   switch (type) {
2869     case PLY_CHAR:
2870     case PLY_UCHAR:
2871     case PLY_SHORT:
2872     case PLY_USHORT:
2873     case PLY_INT:
2874       *int_val = atoi (word);
2875       *uint_val = (unsigned int) *int_val;
2876       *double_val = (double) *int_val;
2877       break;
2878 
2879     case PLY_UINT:
2880       *uint_val = strtol (word, (char **) NULL, 10);
2881       *int_val = (int) *uint_val;
2882       *double_val = (double) *uint_val;
2883       break;
2884 
2885     case PLY_FLOAT:
2886     case PLY_DOUBLE:
2887       *double_val = atof (word);
2888       *int_val = (int) *double_val;
2889       *uint_val = (unsigned int) *double_val;
2890       break;
2891 
2892     default:
2893       fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
2894       exit (-1);
2895   }
2896 }
2897 
2898 
2899 /******************************************************************************
2900 Store a value into a place being pointed to, guided by a data type.
2901 
2902 Entry:
2903   item       - place to store value
2904   type       - data type
2905   int_val    - integer version of value
2906   uint_val   - unsigned integer version of value
2907   double_val - double version of value
2908 
2909 Exit:
2910   item - pointer to stored value
2911 ******************************************************************************/
2912 
store_item(char * item,int type,int int_val,unsigned int uint_val,double double_val)2913 inline void store_item (
2914   char *item,
2915   int type,
2916   int int_val,
2917   unsigned int uint_val,
2918   double double_val
2919 )
2920 {
2921   unsigned char *puchar;
2922   short int *pshort;
2923   unsigned short int *pushort;
2924   int *pint;
2925   unsigned int *puint;
2926   float *pfloat;
2927   double *pdouble;
2928 
2929   switch (type) {
2930     case PLY_CHAR:
2931       *item = int_val;
2932       break;
2933     case PLY_UCHAR:
2934       puchar = (unsigned char *) item;
2935       *puchar = uint_val;
2936       break;
2937     case PLY_SHORT:
2938       pshort = (short *) item;
2939       *pshort = int_val;
2940       break;
2941     case PLY_USHORT:
2942       pushort = (unsigned short *) item;
2943       *pushort = uint_val;
2944       break;
2945     case PLY_INT:
2946       pint = (int *) item;
2947       *pint = int_val;
2948       break;
2949     case PLY_UINT:
2950       puint = (unsigned int *) item;
2951       *puint = uint_val;
2952       break;
2953     case PLY_FLOAT:
2954       pfloat = (float *) item;
2955       *pfloat = double_val;
2956       break;
2957     case PLY_DOUBLE:
2958       pdouble = (double *) item;
2959       *pdouble = double_val;
2960       break;
2961     default:
2962       fprintf (stderr, "store_item: bad type = %d\n", type);
2963       exit (-1);
2964   }
2965 }
2966 
2967 
2968 /******************************************************************************
2969 Add an element to a PLY file descriptor.
2970 
2971 Entry:
2972   plyfile - PLY file descriptor
2973   words   - list of words describing the element
2974   nwords  - number of words in the list
2975 ******************************************************************************/
2976 
add_element(PlyFile * plyfile,char ** words)2977 inline void add_element (PlyFile *plyfile, char **words)
2978 {
2979   PlyElement *elem;
2980 
2981   /* create the new element */
2982   elem = (PlyElement *) myalloc (sizeof (PlyElement));
2983   elem->name = strdup (words[1]);
2984   elem->num = atoi (words[2]);
2985   elem->nprops = 0;
2986 
2987   /* make room for new element in the object's list of elements */
2988   if (plyfile->nelems == 0)
2989     plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
2990   else
2991     plyfile->elems = (PlyElement **) realloc (plyfile->elems,
2992                      sizeof (PlyElement *) * (plyfile->nelems + 1));
2993 
2994   /* add the new element to the object's list */
2995   plyfile->elems[plyfile->nelems] = elem;
2996   plyfile->nelems++;
2997 }
2998 
2999 
3000 /******************************************************************************
3001 Return the type of a property, given the name of the property.
3002 
3003 Entry:
3004   name - name of property type
3005 
3006 Exit:
3007   returns integer code for property, or 0 if not found
3008 ******************************************************************************/
3009 
get_prop_type(char * type_name)3010 inline int get_prop_type(char *type_name)
3011 {
3012   int i;
3013 	const char *type_names[] = {
3014 	"invalid",
3015 	"char", "short", "int",
3016 	"uchar", "ushort", "uint",
3017 	"float", "double",
3018 	};
3019 
3020 	const char *alt_type_names[] = {
3021 	"invalid",
3022 	"int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
3023 	};
3024 
3025 
3026   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
3027     if (equal_strings (type_name, type_names[i]))
3028       return (i);
3029 
3030   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
3031     if (equal_strings (type_name, alt_type_names[i]))
3032       return (i);
3033 
3034   /* if we get here, we didn't find the type */
3035   return (0);
3036 }
3037 
3038 
3039 /******************************************************************************
3040 Add a property to a PLY file descriptor.
3041 
3042 Entry:
3043   plyfile - PLY file descriptor
3044   words   - list of words describing the property
3045   nwords  - number of words in the list
3046 ******************************************************************************/
3047 
add_property(PlyFile * plyfile,char ** words)3048 inline void add_property (PlyFile *plyfile, char **words)
3049 {
3050   PlyProperty *prop;
3051   PlyElement *elem;
3052 
3053   /* create the new property */
3054 
3055   prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
3056 
3057   if (equal_strings (words[1], "list")) {       /* is a list */
3058     prop->count_external = get_prop_type (words[2]);
3059     prop->external_type = get_prop_type (words[3]);
3060     prop->name = strdup (words[4]);
3061     prop->is_list = 1;
3062   }
3063   else {                                        /* not a list */
3064     prop->external_type = get_prop_type (words[1]);
3065     prop->name = strdup (words[2]);
3066     prop->is_list = 0;
3067   }
3068 
3069   /* add this property to the list of properties of the current element */
3070 
3071   elem = plyfile->elems[plyfile->nelems - 1];
3072 
3073   if (elem->nprops == 0)
3074     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
3075   else
3076     elem->props = (PlyProperty **) realloc (elem->props,
3077                   sizeof (PlyProperty *) * (elem->nprops + 1));
3078 
3079   elem->props[elem->nprops] = prop;
3080   elem->nprops++;
3081 }
3082 
3083 
3084 /******************************************************************************
3085 Add a comment to a PLY file descriptor.
3086 
3087 Entry:
3088   plyfile - PLY file descriptor
3089   line    - line containing comment
3090 ******************************************************************************/
3091 
add_comment(PlyFile * plyfile,char * line)3092 inline void add_comment (PlyFile *plyfile, char *line)
3093 {
3094   int i;
3095 
3096   /* skip over "comment" and leading spaces and tabs */
3097   i = 7;
3098   while (line[i] == ' ' || line[i] == '\t')
3099     i++;
3100 
3101   ply_put_comment (plyfile, &line[i]);
3102 }
3103 
3104 
3105 /******************************************************************************
3106 Add a some object information to a PLY file descriptor.
3107 
3108 Entry:
3109   plyfile - PLY file descriptor
3110   line    - line containing text info
3111 ******************************************************************************/
3112 
add_obj_info(PlyFile * plyfile,char * line)3113 inline void add_obj_info (PlyFile *plyfile, char *line)
3114 {
3115   int i;
3116 
3117   /* skip over "obj_info" and leading spaces and tabs */
3118   i = 8;
3119   while (line[i] == ' ' || line[i] == '\t')
3120     i++;
3121 
3122   ply_put_obj_info (plyfile, &line[i]);
3123 }
3124 
3125 
3126 /******************************************************************************
3127 Copy a property.
3128 ******************************************************************************/
3129 
copy_property(PlyProperty * dest,PlyProperty * src)3130 inline void copy_property(PlyProperty *dest, PlyProperty *src)
3131 {
3132   dest->name = strdup (src->name);
3133   dest->external_type = src->external_type;
3134   dest->internal_type = src->internal_type;
3135   dest->offset = src->offset;
3136 
3137   dest->is_list = src->is_list;
3138   dest->count_external = src->count_external;
3139   dest->count_internal = src->count_internal;
3140   dest->count_offset = src->count_offset;
3141 }
3142 
3143 
3144 /******************************************************************************
3145 Allocate some memory.
3146 
3147 Entry:
3148   size  - amount of memory requested (in bytes)
3149   lnum  - line number from which memory was requested
3150   fname - file name from which memory was requested
3151 ******************************************************************************/
3152 
my_alloc(int size,int lnum,const char * fe)3153 inline char *my_alloc(int size, int lnum, const char *fe)
3154 {
3155   char *ptr;
3156 
3157   ptr = (char *) malloc (size);
3158 
3159   if (ptr == 0) {
3160     fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fe);
3161   }
3162 
3163   return (ptr);
3164 }
3165 
3166 }
3167 }
3168 #endif
3169