MDAL
mdal_utils.hpp
1 /*
2  MDAL - Mesh Data Abstraction Library (MIT License)
3  Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
4 */
5 
6 #ifndef MDAL_UTILS_HPP
7 #define MDAL_UTILS_HPP
8 
9 #include <string>
10 #include <vector>
11 #include <stddef.h>
12 #include <limits>
13 #include <sstream>
14 #include <fstream>
15 #include <cmath>
16 #include <functional>
17 
18 #if defined (WIN32)
19 #include <windows.h>
20 #undef min
21 #undef max
22 #else
23 #include <dlfcn.h>
24 #include <dirent.h>
25 #endif
26 
27 #include <algorithm>
28 
29 #include "mdal_data_model.hpp"
30 #include "mdal_memory_data_model.hpp"
31 #include "mdal_datetime.hpp"
32 
33 // avoid unused variable warnings
34 #define MDAL_UNUSED(x) (void)x;
35 #define MDAL_NAN std::numeric_limits<double>::quiet_NaN()
36 
37 #ifndef M_PI
38 #define M_PI 3.14159265358979323846264338327
39 #endif
40 
41 namespace MDAL
42 {
43 
44  std::string getEnvVar( const std::string &varname, const std::string &defaultVal = std::string() );
45 
46  // endianness
47  bool isNativeLittleEndian();
48 
49  // numbers
50  inline bool equals( double val1, double val2, double eps = std::numeric_limits<double>::epsilon() )
51  {
52  return fabs( val1 - val2 ) < eps;
53  }
54 
56  double safeValue( double val, double nodata, double eps = std::numeric_limits<double>::epsilon() );
57 
59  bool openInputFile( std::ifstream &inputFileStream, const std::string &fileName, std::ifstream::openmode mode = std::ifstream::binary );
61  std::ifstream openInputFile( const std::string &fileName, std::ios_base::openmode mode = std::ifstream::in );
62 
64  std::ofstream openOutputFile( const std::string &fileName, std::ios_base::openmode mode = std::ios_base::in );
65 
67  bool fileExists( const std::string &filename );
68  std::string baseName( const std::string &filename, bool keepExtension = false );
69  std::string fileExtension( const std::string &path );
70  std::string dirName( const std::string &filename );
71  std::string pathJoin( const std::string &path1, const std::string &path2 );
72  std::string readFileToString( const std::string &filename );
73 
74  // strings
75  enum ContainsBehaviour
76  {
77  CaseSensitive,
78  CaseInsensitive
79  };
80 
81  bool startsWith( const std::string &str, const std::string &substr, ContainsBehaviour behaviour = CaseSensitive );
82  bool endsWith( const std::string &str, const std::string &substr, ContainsBehaviour behaviour = CaseSensitive );
83  bool contains( const std::string &str, const std::string &substr, ContainsBehaviour behaviour = CaseSensitive );
84  bool contains( const std::vector<std::string> &list, const std::string &str );
85  std::string replace( const std::string &str, const std::string &substr, const std::string &replacestr, ContainsBehaviour behaviour = CaseSensitive );
86  std::string removeFrom( const std::string &str, const std::string &substr );
87 
89  std::string leftJustified( const std::string &str, size_t width, char fill = ' ' );
90 
91  std::string toLower( const std::string &std );
92 
94  bool getHeaderLine( std::ifstream &stream, std::string &line );
95 
97  size_t toSizeT( const std::string &str );
98  size_t toSizeT( const char &str );
99  size_t toSizeT( const double value );
100  int toInt( const std::string &str );
101  int toInt( const size_t value );
102  double toDouble( const std::string &str );
103  double toDouble( const size_t value );
104  bool toBool( const std::string &str );
105 
109  std::string coordinateToString( double coordinate, int precision = 2 );
110 
113  std::string doubleToString( double value, int precision = 6 );
114 
119  std::vector<std::string> split( const std::string &str, const char delimiter );
120 
122  std::vector<std::string> split( const std::string &str, const std::string &delimiter );
123 
124  std::string join( const std::vector<std::string> parts, const std::string &delimiter );
125 
127  std::string rtrim(
128  const std::string &s,
129  const std::string &delimiters = " \f\n\r\t\v" );
130 
132  std::string ltrim(
133  const std::string &s,
134  const std::string &delimiters = " \f\n\r\t\v" );
135 
137  std::string trim(
138  const std::string &s,
139  const std::string &delimiters = " \f\n\r\t\v" );
140 
141  // extent
142  BBox computeExtent( const Vertices &vertices );
143 
144  // time
146  double parseTimeUnits( const std::string &units );
148  std::string getCurrentTimeStamp();
149 
150  // statistics
151  void combineStatistics( Statistics &main, const Statistics &other );
152 
154  Statistics calculateStatistics( std::shared_ptr<DatasetGroup> grp );
155  Statistics calculateStatistics( DatasetGroup *grp );
156 
158  Statistics calculateStatistics( std::shared_ptr<Dataset> dataset );
159 
160  // mesh & datasets
162  void addBedElevationDatasetGroup( MDAL::Mesh *mesh, const Vertices &vertices );
164  void addFaceScalarDatasetGroup( MDAL::Mesh *mesh, const std::vector<double> &values, const std::string &name );
166  void addVertexScalarDatasetGroup( MDAL::Mesh *mesh, const std::vector<double> &values, const std::string &name );
168  void addEdgeScalarDatasetGroup( MDAL::Mesh *mesh, const std::vector<double> &values, const std::string &name );
169 
171  template<typename T>
172  bool readValue( T &value, std::ifstream &in, bool changeEndianness = false )
173  {
174  char *const p = reinterpret_cast<char *>( &value );
175 
176  if ( !in.read( p, sizeof( T ) ) )
177  return false;
178 
179  if ( changeEndianness )
180  std::reverse( p, p + sizeof( T ) );
181 
182  return true;
183  }
184 
186  template<typename T>
187  void writeValue( T &value, std::ofstream &out, bool changeEndianness = false )
188  {
189  T v = value;
190  char *const p = reinterpret_cast<char *>( &v );
191 
192  if ( changeEndianness )
193  std::reverse( p, p + sizeof( T ) );
194 
195  out.write( p, sizeof( T ) );
196  }
197 
199  std::string prependZero( const std::string &str, size_t length );
200 
201  RelativeTimestamp::Unit parseDurationTimeUnit( const std::string &timeUnit );
202 
205  RelativeTimestamp::Unit parseCFTimeUnit( std::string timeInformation );
206 
209  MDAL::DateTime parseCFReferenceTime( const std::string &timeInformation, const std::string &calendarString );
210 
216  void parseDriverAndMeshFromUri( const std::string &uri, std::string &driver, std::string &meshFile, std::string &meshName );
217 
221  void parseDriverFromUri( const std::string &uri, std::string &driver );
222 
226  void parseMeshFileFromUri( const std::string &uri, std::string &meshFile );
227 
238  std::string buildMeshUri( const std::string &meshFile, const std::string &meshName, const std::string &driver );
239 
243  std::string buildAndMergeMeshUris( const std::string &meshfile, const std::vector<std::string> &meshNames, const std::string &driver = "" );
244 
245  struct Error
246  {
247  Error( MDAL_Status status, std::string message, std::string driverName = "" );
248  void setDriver( std::string d );
249  MDAL_Status status;
250  std::string mssg;
251  std::string driver;
252  };
253 
255  class Library
256  {
257  public:
259  Library( std::string libraryFile );
260  ~Library();
261  Library( const Library &other );
262  Library &operator=( const Library &other );
263 
265  bool isValid();
266 
268  static std::vector<std::string> libraryFilesInDir( const std::string &dirPath );
269 
274  template<typename T, typename ... Ts>
275  std::function<T( Ts ... args )> getSymbol( const std::string &symbolName )
276  {
277  if ( !isValid() )
278  return std::function<T( Ts ... args )>();
279 #ifdef WIN32
280  FARPROC proc = GetProcAddress( d->mLibrary, symbolName.c_str() );
281 
282  if ( !proc )
283  return std::function<T( Ts ... args )>();
284 
285  std::function<T( Ts ... args )> symbol = reinterpret_cast<T( * )( Ts ... args )>( proc );
286 #else
287  std::function<T( Ts ... args )> symbol =
288  reinterpret_cast<T( * )( Ts ... args )>( dlsym( d->mLibrary, symbolName.c_str() ) );
289 
290 #if (defined(__APPLE__) && defined(__MACH__))
291  /* On mach-o systems, C symbols have a leading underscore and depending
292  * on how dlcompat is configured it may or may not add the leading
293  * underscore. If dlsym() fails, add an underscore and try again.
294  */
295  if ( symbol == nullptr )
296  {
297  char withUnder[256] = {};
298  snprintf( withUnder, sizeof( withUnder ), "_%s", symbolName.c_str() );
299  std::function<T( Ts ... args )> symbol = reinterpret_cast<T( * )( Ts ... args )>( dlsym( d->mLibrary, withUnder ) );
300  }
301 #endif
302 #endif
303  return symbol;
304  }
305 
306 
307  private:
308  struct Data
309  {
310 #ifdef WIN32
311  HINSTANCE mLibrary = nullptr;
312 #else
313  void *mLibrary = nullptr;
314 #endif
315  mutable int mRef = 0;
316  std::string mLibraryFile;
317  };
318 
319  Data *d;
320 
321  bool loadLibrary();
322  };
323 } // namespace MDAL
324 #endif //MDAL_UTILS_HPP
Definition: mdal_datetime.hpp:48
Class to handle dynamic library. The loaded library is implicity shared when copying this object.
Definition: mdal_utils.hpp:256
bool isValid()
Returns whether the library is valid after loading the file if needed.
Definition: mdal_utils.cpp:1062
static std::vector< std::string > libraryFilesInDir(const std::string &dirPath)
Returns a list of library file in the folder dirPath.
Definition: mdal_utils.cpp:1070
std::function< T(Ts ... args)> getSymbol(const std::string &symbolName)
Returns a function from a symbol name.
Definition: mdal_utils.hpp:275
Library(std::string libraryFile)
Creater a instance from a library file.
Definition: mdal_utils.cpp:1029
Definition: mdal_data_model.hpp:238
Definition: mdal_utils.hpp:246