root/OpenSceneGraph/trunk/src/osgPlugins/ply/plyfile.cpp @ 10040

Revision 10040, 74.0 kB (checked in by robert, 4 years ago)

From Santosh Gaikwad, "I have added the exception handling in ply loader. All exceptions I am catching in VertexData::readPlyFile() and made sure that application will not crash or exit if any exception occurred. I am returning NULL from VertexData::readPlyFile() if any exception occurred.
"

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