Geogram  Version 1.9.0
A programming library of geometric algorithms
geofile.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2000-2022 Inria
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * * Neither the name of the ALICE Project-Team nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * Contact: Bruno Levy
30  *
31  * https://www.inria.fr/fr/bruno-levy
32  *
33  * Inria,
34  * Domaine de Voluceau,
35  * 78150 Le Chesnay - Rocquencourt
36  * FRANCE
37  *
38  */
39 
40 #ifndef GEOGRAM_BASIC_GEOFILE
41 #define GEOGRAM_BASIC_GEOFILE
42 
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/numeric.h>
45 #include <geogram/basic/memory.h>
46 #include <geogram/basic/string.h>
47 #include <geogram/third_party/zlib/zlib.h>
48 
49 #include <stdexcept>
50 #include <fstream>
51 #include <map>
52 
53 
59 namespace GEO {
60 
66  class GEOGRAM_API GeoFileException : public std::logic_error {
67  public:
73  GeoFileException(const std::string& s) : logic_error(s) {
74  }
75 
81  GeoFileException(const GeoFileException& rhs) : logic_error(rhs) {
82  }
83 
87  ~GeoFileException() GEO_NOEXCEPT override;
88  };
89 
90  /**************************************************************/
91 
102  template <class T> inline bool read_ascii_attribute(
103  FILE* file, Memory::pointer base_addr, index_t nb_elements
104  ) {
105  T* attrib = reinterpret_cast<T*>(base_addr);
106  for(index_t i=0; i<nb_elements; ++i) {
107  std::string buff;
108  int res;
109  while(char(res = fgetc(file)) != '\n') {
110  if(res == EOF) {
111  return false;
112  }
113  buff.push_back(char(res));
114  }
115  if(!String::from_string(buff.c_str(),attrib[i])) {
116  return false;
117  }
118  }
119  return true;
120  }
121 
131  template <class T> inline bool write_ascii_attribute(
132  FILE* file, Memory::pointer base_addr, index_t nb_elements
133  ) {
134  T* attrib = reinterpret_cast<T*>(base_addr);
135  for(index_t i=0; i<nb_elements; ++i) {
136  if(
137  fprintf(
138  file, "%s\n", String::to_string(attrib[i]).c_str()
139  ) == 0
140  ) {
141  return false;
142  }
143  }
144  return true;
145  }
146 
158  template <> inline bool read_ascii_attribute<char>(
159  FILE* file, Memory::pointer base_addr, index_t nb_elements
160  ) {
161  char* attrib = reinterpret_cast<char*>(base_addr);
162  for(index_t i=0; i<nb_elements; ++i) {
163  int val;
164  if(fscanf(file, "%d", &val) == 0) {
165  return false;
166  }
167  attrib[i] = char(val);
168  }
169  return true;
170  }
171 
182  template <> inline bool write_ascii_attribute<char>(
183  FILE* file, Memory::pointer base_addr, index_t nb_elements
184  ) {
185  char* attrib = reinterpret_cast<char*>(base_addr);
186  for(index_t i=0; i<nb_elements; ++i) {
187  if(fprintf(file, "%d\n", int(attrib[i])) == 0) {
188  return false;
189  }
190  }
191  return true;
192  }
193 
204  template <> inline bool read_ascii_attribute<bool>(
205  FILE* file, Memory::pointer base_addr, index_t nb_elements
206  ) {
207  char* attrib = reinterpret_cast<char*>(base_addr);
208  for(index_t i=0; i<nb_elements; ++i) {
209  int val;
210  if(fscanf(file, "%d", &val) == 0) {
211  return false;
212  }
213  attrib[i] = char(val);
214  }
215  return true;
216  }
217 
228  template <> inline bool write_ascii_attribute<bool>(
229  FILE* file, Memory::pointer base_addr, index_t nb_elements
230  ) {
231  char* attrib = reinterpret_cast<char*>(base_addr);
232  for(index_t i=0; i<nb_elements; ++i) {
233  if(fprintf(file, "%d\n", int(attrib[i])) == 0) {
234  return false;
235  }
236  }
237  return true;
238  }
239 
240  /**************************************************************/
241 
269  class GEOGRAM_API GeoFile {
270  public:
271 
276  typedef bool (*AsciiAttributeSerializer)(
277  FILE* file, Memory::pointer base_address, index_t nb_elements
278  );
279 
288  const std::string& type_name,
289  AsciiAttributeSerializer read,
290  AsciiAttributeSerializer write
291  );
292 
297  GeoFile(const std::string& filename);
298 
303 
311  bool is_ascii() const {
312  return ascii_;
313  }
314 
319  const std::string& current_chunk_class() const {
320  return current_chunk_class_;
321  }
322 
327  long current_chunk_size() const {
328  return current_chunk_size_;
329  }
330 
334  struct AttributeInfo {
335 
339  AttributeInfo() : element_size(0), dimension(0) {
340  }
341 
350  const std::string& name_in,
351  const std::string& element_type_in,
352  size_t element_size_in,
353  index_t dimension_in
354  ) :
355  name(name_in),
356  element_type(element_type_in),
357  element_size(element_size_in),
358  dimension(dimension_in) {
359  }
360 
361 
365  std::string name;
366 
371  std::string element_type;
372 
376  size_t element_size;
377 
382  };
383 
388 
392  AttributeSetInfo() : nb_items(0), skip(false) {
393  }
394 
402  const std::string& name_in,
403  index_t nb_items_in
404  ) :
405  name(name_in),
406  nb_items(nb_items_in),
407  skip(false) {
408  }
409 
418  const std::string& name_in
419  ) const {
420  for(index_t i=0; i<attributes.size(); ++i) {
421  if(attributes[i].name == name_in) {
422  return &(attributes[i]);
423  }
424  }
425  return nullptr;
426  }
427 
435  AttributeInfo* find_attribute(const std::string& name_in) {
436  for(index_t i=0; i<attributes.size(); ++i) {
437  if(attributes[i].name == name_in) {
438  return &(attributes[i]);
439  }
440  }
441  return nullptr;
442  }
443 
447  std::string name;
448 
453 
458 
463  bool skip;
464  };
465 
472  AttributeSetInfo* find_attribute_set(const std::string& name) {
473  auto it = attribute_sets_.find(name);
474  if(it == attribute_sets_.end()) {
475  return nullptr;
476  }
477  return &(it->second);
478  }
479 
487  const std::string& name
488  ) const {
489  auto it = attribute_sets_.find(name);
490  if(it == attribute_sets_.end()) {
491  return nullptr;
492  }
493  return &(it->second);
494  }
495 
505 
516  void write_int(index_t x, const char* comment = nullptr);
517 
524  std::string read_string();
525 
534  void write_string(const std::string& s, const char* comment = nullptr);
535 
542  size_t read_size();
543 
550  void write_size(size_t x);
551 
559  std::string read_chunk_class();
560 
569  void write_chunk_class(const std::string& chunk_class);
570 
576  void write_string_array(const std::vector<std::string>& strings);
577 
583  void read_string_array(std::vector<std::string>& strings);
584 
585 
594  size_t string_size(const std::string& s) const {
595  return sizeof(index_t) + s.length();
596  }
597 
605  const std::vector<std::string>& strings
606  ) const ;
607 
612 
622  const std::string& chunk_class, size_t size
623  );
624 
630 
637 
644 
645  protected:
646  std::string filename_;
647  gzFile file_;
648  bool ascii_;
649  FILE* ascii_file_;
650  std::string current_chunk_class_;
651  long current_chunk_size_;
652  long current_chunk_file_pos_;
653  std::map<std::string, AttributeSetInfo> attribute_sets_;
654 
655  static std::map<std::string, AsciiAttributeSerializer>
656  ascii_attribute_read_;
657 
658  static std::map<std::string, AsciiAttributeSerializer>
659  ascii_attribute_write_;
660  };
661 
662  /**************************************************************/
663 
667  class GEOGRAM_API InputGeoFile : public GeoFile {
668  public:
673  InputGeoFile(const std::string& filename);
674 
679  const std::string& next_chunk();
680 
686  void read_attribute(void* addr);
687 
688 
696 
697 
706  geo_assert(current_attribute_set_ != nullptr);
707  return *current_attribute_set_;
708  }
709 
717  geo_assert(current_attribute_ != nullptr);
718  return *current_attribute_;
719  }
720 
721  /*
722  * \brief Gets the current user comment.
723  * \return a const reference to the current user comment
724  * \pre current chunk class is "CMNT" (COMMENT)
725  */
726  const std::string& current_comment() const {
727  geo_assert(current_chunk_class_ == "CMNT");
728  return current_comment_;
729  }
730 
731 
740  void read_command_line(std::vector<std::string>& args);
741 
742  protected:
748  void skip_chunk();
749 
750  AttributeSetInfo* current_attribute_set_;
751  AttributeInfo* current_attribute_;
752  std::string current_comment_;
753 
754  private:
758  InputGeoFile(const InputGeoFile& rhs);
759 
763  InputGeoFile& operator=(const InputGeoFile& rhs);
764  };
765 
766  /**************************************************************/
767 
771  class GEOGRAM_API OutputGeoFile : public GeoFile {
772  public:
779  OutputGeoFile(const std::string& filename, index_t compression_level=3);
780 
788  const std::string& name, index_t nb_items
789  );
790 
805  const std::string& attribute_set_name,
806  const std::string& attribute_name,
807  const std::string& element_type,
808  size_t element_size,
809  index_t dimension,
810  const void* data
811  );
812 
813 
818  void write_comment(const std::string& comment);
819 
827  void write_command_line(const std::vector<std::string>& args);
828 
829 
836 
837  private:
841  OutputGeoFile(const InputGeoFile& rhs);
842 
846  OutputGeoFile& operator=(const InputGeoFile& rhs);
847  };
848 
849  /**************************************************************/
850 }
851 
852 #endif
#define geo_assert(x)
Verifies that a condition is met.
Definition: assert.h:149
GeoFile exception.
Definition: geofile.h:66
GeoFileException(const std::string &s)
GeoFileException constructor.
Definition: geofile.h:73
GeoFileException(const GeoFileException &rhs)
GeoFileException copy constructor.
Definition: geofile.h:81
~GeoFileException() GEO_NOEXCEPT override
GeoFileException destructor.
Base class for reading or writing Geogram structured binary files.
Definition: geofile.h:269
std::string read_chunk_class()
Reads a chunk class from the file.
void check_chunk_size()
Checks that the actual chunk size corresponds to the specified chunk size.
const std::string & current_chunk_class() const
Gets the current chunk class.
Definition: geofile.h:319
void write_chunk_class(const std::string &chunk_class)
Writes a chunk class into the file.
long current_chunk_size() const
Gets the size of the current chunk.
Definition: geofile.h:327
bool is_ascii() const
Tests whether this GeoFile is ascii.
Definition: geofile.h:311
size_t string_array_size(const std::vector< std::string > &strings) const
Gets the size in bytes used by a given string array in the file.
GeoFile(const std::string &filename)
GeoFile constructor.
void clear_attribute_maps()
Clears all memorized information about attributes and attribute sets.
std::string read_string()
Reads a string from the file.
size_t string_size(const std::string &s) const
Gets the size in bytes used by a given string in the file.
Definition: geofile.h:594
const AttributeSetInfo * find_attribute_set(const std::string &name) const
Finds an attribute set by name.
Definition: geofile.h:486
void read_string_array(std::vector< std::string > &strings)
Reads a string array from the file.
AttributeSetInfo * find_attribute_set(const std::string &name)
Finds an attribute set by name.
Definition: geofile.h:472
void write_int(index_t x, const char *comment=nullptr)
Writes an integer into the file.
void write_string(const std::string &s, const char *comment=nullptr)
Writes a string into the file.
void check_zlib_version()
Compares the zlib version declared in the header file with the zlib version obtained from the runtime...
index_t read_int()
Reads an integer from the file.
void write_size(size_t x)
Writes an unsigned 64 bits integer into the file.
void write_string_array(const std::vector< std::string > &strings)
Writes a string array into the file.
~GeoFile()
GeoFile destructor.
void write_chunk_header(const std::string &chunk_class, size_t size)
Writes a chunk header into the file.
size_t read_size()
Reads an unsigned 64 bits integer from the file.
void read_chunk_header()
Reads a chunk header from the file.
static void register_ascii_attribute_serializer(const std::string &type_name, AsciiAttributeSerializer read, AsciiAttributeSerializer write)
Declares a new attribute type that can be read from and written to ascii files.
Used to read a structured binary file.
Definition: geofile.h:667
void skip_attribute_set()
Indicates that all the attributes attached to the latest attribute set should be skipped.
void skip_chunk()
Skips the latest chunk.
InputGeoFile(const std::string &filename)
InputGeoFile constructor.
const std::string & next_chunk()
Advances to the next chunk.
const AttributeInfo & current_attribute() const
Gets the current attribute.
Definition: geofile.h:716
void read_attribute(void *addr)
Reads the latest attribute.
const AttributeSetInfo & current_attribute_set() const
Gets the current attribute set.
Definition: geofile.h:705
void read_command_line(std::vector< std::string > &args)
Reads the command line from the file.
Used to write a structured binary file.
Definition: geofile.h:771
void write_attribute_set(const std::string &name, index_t nb_items)
Writes a new attribute set to the file.
void write_separator()
Writes a separator into the file.
OutputGeoFile(const std::string &filename, index_t compression_level=3)
OutputGeoFile constructor.
void write_comment(const std::string &comment)
Writes a new comment to the file.
void write_attribute(const std::string &attribute_set_name, const std::string &attribute_name, const std::string &element_type, size_t element_size, index_t dimension, const void *data)
Writes a new attribute to the file.
void write_command_line(const std::vector< std::string > &args)
Writes the command line to the file.
Vector with aligned memory allocation.
Definition: memory.h:635
Common include file, providing basic definitions. Should be included before anything else by all head...
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
Definition: memory.h:104
Global Vorpaline namespace.
Definition: basic.h:55
bool read_ascii_attribute(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
Definition: geofile.h:102
bool write_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition: geofile.h:228
geo_index_t index_t
The type for storing and manipulating indices.
Definition: numeric.h:329
bool write_ascii_attribute(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition: geofile.h:131
bool read_ascii_attribute< char >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
Definition: geofile.h:158
bool read_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
Definition: geofile.h:204
bool write_ascii_attribute< char >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition: geofile.h:182
Types and functions for numbers manipulation.
Functions for string manipulation.
Internal representation of attributes.
Definition: geofile.h:334
std::string name
Name of the attribute.
Definition: geofile.h:365
AttributeInfo()
AttributeInfo constructor.
Definition: geofile.h:339
index_t dimension
The number of elements per item.
Definition: geofile.h:381
size_t element_size
The size in bytes of each element.
Definition: geofile.h:376
std::string element_type
A string with the name fo the C++ type of the elements.
Definition: geofile.h:371
AttributeInfo(const std::string &name_in, const std::string &element_type_in, size_t element_size_in, index_t dimension_in)
AttributeInfo constructor.
Definition: geofile.h:349
Internal representation of an attribute set.
Definition: geofile.h:387
AttributeInfo * find_attribute(const std::string &name_in)
Finds an AttributeInfo by name.
Definition: geofile.h:435
AttributeSetInfo(const std::string &name_in, index_t nb_items_in)
AttributeSetInfo constructor.
Definition: geofile.h:401
const AttributeInfo * find_attribute(const std::string &name_in) const
Finds an AttributeInfo by name.
Definition: geofile.h:417
bool skip
if set, all attributes in the set are skipped when reading the file.
Definition: geofile.h:463
index_t nb_items
number of items in each attribute of the set.
Definition: geofile.h:452
vector< AttributeInfo > attributes
the attributes of the set.
Definition: geofile.h:457
AttributeSetInfo()
AttributeSetInfo constructor.
Definition: geofile.h:392
std::string name
name of the attribute set.
Definition: geofile.h:447