1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #include "moab/Core.hpp"
17 
18 #include "moab/ReaderWriterSet.hpp"
19 #include "moab/ReaderIface.hpp"
20 #include "moab/WriterIface.hpp"
21 
22 #include "ReadVtk.hpp"
23 #include "ReadSTL.hpp"
24 #include "ReadGmsh.hpp"
25 #include "ReadIDEAS.hpp"
26 #include "ReadMCNP5.hpp"
27 #include "ReadOBJ.hpp"
28 #include "ReadNASTRAN.hpp"
29 #include "ReadRTT.hpp"
30 #include "ReadABAQUS.hpp"
31 #include "ReadSms.hpp"
32 #include "Tqdcfr.hpp"
33 #include "ReadTetGen.hpp"
34 #include "ReadSmf.hpp"
35 #include "ReadTemplate.hpp"
36 #ifdef MOAB_HAVE_CGM
37 #  include "ReadCGM.hpp"
38 #endif
39 
40 #include "WriteAns.hpp"
41 #include "WriteVtk.hpp"
42 #include "WriteGMV.hpp"
43 #include "WriteSTL.hpp"
44 #include "WriteGmsh.hpp"
45 #include "WriteSmf.hpp"
46 #include "WriteTemplate.hpp"
47 
48 #ifdef MOAB_HAVE_NETCDF
49 #  include "ReadNCDF.hpp"
50 #  include "WriteNCDF.hpp"
51 #  include "WriteNC.hpp"
52 #  include "WriteSLAC.hpp"
53 #  include "ReadNC.hpp"
54 #endif
55 
56 // 2nd include of ReadNC in case we have pnetcdf and not netcdf
57 #if defined(MOAB_HAVE_PNETCDF) && !defined(MOAB_HAVE_NETCDF)
58 #  include "ReadNC.hpp"
59 #endif
60 
61 #ifdef MOAB_HAVE_CGNS
62 #  include "ReadCGNS.hpp"
63 #  include "WriteCGNS.hpp"
64 #endif
65 
66 #ifdef MOAB_HAVE_CCMIO
67 #  include "ReadCCMIO.hpp"
68 #  include "WriteCCMIO.hpp"
69 #endif
70 
71 #ifdef MOAB_HAVE_DAMSEL
72 #  include "WriteDamsel.hpp"
73 #  include "ReadDamsel.hpp"
74 #endif
75 
76 #ifdef MOAB_HAVE_HDF5
77 #  include "ReadHDF5.hpp"
78 #  ifdef MOAB_HAVE_HDF5_PARALLEL
79 #    include "WriteHDF5Parallel.hpp"
80 #  else
81 #    include "WriteHDF5.hpp"
82 #  endif
83 #endif
84 
85 #include <algorithm>
86 
87 namespace moab {
88 
ReaderWriterSet(Core * mdb)89 ReaderWriterSet::ReaderWriterSet(Core* mdb)
90   : mbCore( mdb )
91 {
92 #ifdef MOAB_HAVE_HDF5
93   const char* hdf5_sufxs[] = { "h5m", "mhdf", NULL };
94 #ifdef MOAB_HAVE_HDF5_PARALLEL
95   register_factory(  ReadHDF5::factory, WriteHDF5Parallel::factory,
96                      "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
97 #else
98   register_factory(  ReadHDF5::factory, WriteHDF5::factory,
99                      "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
100 #endif
101 #endif
102 
103 #ifdef MOAB_HAVE_NETCDF
104   const char* exo_sufxs[] = { "exo", "exoII", "exo2", "g", "gen", NULL };
105   register_factory( ReadNCDF::factory, WriteNCDF::factory, "Exodus II", exo_sufxs, "EXODUS" );
106   register_factory( ReadNC::factory, WriteNC::factory, "Climate NC", "nc", "NC" );
107 #endif
108 
109 #ifdef MOAB_HAVE_CGNS
110   const char* cgns_sufxs[] = { "cgns", NULL };
111   register_factory( ReadCGNS::factory, WriteCGNS::factory, "CGNS", cgns_sufxs, "CGNS" );
112 #endif
113 
114   register_factory( ReadIDEAS::factory, NULL, "IDEAS format", "unv", "UNV" );
115 
116   register_factory( ReadMCNP5::factory, NULL, "MCNP5 format", "meshtal", "MESHTAL" );
117 
118   const char* nastran_sufxs[] = { "nas", "bdf", NULL };
119   register_factory( ReadNASTRAN::factory, NULL, "NASTRAN format", nastran_sufxs, "NAS" );
120 
121   register_factory( ReadABAQUS::factory, NULL, "ABAQUS INP mesh format", "abq", "Abaqus mesh" );
122 
123   register_factory( ReadRTT::factory, NULL, "RTT Mesh Format", "rtt", "Atilla RTT Mesh" );
124 
125   register_factory( ReadVtk::factory, WriteVtk::factory, "Kitware VTK", "vtk", "VTK" );
126 
127   register_factory( ReadOBJ::factory, NULL, "OBJ mesh format", "obj", "OBJ mesh" );
128 
129   register_factory( ReadSms::factory, NULL, "RPI SMS", "sms", "SMS" );
130 
131   register_factory( Tqdcfr::factory, NULL, "Cubit", "cub", "CUBIT" );
132 
133   register_factory( ReadSmf::factory, WriteSmf::factory , "QSlim format", "smf", "SMF");
134 #ifdef MOAB_HAVE_CGM_FACET
135   const char* facet_sufxs[] = { "facet", NULL };
136   register_factory( ReadCGM::factory, NULL, "Facet Engine Solid Model", facet_sufxs, "facet");
137 #endif
138 #ifdef MOAB_HAVE_CGM_OCC
139   const char* occ_sufxs[] = { "brep", "occ", NULL };
140   const char* step_sufxs[] = { "step", "stp", NULL };
141   const char* iges_sufxs[] = { "iges", "igs", NULL };
142   register_factory( ReadCGM::factory, NULL, "OpenCascade solid model", occ_sufxs, "OCC");
143   register_factory( ReadCGM::factory, NULL, "STEP B-Rep exchange", step_sufxs, "STEP");
144   register_factory( ReadCGM::factory, NULL, "IGES B-Rep exchange", iges_sufxs, "IGES");
145 #endif
146 
147 #ifdef MOAB_HAVE_NETCDF
148   register_factory( NULL, WriteSLAC::factory, "SLAC", "slac", "SLAC" );
149 #endif
150 
151 #ifdef MOAB_HAVE_CCMIO
152   const char* ccmio_sufxs[] = { "ccm", "ccmg", NULL };
153   register_factory( ReadCCMIO::factory, WriteCCMIO::factory, "CCMIO files", ccmio_sufxs, "CCMIO");
154 #endif
155 
156 #ifdef MOAB_HAVE_DAMSEL
157   const char* damsel_sufxs[] = { "h5", NULL };
158   register_factory( ReadDamsel::factory, WriteDamsel::factory, "Damsel files", damsel_sufxs, "DAMSEL");
159 #endif
160 
161   register_factory( NULL, WriteGMV::factory, "GMV", "gmv", "GMV" );
162 
163   register_factory( NULL, WriteAns::factory, "Ansys", "ans", "ANSYS" );
164 
165   const char* gmsh_sufxs[] = { "msh", "gmsh", NULL };
166   register_factory( ReadGmsh::factory, WriteGmsh::factory, "Gmsh mesh file", gmsh_sufxs, "GMSH" );
167 
168   register_factory( ReadSTL::factory, WriteSTL::factory, "Stereo Lithography File (STL)", "stl", "STL" );
169 
170   const char* tetgen_sufxs[] = { "node", "ele", "face", "edge", NULL };
171   register_factory( ReadTetGen::factory, 0, "TetGen output files", tetgen_sufxs, "TETGEN" );
172 
173   const char* template_sufxs[] = { NULL };
174   register_factory( ReadTemplate::factory, WriteTemplate::factory, "Template input files", template_sufxs, "TEMPLATE" );
175 
176 }
177 
178 
~ReaderWriterSet()179 ReaderWriterSet::~ReaderWriterSet()
180 {
181 }
182 
register_factory(reader_factory_t reader,writer_factory_t writer,const char * description,const char * const * extensions,const char * name)183 ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
184                                                  writer_factory_t writer,
185                                                  const char* description,
186                                                  const char* const* extensions,
187                                                  const char* name )
188 {
189   if (!reader && !writer)
190     return MB_FAILURE;
191 
192     // check for duplicate names
193   iterator h = handler_by_name( name );
194   if (h != end()) {
195     MB_SET_ERR(MB_FAILURE, "Conflicting string name for file formats: \"" << name << "\"");
196   }
197 
198     // count extensions and check for duplicates
199   const char* const* iter;
200   for (iter = extensions; *iter; ++iter)
201   {
202     h = handler_from_extension( *iter );
203     if (h != end())
204     {
205       if (NULL != reader && h->have_reader())
206         MB_SET_ERR(MB_FAILURE, "Conflicting readers for file extension \"" << *iter << "\": \"" << h->description() << "\" and \"" << description << "\".");
207       else if (NULL != writer && h->have_writer())
208         MB_SET_ERR(MB_FAILURE, "Conflicting writers for file extension \"" << *iter << "\": \"" << h->description() << "\" and \"" << description << "\".");
209     }
210   }
211   handlerList.push_back( Handler(reader, writer, name, description, extensions, iter - extensions) );
212   return MB_SUCCESS;
213 }
214 
register_factory(reader_factory_t reader,writer_factory_t writer,const char * description,const char * extension,const char * name)215 ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
216                                                  writer_factory_t writer,
217                                                  const char* description,
218                                                  const char* extension,
219                                                  const char* name )
220 {
221   const char* extensions[2] = {extension, NULL};
222   return register_factory( reader, writer, description, extensions, name );
223 }
224 
225 
get_file_extension_reader(const std::string & filename) const226 ReaderIface* ReaderWriterSet::get_file_extension_reader(
227                                   const std::string& filename ) const
228 {
229   std::string ext = extension_from_filename( filename );
230   iterator handler = handler_from_extension( ext, true, false );
231   return handler == end() ? NULL : handler->make_reader(mbCore);
232 }
233 
get_file_extension_writer(const std::string & filename) const234 WriterIface* ReaderWriterSet::get_file_extension_writer(
235                                   const std::string& filename ) const
236 {
237   std::string ext = extension_from_filename( filename );
238   iterator handler = handler_from_extension( ext, false, true );
239   return handler == end() ? NULL : handler->make_writer(mbCore);
240 }
241 
extension_from_filename(const std::string & filename)242 std::string ReaderWriterSet::extension_from_filename(
243                                  const std::string& filename )
244 {
245   std::string::size_type idx = filename.find_last_of( "." );
246   std::string::size_type idirx = filename.find_last_of( "\\/" );
247 
248   if (idx == std::string::npos)
249     return std::string("");
250   if ((idirx != std::string::npos) && (idirx > idx))
251     return std::string("");
252   return filename.substr( idx + 1 );
253 }
254 
Handler(reader_factory_t read_f,writer_factory_t write_f,const char * nm,const char * desc,const char * const * ext,int num_ext)255 ReaderWriterSet::Handler::Handler( reader_factory_t read_f,
256                                      writer_factory_t write_f,
257                                      const char* nm,
258                                      const char* desc,
259                                      const char* const* ext,
260                                      int num_ext )
261  : mReader(read_f), mWriter(write_f), mName(nm), mDescription(desc), mExtensions(num_ext)
262 {
263   for (int i = 0; i < num_ext; ++i)
264     mExtensions[i] = ext[i];
265 }
266 
267 #ifdef WIN32
268 #define strcasecmp(A,B) _stricmp( A, B )
269 #endif
270 
271 ReaderWriterSet::iterator
handler_from_extension(const std::string & ext,bool with_reader,bool with_writer) const272 ReaderWriterSet::handler_from_extension( const std::string& ext,
273                                            bool with_reader,
274                                            bool with_writer ) const
275 {
276   iterator iter;
277   std::vector<std::string>::const_iterator siter;
278 
279     // try case-sensitive compare
280   for (iter = begin(); iter != end(); ++iter)
281   {
282     if ((with_reader && !iter->have_reader()) ||
283         (with_writer && !iter->have_writer()))
284       continue;
285 
286     for (siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter)
287       if (*siter == ext)
288         return iter;
289   }
290 
291     // try case-insensitive compare
292   for (iter = begin(); iter != end(); ++iter)
293   {
294     if ((with_reader && !iter->have_reader()) ||
295         (with_writer && !iter->have_writer()))
296       continue;
297 
298     for (siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter)
299       if (0 == strcasecmp( siter->c_str(), ext.c_str() ))
300         return iter;
301   }
302 
303   return end();
304 }
305 
reads_extension(const char * ext) const306 bool ReaderWriterSet::Handler::reads_extension(const char *ext) const
307 {
308   if (!have_reader()) return false;
309 
310   std::vector<std::string>::const_iterator siter;
311   for (siter = mExtensions.begin(); siter != mExtensions.end(); ++siter)
312     if (!(*siter).compare(ext)) return true;
313     else if (0 == strcasecmp( siter->c_str(), ext)) return true;
314 
315   return false;
316 }
317 
writes_extension(const char * ext) const318 bool ReaderWriterSet::Handler::writes_extension(const char *ext) const
319 {
320   if (!have_writer()) return false;
321 
322   std::vector<std::string>::const_iterator siter;
323   for (siter = mExtensions.begin(); siter != mExtensions.end(); ++siter)
324     if (!(*siter).compare(ext)) return true;
325     else if (0 == strcasecmp( siter->c_str(), ext)) return true;
326 
327   return false;
328 }
329 
330 ReaderWriterSet::iterator
handler_by_name(const char * nm) const331 ReaderWriterSet::handler_by_name( const char* nm ) const
332 {
333   return std::find( begin(), end(), nm );
334 }
335 
operator ==(const char * nm) const336 bool ReaderWriterSet::Handler::operator==( const char* nm ) const
337 {
338     // do case-insensitive comparison
339   std::string::const_iterator siter = mName.begin();
340   for (; *nm; ++nm, ++siter)
341     if (siter == mName.end() || tolower(*nm) != tolower(*siter))
342       return false;
343   return *nm == '\0';
344 }
345 
346 } // namespace moab
347 
348 
349 
350