source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vrippack-0.31/src/libply/plyfile.c @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

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