Visual Servoing Platform  version 3.6.1 under development (2024-04-19)
vpIoTools.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Directory management.
33  */
34 
40 // At this point, to make scandir() working as expected on armv7 virtualized on a x86-64bit architecture
41 // (see github/workflow/other-arch-isolated.yml) we need to define _FILE_OFFSET_BITS=64. Otherwise
42 // testVideo.cpp will fail.
43 // Since adding here something like:
44 // #include <visp3/core/vpConfig.h>
45 // #ifdef VISP_DEFINE_FILE_OFFSET_BITS
46 // # define _FILE_OFFSET_BITS 64
47 // #endif
48 // where VISP_DEFINE_FILE_OFFSET_BITS is defined in vpConfig.h doesn't work (my explanation is that the define
49 // should be done before any other includes; in vpConfig.h there is cstdlib that is included), the other way
50 // that was retained is to add to vpIoTools.cpp COMPILE_DEFINTIONS _FILE_OFFSET_BITS=64 (see CMakeLists.txt)
51 
52 #include <algorithm>
53 #include <cctype>
54 #include <cmath>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <fstream>
58 #include <functional>
59 #include <limits>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <sys/stat.h>
64 #include <sys/types.h>
65 #include <visp3/core/vpDebug.h>
66 #include <visp3/core/vpEndian.h>
67 #include <visp3/core/vpIoException.h>
68 #include <visp3/core/vpIoTools.h>
69 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
70 #include <dirent.h>
71 #include <unistd.h>
72 #elif defined(_WIN32)
73 #include <direct.h>
74 #include <windows.h>
75 #endif
76 #if !defined(_WIN32)
77 #ifdef __ANDROID__
78 // Like IOS, wordexp.cpp is not defined for Android
79 #else
80 #include <wordexp.h>
81 #endif
82 #endif
83 
84 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
85 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IOS macro
86 #endif
87 
88 #ifndef PATH_MAX
89 #ifdef _MAX_PATH
90 #define PATH_MAX _MAX_PATH
91 #else
92 #define PATH_MAX 1024
93 #endif
94 #endif
95 
96 
97 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
98 #define VP_STAT stat
99 #elif defined(_WIN32) && defined(__MINGW32__)
100 #define VP_STAT stat
101 #elif defined(_WIN32)
102 #define VP_STAT _stat
103 #else
104 #define VP_STAT stat
105 #endif
106 
107 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
108 #define USE_ZLIB_API 0
109 
110 #if !USE_ZLIB_API
111 // See: https://github.com/BinomialLLC/basis_universal/blob/master/encoder/basisu_miniz.h
112 // Apache License, Version 2.0
113 #include "basisu_miniz.h"
114 
115 using namespace buminiz;
116 #else
117 #include <zlib.h>
118 #endif
119 
120 // To avoid warnings such as: warning: unused variable ‘littleEndian’ [-Wunused-variable]
121 #define UNUSED(x) ((void)(x)) // see: https://stackoverflow.com/a/777359
122 
123 // Copyright (C) 2011 Carl Rogers
124 // Released under MIT License
125 // license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
126 
127 #include <regex>
128 
130 {
131  int x = 1;
132  return (((reinterpret_cast<char *>(&x))[0]) ? '<' : '>');
133 }
134 
135 char visp::cnpy::map_type(const std::type_info &t)
136 {
137  if (t == typeid(float)) { return 'f'; }
138  if (t == typeid(double)) { return 'f'; }
139  if (t == typeid(long double)) { return 'f'; }
140 
141  if (t == typeid(int)) { return 'i'; }
142  if (t == typeid(char)) { return 'i'; }
143  if (t == typeid(short)) { return 'i'; }
144  if (t == typeid(long)) { return 'i'; }
145  if (t == typeid(long long)) { return 'i'; }
146 
147  if (t == typeid(unsigned char)) { return 'u'; }
148  if (t == typeid(unsigned short)) { return 'u'; }
149  if (t == typeid(unsigned long)) { return 'u'; }
150  if (t == typeid(unsigned long long)) { return 'u'; }
151  if (t == typeid(unsigned int)) { return 'u'; }
152 
153  if (t == typeid(bool)) { return 'b'; }
154 
155  if (t == typeid(std::complex<float>)) { return 'c'; }
156  if (t == typeid(std::complex<double>)) { return 'c'; }
157  if (t == typeid(std::complex<long double>)) { return 'c'; }
158 
159  else { return '?'; }
160 }
161 
162 void visp::cnpy::parse_npy_header(unsigned char *buffer, size_t &word_size, std::vector<size_t> &shape, bool &fortran_order)
163 {
164  uint16_t header_len = *reinterpret_cast<uint16_t *>(buffer+8);
165  std::string header(reinterpret_cast<char *>(buffer+9), header_len);
166 
167  //fortran order
168  size_t loc1 = header.find("fortran_order")+16;
169  fortran_order = (header.substr(loc1, 4) == "True" ? true : false);
170 
171  //shape
172  loc1 = header.find("(");
173  size_t loc2 = header.find(")");
174 
175  std::regex num_regex("[0-9][0-9]*");
176  std::smatch sm;
177  shape.clear();
178 
179  std::string str_shape = header.substr(loc1+1, loc2-loc1-1);
180  while (std::regex_search(str_shape, sm, num_regex)) {
181  shape.push_back(std::stoi(sm[0].str()));
182  str_shape = sm.suffix().str();
183  }
184 
185  //endian, word size, data type
186  //byte order code | stands for not applicable.
187  //not sure when this applies except for byte array
188  loc1 = header.find("descr")+9;
189  bool littleEndian = (((header[loc1] == '<') || (header[loc1] == '|')) ? true : false);
190  UNUSED(littleEndian); assert(littleEndian);
191 
192  std::string str_ws = header.substr(loc1+2);
193  loc2 = str_ws.find("'");
194  word_size = atoi(str_ws.substr(0, loc2).c_str());
195 }
196 
197 void visp::cnpy::parse_npy_header(FILE *fp, size_t &word_size, std::vector<size_t> &shape, bool &fortran_order)
198 {
199  char buffer[256];
200  size_t res = fread(buffer, sizeof(char), 11, fp);
201  if (res != 11) {
202  throw std::runtime_error("parse_npy_header: failed fread");
203  }
204  std::string header = fgets(buffer, 256, fp);
205  assert(header[header.size()-1] == '\n');
206 
207  size_t loc1, loc2;
208 
209  //fortran order
210  loc1 = header.find("fortran_order");
211  if (loc1 == std::string::npos) {
212  throw std::runtime_error("parse_npy_header: failed to find header keyword: 'fortran_order'");
213  }
214  loc1 += 16;
215  fortran_order = (header.substr(loc1, 4) == "True" ? true : false);
216 
217  //shape
218  loc1 = header.find("(");
219  loc2 = header.find(")");
220  if ((loc1 == std::string::npos) || (loc2 == std::string::npos)) {
221  throw std::runtime_error("parse_npy_header: failed to find header keyword: '(' or ')'");
222  }
223 
224  std::regex num_regex("[0-9][0-9]*");
225  std::smatch sm;
226  shape.clear();
227 
228  std::string str_shape = header.substr(loc1+1, loc2-loc1-1);
229  while (std::regex_search(str_shape, sm, num_regex)) {
230  shape.push_back(std::stoi(sm[0].str()));
231  str_shape = sm.suffix().str();
232  }
233 
234  //endian, word size, data type
235  //byte order code | stands for not applicable.
236  //not sure when this applies except for byte array
237  loc1 = header.find("descr");
238  if (loc1 == std::string::npos) {
239  throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'");
240  }
241  loc1 += 9;
242  bool littleEndian = ((header[loc1] == '<') || (header[loc1] == '|') ? true : false);
243  UNUSED(littleEndian); assert(littleEndian);
244 
245  // --comment: char type equals header[loc1+1];
246  // --comment: assert type equals map_type(T);
247 
248  std::string str_ws = header.substr(loc1+2);
249  loc2 = str_ws.find("'");
250  word_size = atoi(str_ws.substr(0, loc2).c_str());
251 }
252 
253 void visp::cnpy::parse_zip_footer(FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
254 {
255  std::vector<char> footer(22);
256  fseek(fp, -22, SEEK_END);
257  size_t res = fread(&footer[0], sizeof(char), 22, fp);
258  if (res != 22) {
259  throw std::runtime_error("parse_zip_footer: failed fread");
260  }
261 
262  uint16_t disk_no, disk_start, nrecs_on_disk, comment_len;
263  disk_no = *(uint16_t *)&footer[4];
264  disk_start = *(uint16_t *)&footer[6];
265  nrecs_on_disk = *(uint16_t *)&footer[8];
266  nrecs = *(uint16_t *)&footer[10];
267  global_header_size = *(uint32_t *)&footer[12];
268  global_header_offset = *(uint32_t *)&footer[16];
269  comment_len = *(uint16_t *)&footer[20];
270 
271  UNUSED(disk_no); assert(disk_no == 0);
272  UNUSED(disk_start); assert(disk_start == 0);
273  UNUSED(nrecs_on_disk); assert(nrecs_on_disk == nrecs);
274  UNUSED(comment_len); assert(comment_len == 0);
275 }
276 
277 visp::cnpy::NpyArray load_the_npy_file(FILE *fp)
278 {
279  std::vector<size_t> shape;
280  size_t word_size;
281  bool fortran_order;
282  visp::cnpy::parse_npy_header(fp, word_size, shape, fortran_order);
283 
284  visp::cnpy::NpyArray arr(shape, word_size, fortran_order);
285  size_t nread = fread(arr.data<char>(), 1, arr.num_bytes(), fp);
286  if (nread != arr.num_bytes()) {
287  throw std::runtime_error("load_the_npy_file: failed fread");
288  }
289  return arr;
290 }
291 
292 visp::cnpy::NpyArray load_the_npz_array(FILE *fp, uint32_t compr_bytes, uint32_t uncompr_bytes)
293 {
294  std::vector<unsigned char> buffer_compr(compr_bytes);
295  std::vector<unsigned char> buffer_uncompr(uncompr_bytes);
296  size_t nread = fread(&buffer_compr[0], 1, compr_bytes, fp);
297  if (nread != compr_bytes) {
298  throw std::runtime_error("load_the_npy_file: failed fread");
299  }
300 
301  z_stream d_stream;
302 
303  d_stream.zalloc = Z_NULL;
304  d_stream.zfree = Z_NULL;
305  d_stream.opaque = Z_NULL;
306  d_stream.avail_in = 0;
307  d_stream.next_in = Z_NULL;
308  int err = inflateInit2(&d_stream, -MAX_WBITS);
309  UNUSED(err); assert(err == 0);
310 
311  d_stream.avail_in = compr_bytes;
312  d_stream.next_in = &buffer_compr[0];
313  d_stream.avail_out = uncompr_bytes;
314  d_stream.next_out = &buffer_uncompr[0];
315 
316  err = inflate(&d_stream, Z_FINISH);
317  UNUSED(err); assert(err == 0);
318  err = inflateEnd(&d_stream);
319  UNUSED(err); assert(err == 0);
320 
321  std::vector<size_t> shape;
322  size_t word_size;
323  bool fortran_order;
324  visp::cnpy::parse_npy_header(&buffer_uncompr[0], word_size, shape, fortran_order);
325 
326  visp::cnpy::NpyArray array(shape, word_size, fortran_order);
327 
328  size_t offset = uncompr_bytes - array.num_bytes();
329  memcpy(array.data<unsigned char>(), &buffer_uncompr[0]+offset, array.num_bytes());
330 
331  return array;
332 }
333 
343 {
344  FILE *fp = fopen(fname.c_str(), "rb");
345 
346  if (!fp) {
347  throw std::runtime_error("npz_load: Error! Unable to open file "+fname+"!");
348  }
349 
350  visp::cnpy::npz_t arrays;
351  bool quit = false;
352  while (!quit) {
353  std::vector<char> local_header(30);
354  size_t headerres = fread(&local_header[0], sizeof(char), 30, fp);
355  if (headerres != 30) {
356  throw std::runtime_error("npz_load: failed fread");
357  }
358 
359  //if we've reached the global header, stop reading
360  if ((local_header[2] != 0x03) || (local_header[3] != 0x04)) {
361  quit = true;
362  }
363 
364  //read in the variable name
365  uint16_t name_len = *(uint16_t *)&local_header[26];
366  std::string varname(name_len, ' ');
367  size_t vname_res = fread(&varname[0], sizeof(char), name_len, fp);
368  if (vname_res != name_len) {
369  throw std::runtime_error("npz_load: failed fread");
370  }
371 
372  //erase the lagging .npy
373  varname.erase(varname.end()-4, varname.end());
374 
375  //read in the extra field
376  uint16_t extra_field_len = *(uint16_t *)&local_header[28];
377  if (extra_field_len > 0) {
378  std::vector<char> buff(extra_field_len);
379  size_t efield_res = fread(&buff[0], sizeof(char), extra_field_len, fp);
380  if (efield_res != extra_field_len) {
381  throw std::runtime_error("npz_load: failed fread");
382  }
383  }
384 
385  uint16_t compr_method = *reinterpret_cast<uint16_t *>(&local_header[0]+8);
386  uint32_t compr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0]+18);
387  uint32_t uncompr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0]+22);
388 
389  if (compr_method == 0) { arrays[varname] = load_the_npy_file(fp); }
390  else { arrays[varname] = load_the_npz_array(fp, compr_bytes, uncompr_bytes); }
391  }
392 
393  fclose(fp);
394  return arrays;
395 }
396 
406 visp::cnpy::NpyArray visp::cnpy::npz_load(std::string fname, std::string varname)
407 {
408  FILE *fp = fopen(fname.c_str(), "rb");
409 
410  if (!fp) {
411  throw std::runtime_error("npz_load: Unable to open file "+fname);
412  }
413 
414  bool quit = false;
415  while (!quit) {
416  std::vector<char> local_header(30);
417  size_t header_res = fread(&local_header[0], sizeof(char), 30, fp);
418  if (header_res != 30) {
419  throw std::runtime_error("npz_load: failed fread");
420  }
421 
422  //if we've reached the global header, stop reading
423  if ((local_header[2] != 0x03) || (local_header[3] != 0x04)) {
424  quit = true;
425  }
426 
427  //read in the variable name
428  uint16_t name_len = *(uint16_t *)&local_header[26];
429  std::string vname(name_len, ' ');
430  size_t vname_res = fread(&vname[0], sizeof(char), name_len, fp);
431  if (vname_res != name_len) {
432  throw std::runtime_error("npz_load: failed fread");
433  }
434  vname.erase(vname.end()-4, vname.end()); //erase the lagging .npy
435 
436  //read in the extra field
437  uint16_t extra_field_len = *(uint16_t *)&local_header[28];
438  fseek(fp, extra_field_len, SEEK_CUR); //skip past the extra field
439 
440  uint16_t compr_method = *reinterpret_cast<uint16_t *>(&local_header[0]+8);
441  uint32_t compr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0]+18);
442  uint32_t uncompr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0]+22);
443 
444  if (vname == varname) {
445  NpyArray array = (compr_method == 0) ? load_the_npy_file(fp) : load_the_npz_array(fp, compr_bytes, uncompr_bytes);
446  fclose(fp);
447  return array;
448  }
449  else {
450  //skip past the data
451  uint32_t size = *(uint32_t *)&local_header[22];
452  fseek(fp, size, SEEK_CUR);
453  }
454  }
455 
456  fclose(fp);
457 
458  //if we get here, we haven't found the variable in the file
459  throw std::runtime_error("npz_load: Variable name "+varname+" not found in "+fname);
460 }
461 
471 {
472 
473  FILE *fp = fopen(fname.c_str(), "rb");
474 
475  if (!fp) {
476  throw std::runtime_error("npy_load: Unable to open file "+fname);
477  }
478 
479  NpyArray arr = load_the_npy_file(fp);
480 
481  fclose(fp);
482  return arr;
483 }
484 
485 #endif
486 
487 std::string vpIoTools::baseName = "";
488 std::string vpIoTools::baseDir = "";
489 std::string vpIoTools::configFile = "";
490 std::vector<std::string> vpIoTools::configVars = std::vector<std::string>();
491 std::vector<std::string> vpIoTools::configValues = std::vector<std::string>();
492 
493 const char vpIoTools::separator =
494 #if defined(_WIN32)
495 '\\';
496 #else
497 '/';
498 #endif
499 
500 namespace
501 {
502 // The following code is not working on iOS since wordexp() is not available
503 // The function is not used on Android
504 #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
505 #if (TARGET_OS_IOS == 0) && !defined(__ANDROID__)
506 void replaceAll(std::string &str, const std::string &search, const std::string &replace)
507 {
508  size_t start_pos = 0;
509  while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
510  str.replace(start_pos, search.length(), replace);
511  start_pos += replace.length(); // Handles case where 'replace' is a
512  // substring of 'search'
513  }
514 }
515 #endif
516 #endif
517 
518 std::string &ltrim(std::string &s)
519 {
520 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
521  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
522 #else
523  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
524 #endif
525  return s;
526 }
527 
528 std::string &rtrim(std::string &s)
529 {
530 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
531  s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
532 #else
533  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
534 #endif
535  return s;
536 }
537 } // namespace
538 
542 const std::string &vpIoTools::getBuildInformation()
543 {
544  static std::string build_info =
545 #include "version_string.inc"
546  ;
547  return build_info;
548 }
549 
602 {
603 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
604  std::string username;
605  vpIoTools::getUserName(username);
606  return "/tmp/" + username;
607 #elif defined(_WIN32) && !defined(WINRT)
608  // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file
609  // Gets the temp path env string (no guarantee it's a valid path).
610  TCHAR lpTempPathBuffer[MAX_PATH];
611  DWORD dwRetVal = GetTempPath(MAX_PATH /* length of the buffer */, lpTempPathBuffer /* buffer for path */);
612  if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
613  throw vpIoException(vpIoException::cantGetenv, "Error with GetTempPath() call!");
614  }
615  std::string temp_path(lpTempPathBuffer);
616  if (!temp_path.empty()) {
617  if (temp_path.back() == '\\') {
618  temp_path.resize(temp_path.size() - 1);
619  }
620  }
621  else {
622  temp_path = "C:\temp";
623  try {
624  vpIoTools::makeDirectory(temp_path);
625  }
626  catch (...) {
627  throw(vpException(vpException::fatalError, "Cannot set temp path to %s", temp_path.c_str()));
628  }
629  }
630  return temp_path;
631 #else
632  throw vpIoException(vpException::fatalError, "Not implemented on this platform!");
633 #endif
634 }
635 
641 void vpIoTools::setBaseName(const std::string &s) { baseName = s; }
642 
648 void vpIoTools::setBaseDir(const std::string &dir) { baseDir = dir + "/"; }
649 
655 std::string vpIoTools::getBaseName() { return baseName; }
656 
662 std::string vpIoTools::getFullName() { return baseDir + baseName; }
663 
677 void vpIoTools::getUserName(std::string &username)
678 {
679  // With MinGW, UNIX and _WIN32 are defined
680 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
681  // Get the user name.
682  char *logname = ::getenv("LOGNAME");
683  if (!logname) {
684  username = "unknown";
685  }
686  else {
687  username = logname;
688  }
689 #elif defined(_WIN32)
690 #if (!defined(WINRT))
691  unsigned int info_buffer_size = 1024;
692  TCHAR *infoBuf = new TCHAR[info_buffer_size];
693  DWORD bufCharCount = (DWORD)info_buffer_size;
694  // Get the user name.
695  if (!GetUserName(infoBuf, &bufCharCount)) {
696  username = "unknown";
697  }
698  else {
699  username = infoBuf;
700  }
701  delete[] infoBuf;
702 #else
703  // Universal platform
704  username = "unknown";
705 #endif
706 #else
707  username = "unknown";
708 #endif
709 }
710 
726 {
727  std::string username;
728  getUserName(username);
729  return username;
730 }
731 
762 std::string vpIoTools::getenv(const std::string &env)
763 {
764 #if defined(_WIN32) && defined(WINRT)
765  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value: not "
766  "implemented on Universal Windows Platform"));
767 #else
768  std::string value;
769  // Get the environment variable value.
770  char *v_value = ::getenv(env.c_str());
771  if (!v_value) {
772  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value"));
773  }
774  value = v_value;
775 
776  return value;
777 #endif
778 }
779 
789 void vpIoTools::getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
790 {
791  if (version.size() == 0) {
792  major = 0;
793  minor = 0;
794  patch = 0;
795  }
796  else {
797  size_t major_pos = version.find('.');
798  std::string major_str = version.substr(0, major_pos);
799  major = static_cast<unsigned>(atoi(major_str.c_str()));
800 
801  if (major_pos != std::string::npos) {
802  size_t minor_pos = version.find('.', major_pos + 1);
803  std::string minor_str = version.substr(major_pos + 1, (minor_pos - (major_pos + 1)));
804  minor = static_cast<unsigned>(atoi(minor_str.c_str()));
805 
806  if (minor_pos != std::string::npos) {
807  std::string patch_str = version.substr(minor_pos + 1);
808  patch = static_cast<unsigned>(atoi(patch_str.c_str()));
809  }
810  else {
811  patch = 0;
812  }
813  }
814  else {
815  minor = 0;
816  patch = 0;
817  }
818  }
819 }
820 
832 bool vpIoTools::checkDirectory(const std::string &dirname)
833 {
834 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
835  struct stat stbuf;
836 #elif defined(_WIN32) && defined(__MINGW32__)
837  struct stat stbuf;
838 #elif defined(_WIN32)
839  struct _stat stbuf;
840 #endif
841 
842  if (dirname.empty()) {
843  return false;
844  }
845 
846  std::string path_dirname = path(dirname);
847 
848  if (VP_STAT(path_dirname.c_str(), &stbuf) != 0) {
849  // Test adding the separator if not already present
850  if (path_dirname.at(path_dirname.size() - 1) != separator) {
851  if (VP_STAT((path_dirname + separator).c_str(), &stbuf) != 0) {
852  return false;
853  }
854  }
855  // Test removing the separator if already present
856  if (path_dirname.at(path_dirname.size() - 1) == separator) {
857  if (VP_STAT((path_dirname.substr(0, path_dirname.size() - 1)).c_str(), &stbuf) != 0) {
858  return false;
859  }
860  }
861  }
862 
863 #if defined(_WIN32) || (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
864  if ((stbuf.st_mode & S_IFDIR) == 0)
865 #endif
866  {
867  return false;
868  }
869 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
870  if ((stbuf.st_mode & S_IWUSR) == 0)
871 #elif defined(_WIN32)
872  if ((stbuf.st_mode & S_IWRITE) == 0)
873 #endif
874  {
875  return false;
876  }
877  return true;
878 }
879 
892 bool vpIoTools::checkFifo(const std::string &fifofilename)
893 {
894 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
895  struct stat stbuf;
896 
897  std::string v_filename = path(fifofilename);
898  if (stat(v_filename.c_str(), &stbuf) != 0) {
899  return false;
900  }
901  if ((stbuf.st_mode & S_IFIFO) == 0) {
902  return false;
903  }
904  if ((stbuf.st_mode & S_IRUSR) == 0)
905 
906  {
907  return false;
908  }
909  return true;
910 #elif defined(_WIN32)
911  (void)fifofilename;
912  throw(vpIoException(vpIoException::notImplementedError, "Fifo files are not supported on Windows platforms."));
913 #endif
914 }
915 
916 #ifndef DOXYGEN_SHOULD_SKIP_THIS
917 int vpIoTools::mkdir_p(const std::string &path, int mode)
918 {
919  errno = 0;
920  if (path.size() > PATH_MAX) {
921  errno = ENAMETOOLONG;
922  return -1;
923  }
924 
925  // Iterate over the string
926  std::string cpy_path = path;
927  std::string sub_path;
928  for (size_t pos = 0; (pos = cpy_path.find(vpIoTools::separator)) != std::string::npos;) {
929  sub_path += cpy_path.substr(0, pos + 1);
930  // Continue if sub_path = separator
931  if (pos == 0) {
932  cpy_path.erase(0, pos + 1);
933  continue;
934  }
935 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
936  if (mkdir(sub_path.c_str(), static_cast<mode_t>(mode)) != 0)
937 #elif defined(_WIN32)
938  (void)mode; // var not used
939  if (!checkDirectory(sub_path) && _mkdir(sub_path.c_str()) != 0)
940 #endif
941  {
942  if (errno != EEXIST) {
943  return -1;
944  }
945  }
946  cpy_path.erase(0, pos + 1);
947  }
948 
949  if (!cpy_path.empty()) {
950  sub_path += cpy_path;
951 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
952  if (mkdir(sub_path.c_str(), static_cast<mode_t>(mode)) != 0)
953 #elif defined(_WIN32)
954 
955  if (_mkdir(sub_path.c_str()) != 0)
956 #endif
957  {
958  if (errno != EEXIST) {
959  return -1;
960  }
961  }
962  }
963 
964  return 0;
965 }
966 
967 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
968 
981 void vpIoTools::makeDirectory(const std::string &dirname)
982 {
983 #if ((!defined(__unix__) && !defined(__unix) && (!defined(__APPLE__) || !defined(__MACH__)))) && !defined(_WIN32)
984  std::cerr << "Unsupported platform for vpIoTools::makeDirectory()!" << std::endl;
985  return;
986 #endif
987 
988 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
989  struct stat stbuf;
990 #elif defined(_WIN32) && defined(__MINGW32__)
991  struct stat stbuf;
992 #elif defined(_WIN32)
993  struct _stat stbuf;
994 #endif
995 
996  if (dirname.empty()) {
997  throw(vpIoException(vpIoException::invalidDirectoryName, "invalid directory name"));
998  }
999 
1000  std::string v_dirname = path(dirname);
1001 
1002 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1003  if (stat(v_dirname.c_str(), &stbuf) != 0)
1004 #elif defined(_WIN32) && defined(__MINGW32__)
1005  if (stat(v_dirname.c_str(), &stbuf) != 0)
1006 #elif defined(_WIN32)
1007  if (_stat(v_dirname.c_str(), &stbuf) != 0)
1008 #endif
1009  {
1010  if (vpIoTools::mkdir_p(v_dirname, 0755) != 0) {
1011  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
1012  }
1013  }
1014 
1015  if (checkDirectory(dirname) == false) {
1016  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
1017  }
1018 }
1019 
1032 void vpIoTools::makeFifo(const std::string &fifoname)
1033 {
1034 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1035 
1036  // If dirname is a directory, we throw an error
1037  if (vpIoTools::checkDirectory(fifoname)) {
1039  "Unable to create fifo file. '%s' is an existing directory.", fifoname.c_str()));
1040  }
1041 
1042  // If dirname refers to an already existing file, we throw an error
1043  else if (vpIoTools::checkFilename(fifoname)) {
1044  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. File already exists.",
1045  fifoname.c_str()));
1046  // If dirname refers to an already existing fifo, we throw an error
1047  }
1048  else if (vpIoTools::checkFifo(fifoname)) {
1049  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. Fifo already exists.",
1050  fifoname.c_str()));
1051  }
1052 
1053  else if (mkfifo(fifoname.c_str(), 0666) < 0) {
1054  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo file '%s'.", fifoname.c_str()));
1055  }
1056 #elif defined(_WIN32)
1057  (void)fifoname;
1058  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo on Windows platforms."));
1059 #endif
1060 }
1061 
1062 #if defined(_WIN32) && !defined(WINRT)
1063 std::string getUuid()
1064 {
1065  UUID uuid;
1066  if (UuidCreate(&uuid) != RPC_S_OK) {
1067  throw(vpIoException(vpIoException::fatalError, "UuidCreate() failed!"));
1068  }
1069 
1070  RPC_CSTR stringUuid;
1071  if (UuidToString(&uuid, &stringUuid) != RPC_S_OK) {
1072  throw(vpIoException(vpIoException::fatalError, "UuidToString() failed!"));
1073  }
1074 
1075  return reinterpret_cast<char *>(stringUuid);
1076 }
1077 #endif
1078 
1135 std::string vpIoTools::makeTempDirectory(const std::string &dirname)
1136 {
1137 #if defined(WINRT) || !defined(_WIN32) && !(defined(__unix__) || defined(__unix) || \
1138  (defined(__APPLE__) && defined(__MACH__))) // not UNIX and not Windows
1139  throw(vpIoException(vpIoException::cantCreateDirectory, "makeTempDirectory() is not supported on this platform!"));
1140 #endif
1141 
1142  std::string dirname_cpy = std::string(dirname);
1143  std::string correctEnding = "XXXXXX";
1144 
1145  // If dirname is an unexisting directory, it should end with XXXXXX in order to create a temp directory
1146  if (!vpIoTools::checkDirectory(dirname_cpy)) {
1147 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1148  // Check if dirname ends with XXXXXX
1149  if (dirname_cpy.rfind(correctEnding) == std::string::npos) {
1150  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
1151  dirname_cpy = dirname_cpy + "/";
1152  }
1153  try {
1154  vpIoTools::makeDirectory(dirname_cpy);
1155  }
1156  catch (...) {
1157  throw(vpException(vpException::fatalError, "Cannot create temp directory %s", dirname_cpy.c_str()));
1158  }
1159 
1160  dirname_cpy = dirname_cpy + "XXXXXX";
1161  }
1162 
1163 #elif defined(_WIN32) && !defined(WINRT)
1164  // Remove XXXXXX
1165  dirname_cpy = dirname_cpy.substr(0, dirname_cpy.rfind(correctEnding));
1166  // Append UUID
1167  dirname_cpy = dirname_cpy + getUuid();
1168 #endif
1169 
1170  }
1171  else {
1172  // If dirname is an existing directory, we create a temp directory inside
1173 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1174  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
1175  dirname_cpy = dirname_cpy + "/";
1176  }
1177  dirname_cpy = dirname_cpy + "XXXXXX";
1178 #elif defined(_WIN32) && !defined(WINRT)
1179  dirname_cpy = createFilePath(dirname_cpy, getUuid());
1180 #endif
1181  }
1182 
1183 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1184  char *dirname_char = new char[dirname_cpy.length() + 1];
1185  strcpy(dirname_char, dirname_cpy.c_str());
1186 
1187  char *computedDirname = mkdtemp(dirname_char);
1188 
1189  if (!computedDirname) {
1190  delete[] dirname_char;
1191  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'.", dirname_cpy.c_str()));
1192  }
1193 
1194  std::string res(computedDirname);
1195  delete[] dirname_char;
1196  return res;
1197 #elif defined(_WIN32) && !defined(WINRT)
1198  makeDirectory(dirname_cpy);
1199  return dirname_cpy;
1200 #endif
1201 }
1202 
1213 bool vpIoTools::checkFilename(const std::string &filename)
1214 {
1215 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1216  struct stat stbuf;
1217 #elif defined(_WIN32)
1218  struct _stat stbuf;
1219 #endif
1220 
1221  if (filename.empty()) {
1222  return false;
1223  }
1224 
1225  std::string v_filename = path(filename);
1226 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1227  if (stat(v_filename.c_str(), &stbuf) != 0)
1228 #elif defined(_WIN32)
1229  if (_stat(v_filename.c_str(), &stbuf) != 0)
1230 #endif
1231  {
1232  return false;
1233  }
1234  if ((stbuf.st_mode & S_IFREG) == 0) {
1235  return false;
1236  }
1237 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1238  if ((stbuf.st_mode & S_IRUSR) == 0)
1239 #elif defined(_WIN32)
1240  if ((stbuf.st_mode & S_IREAD) == 0)
1241 #endif
1242  {
1243  return false;
1244  }
1245  return true;
1246 }
1247 
1255 bool vpIoTools::copy(const std::string &src, const std::string &dst)
1256 {
1257  // Check if we have to consider a file or a directory
1258  if (vpIoTools::checkFilename(src)) {
1259  // --comment: std::cout "copy file: " src " in " dst std::endl;
1260 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1261 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
1262  // wordexp() is not available
1263  std::stringstream cmd;
1264  cmd << "cp -p ";
1265  cmd << src;
1266  cmd << " ";
1267  cmd << dst;
1268  int ret = system(cmd.str().c_str());
1269  if (ret) {
1270  } // to avoid a warning
1271  // std::cout << cmd << " return value: " << ret << std::endl;
1272  return true;
1273 #else
1274  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
1275  dst.c_str()));
1276 #endif
1277 #elif defined(_WIN32)
1278 #if (!defined(WINRT))
1279  std::stringstream cmd;
1280  cmd << "copy ";
1281  cmd << vpIoTools::path(src);
1282  cmd << " ";
1283  cmd << vpIoTools::path(dst);
1284  int ret = system(cmd.str().c_str());
1285  if (ret) {
1286  }; // to avoid a warning
1287  // std::cout << cmd << " return value: " << ret << std::endl;
1288  return true;
1289 #else
1290  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
1291  src.c_str(), dst.c_str()));
1292 #endif
1293 #endif
1294  }
1295  else if (vpIoTools::checkDirectory(src)) {
1296  // --comment: std::cout "copy directory: " src " in " dst
1297 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1298 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
1299  // wordexp() is not available
1300  std::stringstream cmd;
1301  cmd << "cp -p ";
1302  cmd << src;
1303  cmd << " ";
1304  cmd << dst;
1305  int ret = system(cmd.str().c_str());
1306  if (ret) {
1307  } // to avoid a warning
1308  // std::cout << cmd << " return value: " << ret << std::endl;
1309  return true;
1310 #else
1311  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
1312  dst.c_str()));
1313 #endif
1314 #elif defined(_WIN32)
1315 #if (!defined(WINRT))
1316  std::stringstream cmd;
1317  cmd << "copy ";
1318  cmd << vpIoTools::path(src);
1319  cmd << " ";
1320  cmd << vpIoTools::path(dst);
1321  int ret = system(cmd.str().c_str());
1322  if (ret) {
1323  }; // to avoid a warning
1324  // std::cout << cmd << " return value: " << ret << std::endl;
1325  return true;
1326 #else
1327  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
1328  src.c_str(), dst.c_str()));
1329 #endif
1330 #endif
1331  }
1332  else {
1333  std::cout << "Cannot copy: " << src << " in " << dst << std::endl;
1334  return false;
1335  }
1336 }
1337 
1348 bool vpIoTools::remove(const std::string &file_or_dir)
1349 {
1350  // Check if we have to consider a file or a directory
1351  if (vpIoTools::checkFilename(file_or_dir)
1352 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1353  || vpIoTools::checkFifo(std::string(file_or_dir))
1354 #endif
1355  ) {
1356  if (::remove(file_or_dir.c_str()) != 0) {
1357  return false;
1358  }
1359  else {
1360  return true;
1361  }
1362  }
1363  else if (vpIoTools::checkDirectory(file_or_dir)) {
1364 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1365 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
1366  // wordexp() is not available
1367  std::stringstream cmd;
1368  cmd << "rm -rf \"";
1369  cmd << file_or_dir;
1370  cmd << "\"";
1371  int ret = system(cmd.str().c_str());
1372  if (ret) {
1373  } // to avoid a warning
1374  // std::cout << cmd << " return value: " << ret << std::endl;
1375  return true;
1376 #else
1377  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on iOS Platform",
1378  file_or_dir.c_str()));
1379 #endif
1380 #elif defined(_WIN32)
1381 #if (!defined(WINRT))
1382  std::stringstream cmd;
1383  cmd << "rmdir /S /Q ";
1384  cmd << vpIoTools::path(file_or_dir);
1385  cmd << "\"";
1386  int ret = system(cmd.str().c_str());
1387  if (ret) {
1388  }; // to avoid a warning
1389  // std::cout << cmd << " return value: " << ret << std::endl;
1390  return true;
1391 #else
1392  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on Universal Windows Platform",
1393  file_or_dir.c_str()));
1394 #endif
1395 #endif
1396  }
1397  else {
1398  std::cout << "Cannot remove: " << file_or_dir << std::endl;
1399  return false;
1400  }
1401 }
1402 
1412 bool vpIoTools::rename(const std::string &oldfilename, const std::string &newfilename)
1413 {
1414  if (::rename(oldfilename.c_str(), newfilename.c_str()) != 0) {
1415  return false;
1416  }
1417  else {
1418  return true;
1419  }
1420 }
1421 
1432 std::string vpIoTools::path(const std::string &pathname)
1433 {
1434  std::string path(pathname);
1435 
1436 #if defined(_WIN32)
1437  for (unsigned int i = 0; i < path.length(); ++i)
1438  if (path[i] == '/')
1439  path[i] = '\\';
1440 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
1441  unsigned int path_length = path.length();
1442  for (unsigned int i = 0; i < path_length; ++i) {
1443  if (path[i] == '\\') {
1444  path[i] = '/';
1445  }
1446  }
1447 #if TARGET_OS_IOS == 0 // The following code is not working on iOS and android since
1448  // wordexp() is not available
1449 #ifdef __ANDROID__
1450 // Do nothing
1451 #else
1452  wordexp_t exp_result;
1453 
1454  // escape quote character
1455  replaceAll(path, "'", "'\\''");
1456  // add quotes to handle special characters like parentheses and spaces
1457  wordexp(std::string("'" + path + "'").c_str(), &exp_result, 0);
1458  path = exp_result.we_wordc == 1 ? exp_result.we_wordv[0] : "";
1459  wordfree(&exp_result);
1460 #endif
1461 #endif
1462 #endif
1463 
1464  return path;
1465 }
1466 
1475 bool vpIoTools::loadConfigFile(const std::string &confFile)
1476 {
1477  configFile = path(confFile);
1478  configVars.clear();
1479  configValues.clear();
1480  std::ifstream confContent(configFile.c_str(), std::ios::in);
1481 
1482  if (confContent.is_open()) {
1483  std::string line, var, val;
1484  unsigned long int k;
1485  int c;
1486  std::string stop[3] = { " ", "\t", "#" };
1487  while (std::getline(confContent, line)) {
1488  if ((line.compare(0, 1, "#") != 0) && (line.size() > 2)) {
1489  // name of the variable
1490  k = static_cast<unsigned long>(line.find(" "));
1491  var = line.substr(0, k);
1492  // look for the end of the actual value
1493  c = 200;
1494  for (unsigned i = 0; i < 3; ++i) {
1495  c = vpMath::minimum(c,
1496  static_cast<int>(line.find(stop[i], static_cast<size_t>(k) + static_cast<size_t>(1))));
1497  }
1498  if (c == -1) {
1499  c = static_cast<int>(line.size());
1500  }
1501  unsigned long int c_ = static_cast<unsigned long int>(c);
1502  val = line.substr(static_cast<size_t>(k) + static_cast<size_t>(1),
1503  static_cast<size_t>(c_) - static_cast<size_t>(k) - static_cast<size_t>(1));
1504  configVars.push_back(var);
1505  configValues.push_back(val);
1506  }
1507  }
1508  confContent.close();
1509  }
1510  else {
1511  return false;
1512  }
1513  return true;
1514 }
1515 
1524 bool vpIoTools::readConfigVar(const std::string &var, float &value)
1525 {
1526  bool found = false;
1527  unsigned int configvars_size = configVars.size();
1528  for (unsigned int k = 0; (k < configvars_size) && (found == false); ++k) {
1529  if (configVars[k] == var) {
1530  if (configValues[k].compare("PI") == 0) {
1531  value = static_cast<float>(M_PI);
1532  }
1533  else if (configValues[k].compare("PI/2") == 0) {
1534  value = static_cast<float>(M_PI / 2.0);
1535  }
1536  else if (configValues[k].compare("-PI/2") == 0) {
1537  value = static_cast<float>(-M_PI / 2.0);
1538  }
1539  else {
1540  value = static_cast<float>(atof(configValues[k].c_str()));
1541  }
1542  found = true;
1543  }
1544  }
1545  if (found == false) {
1546  std::cout << var << " not found in config file" << std::endl;
1547  }
1548  return found;
1549 }
1558 bool vpIoTools::readConfigVar(const std::string &var, double &value)
1559 {
1560  bool found = false;
1561  unsigned int configvars_size = configVars.size();
1562  for (unsigned int k = 0; (k < configvars_size) && (found == false); ++k) {
1563  if (configVars[k] == var) {
1564  if (configValues[k].compare("PI") == 0) {
1565  value = M_PI;
1566  }
1567  else if (configValues[k].compare("PI/2") == 0) {
1568  value = M_PI / 2;
1569  }
1570  else if (configValues[k].compare("-PI/2") == 0) {
1571  value = -M_PI / 2;
1572  }
1573  else {
1574  value = atof(configValues[k].c_str());
1575  }
1576  found = true;
1577  }
1578  }
1579  if (found == false) {
1580  std::cout << var << " not found in config file" << std::endl;
1581  }
1582  return found;
1583 }
1584 
1593 bool vpIoTools::readConfigVar(const std::string &var, int &value)
1594 {
1595  bool found = false;
1596  unsigned int configvars_size = configVars.size();
1597  for (unsigned int k = 0; (k < configvars_size) && (found == false); ++k) {
1598  if (configVars[k] == var) {
1599  value = atoi(configValues[k].c_str());
1600  found = true;
1601  }
1602  }
1603  if (found == false) {
1604  std::cout << var << " not found in config file" << std::endl;
1605  }
1606  return found;
1607 }
1608 
1617 bool vpIoTools::readConfigVar(const std::string &var, unsigned int &value)
1618 {
1619  int v = 0;
1620  bool found = readConfigVar(var, v);
1621  value = static_cast<unsigned int>(v);
1622  return found;
1623 }
1624 
1633 bool vpIoTools::readConfigVar(const std::string &var, bool &value)
1634 {
1635  int v = 0;
1636  bool found = readConfigVar(var, v);
1637  value = (v != 0);
1638  return found;
1639 }
1640 
1649 bool vpIoTools::readConfigVar(const std::string &var, vpColor &value)
1650 {
1651  unsigned int v = 0;
1652  bool found = readConfigVar(var, v);
1653  value = vpColor::getColor(v);
1654  return found;
1655 }
1656 
1665 bool vpIoTools::readConfigVar(const std::string &var, std::string &value)
1666 {
1667  bool found = false;
1668  unsigned int configvars_size = configVars.size();
1669  for (unsigned int k = 0; (k < configvars_size) && (found == false); ++k) {
1670  if (configVars[k] == var) {
1671  value = configValues[k];
1672  found = true;
1673  }
1674  }
1675  if (found == false) {
1676  std::cout << var << " not found in config file" << std::endl;
1677  }
1678  return found;
1679 }
1680 
1694 bool vpIoTools::readConfigVar(const std::string &var, vpArray2D<double> &value, const unsigned int &nCols,
1695  const unsigned int &nRows)
1696 {
1697  bool found = false;
1698  std::string nb;
1699  unsigned int configvars_size = configVars.size();
1700  for (unsigned int k = 0; (k < configvars_size) && (found == false); ++k) {
1701  if (configVars[k] == var) {
1702  found = true;
1703  // resize or not
1704  if ((nCols != 0) && (nRows != 0)) {
1705  value.resize(nRows, nCols);
1706  }
1707  size_t ind = 0, ind2;
1708  unsigned int value_rows = value.getRows();
1709  unsigned int value_cols = value.getCols();
1710  for (unsigned int i = 0; i < value_rows; ++i) {
1711  for (unsigned int j = 0; j < value_cols; ++j) {
1712  ind2 = configValues[k].find(",", ind);
1713  nb = configValues[k].substr(ind, ind2 - ind);
1714  if (nb.compare("PI") == 0) {
1715  value[i][j] = M_PI;
1716  }
1717  else if (nb.compare("PI/2") == 0) {
1718  value[i][j] = M_PI / 2;
1719  }
1720  else if (nb.compare("-PI/2") == 0) {
1721  value[i][j] = -M_PI / 2;
1722  }
1723  else {
1724  value[i][j] = atof(nb.c_str());
1725  }
1726  ind = ind2 + 1;
1727  }
1728  }
1729  }
1730  }
1731  if (found == false) {
1732  std::cout << var << " not found in config file" << std::endl;
1733  }
1734  return found;
1735 }
1736 
1737 // construct experiment filename & path
1738 
1747 void vpIoTools::addNameElement(const std::string &strTrue, const bool &cond, const std::string &strFalse)
1748 {
1749  if (cond) {
1750  baseName += "_" + strTrue;
1751  }
1752  else if (strFalse != "") {
1753  baseName += "_" + strFalse;
1754  }
1755 }
1756 
1765 void vpIoTools::addNameElement(const std::string &strTrue, const double &val)
1766 {
1767  // if(val != 0.)
1768  if (std::fabs(val) < std::numeric_limits<double>::epsilon()) {
1769  std::stringstream valS;
1770  valS.precision(4);
1771  valS << val;
1772  baseName += "_" + strTrue + valS.str();
1773  }
1774 }
1775 
1784 void vpIoTools::createBaseNamePath(const bool &empty)
1785 {
1786  std::string path = baseDir + baseName;
1787  if (vpIoTools::checkDirectory(path) == false) {
1788  try {
1790  std::cout << "Creating directory " << path << std::endl;
1791  }
1792  catch (...) {
1793  throw(vpException(vpException::fatalError, "Cannot create base name directory %s", path.c_str()));
1794  }
1795  }
1796  else {
1797  if (empty) {
1798  std::cout << "Emptying directory " << path << std::endl;
1799  vpIoTools::remove(path + "/*");
1800  }
1801  }
1802 }
1803 
1810 void vpIoTools::saveConfigFile(const bool &actuallySave)
1811 {
1812  if (actuallySave) {
1813  std::string dest = baseDir + "/" + baseName + "_config.txt";
1814  // file copy
1815  vpIoTools::copy(configFile, dest);
1816  }
1817 }
1818 
1833 {
1834  std::string data_path;
1835  std::string file_to_test("mbt/cube.cao");
1836  std::string filename;
1837  // Test if VISP_INPUT_IMAGE_PATH env var is set
1838  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH");
1839  filename = data_path + "/" + file_to_test;
1840  if (vpIoTools::checkFilename(filename)) {
1841  return data_path;
1842  }
1843  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/ViSP-images";
1844  filename = data_path + "/" + file_to_test;
1845  if (vpIoTools::checkFilename(filename)) {
1846  return data_path;
1847  }
1848  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/visp-images";
1849  filename = data_path + "/" + file_to_test;
1850  if (vpIoTools::checkFilename(filename)) {
1851  return data_path;
1852  }
1853 
1854 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1855  // Test if visp-images-data package is installed (Ubuntu and Debian)
1856  data_path = "/usr/share/visp-images-data/ViSP-images";
1857  filename = data_path + "/" + file_to_test;
1858  if (vpIoTools::checkFilename(filename)) {
1859  return data_path;
1860  }
1861  data_path = "/usr/share/visp-images-data/visp-images";
1862  filename = data_path + "/" + file_to_test;
1863  if (vpIoTools::checkFilename(filename)) {
1864  return data_path;
1865  }
1866 #endif
1867  data_path = "";
1868  return data_path;
1869 }
1870 
1900 std::string vpIoTools::getFileExtension(const std::string &pathname, bool checkFile)
1901 {
1902  if (checkFile && (vpIoTools::checkDirectory(pathname) || (!vpIoTools::checkFilename(pathname)))) {
1903  return "";
1904  }
1905 
1906 #if defined(_WIN32)
1907  std::string sep = "\\";
1908  std::string altsep = "/";
1909  std::string extsep = ".";
1910 #else
1911  // On Unix, or on the Mac
1912  std::string sep = "/";
1913  std::string altsep = "";
1914  std::string extsep = ".";
1915 #endif
1916 
1917  // Python 2.7.8 module.
1918  // # Split a path in root and extension.
1919  // # The extension is everything starting at the last dot in the last
1920  // # pathname component; the root is everything before that.
1921  // # It is always true that root + ext == p.
1922  //
1923  // # Generic implementation of splitext, to be parametrized with
1924  // # the separators
1925  // def _splitext(p, sep, altsep, extsep):
1926  // """Split the extension from a pathname.
1927  //
1928  // Extension is everything from the last dot to the end, ignoring
1929  // leading dots. Returns "(root, ext)"; ext may be empty."""
1930  //
1931  // sepIndex = p.rfind(sep)
1932  // if altsep:
1933  // altsepIndex = p.rfind(altsep)
1934  // sepIndex = max(sepIndex, altsepIndex)
1935  //
1936  // dotIndex = p.rfind(extsep)
1937  // if dotIndex > sepIndex:
1938  // # skip all leading dots
1939  // filenameIndex = sepIndex + 1
1940  // while filenameIndex < dotIndex:
1941  // if p[filenameIndex] != extsep:
1942  // return p[:dotIndex], p[dotIndex:]
1943  // filenameIndex += 1
1944  //
1945  // return p, ''
1946 
1947  int sepIndex = static_cast<int>(pathname.rfind(sep));
1948  if (!altsep.empty()) {
1949  int altsepIndex = static_cast<int>(pathname.rfind(altsep));
1950  sepIndex = std::max<int>(sepIndex, altsepIndex);
1951  }
1952 
1953  size_t dotIndex = pathname.rfind(extsep);
1954  if (dotIndex != std::string::npos) {
1955  // The extsep character exists
1956  size_t npos = std::string::npos;
1957  if (((sepIndex != static_cast<int>(npos)) && (static_cast<int>(dotIndex) > sepIndex)) ||
1958  (sepIndex == static_cast<int>(npos))) {
1959  if (sepIndex == static_cast<int>(npos)) {
1960  sepIndex = 0;
1961  }
1962  size_t filenameIndex = static_cast<size_t>(sepIndex) + static_cast<size_t>(1);
1963 
1964  while (filenameIndex < dotIndex) {
1965  if (pathname.compare(filenameIndex, 1, extsep) != 0) {
1966  return pathname.substr(dotIndex);
1967  }
1968  filenameIndex++;
1969  }
1970  }
1971  }
1972 
1973  return "";
1974 }
1975 
1981 std::string vpIoTools::getName(const std::string &pathname)
1982 {
1983  if (pathname.size() > 0) {
1984  std::string convertedPathname = vpIoTools::path(pathname);
1985 
1986  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1987  if (index != std::string::npos) {
1988  return convertedPathname.substr(index + 1);
1989  }
1990 
1991  return convertedPathname;
1992  }
1993 
1994  return "";
1995 }
1996 
2003 std::string vpIoTools::getNameWE(const std::string &pathname)
2004 {
2005  std::string name = vpIoTools::getName(pathname);
2006  size_t found = name.find_last_of(".");
2007  std::string name_we = name.substr(0, found);
2008  return name_we;
2009 }
2010 
2044 long vpIoTools::getIndex(const std::string &filename, const std::string &format)
2045 {
2046  size_t indexBegin = format.find_last_of('%');
2047  size_t indexEnd = format.find_first_of('d', indexBegin);
2048  size_t suffixLength = format.length() - indexEnd - 1;
2049  // Extracting index
2050  if (filename.length() <= (suffixLength + indexBegin)) {
2051  return -1;
2052  }
2053  size_t indexLength = filename.length() - suffixLength - indexBegin;
2054  std::string indexSubstr = filename.substr(indexBegin, indexLength);
2055  std::istringstream ss(indexSubstr);
2056  long index = 0;
2057  ss >> index;
2058  if (ss.fail() || (index < 0) || (!ss.eof())) {
2059  return -1;
2060  }
2061 
2062  // Checking that format with inserted index equals filename
2063  char nameByFormat[FILENAME_MAX];
2064  snprintf(nameByFormat, FILENAME_MAX, format.c_str(), index);
2065  if (std::string(nameByFormat) != filename) {
2066  return -1;
2067  }
2068  return index;
2069 }
2070 
2086 std::string vpIoTools::getParent(const std::string &pathname)
2087 {
2088  if (pathname.size() > 0) {
2089  std::string convertedPathname = vpIoTools::path(pathname);
2090 
2091  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
2092  if (index != std::string::npos) {
2093  return convertedPathname.substr(0, index);
2094  }
2095 
2096  return ".";
2097  }
2098  else {
2099  return "";
2100  }
2101 }
2102 
2111 std::string vpIoTools::toLowerCase(const std::string &input)
2112 {
2113  std::string out;
2114 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
2115  for (std::string::const_iterator it = input.cbegin(); it != input.cend(); ++it) {
2116 #else
2117  for (std::string::const_iterator it = input.begin(); it != input.end(); ++it) {
2118 #endif
2119  out += std::tolower(*it);
2120  }
2121  return out;
2122  }
2123 
2132 std::string vpIoTools::toUpperCase(const std::string &input)
2133 {
2134  std::string out;
2135 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
2136  for (std::string::const_iterator it = input.cbegin(); it != input.cend(); ++it) {
2137 #else
2138  for (std::string::const_iterator it = input.begin(); it != input.end(); ++it) {
2139 #endif
2140  out += std::toupper(*it);
2141  }
2142  return out;
2143  }
2144 
2153 std::string vpIoTools::getAbsolutePathname(const std::string &pathname)
2154 {
2155 
2156 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
2157  std::string real_path_str = pathname;
2158  char *real_path = realpath(pathname.c_str(), nullptr);
2159 
2160  if (real_path) {
2161  real_path_str = real_path;
2162  free(real_path);
2163  }
2164  return real_path_str;
2165 #elif defined(_WIN32)
2166 #if (!defined(WINRT))
2167  std::string real_path_str = pathname;
2168  DWORD retval = 0;
2169  TCHAR buffer[4096] = TEXT("");
2170 
2171  retval = GetFullPathName(pathname.c_str(), 4096, buffer, 0);
2172  if (retval != 0) {
2173  real_path_str = buffer;
2174  }
2175  return real_path_str;
2176 #else
2178  "Cannot get absolute path of %s: not implemented on "
2179  "Universal Windows Platform",
2180  pathname.c_str()));
2181 #endif
2182 #endif
2183 }
2184 
2195 std::string vpIoTools::createFilePath(const std::string &parent, const std::string &child)
2196 {
2197  if ((child.size() == 0) && (parent.size() == 0)) {
2198  return "";
2199  }
2200 
2201  if (child.size() == 0) {
2202  return vpIoTools::path(parent);
2203  }
2204 
2205  if (parent.size() == 0) {
2206  return vpIoTools::path(child);
2207  }
2208 
2209  std::string convertedParent = vpIoTools::path(parent);
2210  std::string convertedChild = vpIoTools::path(child);
2211 
2212  std::stringstream ss;
2213  ss << vpIoTools::separator;
2214  std::string stringSeparator;
2215  ss >> stringSeparator;
2216 
2217  std::string lastConvertedParentChar = convertedParent.substr(convertedParent.size() - 1);
2218  std::string firstConvertedChildChar = convertedChild.substr(0, 1);
2219 
2220  if (lastConvertedParentChar == stringSeparator) {
2221  convertedParent = convertedParent.substr(0, convertedParent.size() - 1);
2222  }
2223 
2224  if (firstConvertedChildChar == stringSeparator) {
2225  convertedChild = convertedChild.substr(1);
2226  }
2227 
2228  return std::string(convertedParent + vpIoTools::separator + convertedChild);
2229 }
2230 
2236 bool vpIoTools::isAbsolutePathname(const std::string &pathname)
2237 {
2238  // # Inspired by the Python 2.7.8 module.
2239  // # Return whether a path is absolute.
2240  // # Trivial in Posix, harder on the Mac or MS-DOS.
2241  // # For DOS it is absolute if it starts with a slash or backslash (current
2242  // # volume), or if a pathname after the volume letter and colon / UNC
2243  // resource # starts with a slash or backslash.
2244  //
2245  // def isabs(s):
2246  // """Test whether a path is absolute"""
2247  // s = splitdrive(s)[1]
2248  // return s != '' and s[:1] in '/\\'
2249  std::string path = splitDrive(pathname).second;
2250  return (path.size() > 0) && ((path.substr(0, 1) == "/") || (path.substr(0, 1) == "\\"));
2251 }
2252 
2260 bool vpIoTools::isSamePathname(const std::string &pathname1, const std::string &pathname2)
2261 {
2262  // Normalize path
2263  std::string path1_normalize = vpIoTools::path(pathname1);
2264  std::string path2_normalize = vpIoTools::path(pathname2);
2265 
2266  // Get absolute path
2267  path1_normalize = vpIoTools::getAbsolutePathname(path1_normalize);
2268  path2_normalize = vpIoTools::getAbsolutePathname(path2_normalize);
2269 
2270  return (path1_normalize == path2_normalize);
2271 }
2272 
2280 std::pair<std::string, std::string> vpIoTools::splitDrive(const std::string &pathname)
2281 {
2282  // # Split a path in a drive specification (a drive letter followed by a
2283  // # colon) and the path specification.
2284  // # It is always true that drivespec + pathspec == p
2285  // def splitdrive(p):
2286  // """Split a pathname into drive/UNC sharepoint and relative path
2287  // specifiers. Returns a 2-tuple (drive_or_unc, path); either part may be
2288  // empty.
2289  //
2290  // If you assign
2291  // result = splitdrive(p)
2292  // It is always true that:
2293  // result[0] + result[1] == p
2294  //
2295  // If the path contained a drive letter, drive_or_unc will contain
2296  // everything up to and including the colon. e.g. splitdrive("c:/dir")
2297  // returns ("c:", "/dir")
2298  //
2299  // If the path contained a UNC path, the drive_or_unc will contain the host
2300  // name and share up to but not including the fourth directory separator
2301  // character. e.g. splitdrive("//host/computer/dir") returns
2302  // ("//host/computer", "/dir")
2303  //
2304  // Paths cannot contain both a drive letter and a UNC path.
2305  //
2306  // """
2307  // if len(p) > 1:
2308  // normp = p.replace(altsep, sep)
2309  // if (normp[0:2] == sep*2) and (normp[2] != sep):
2310  // # is a UNC path:
2311  // # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
2312  // # \\machine\mountpoint\directory\etc\...
2313  // # directory ^^^^^^^^^^^^^^^
2314  // index = normp.find(sep, 2)
2315  // if index == -1:
2316  // return '', p
2317  // index2 = normp.find(sep, index + 1)
2318  // # a UNC path can't have two slashes in a row
2319  // # (after the initial two)
2320  // if index2 == index + 1:
2321  // return '', p
2322  // if index2 == -1:
2323  // index2 = len(p)
2324  // return p[:index2], p[index2:]
2325  // if normp[1] == ':':
2326  // return p[:2], p[2:]
2327  // return '', p
2328 
2329  // On Unix, the drive is always empty.
2330  // On the Mac, the drive is always empty (don't use the volume name -- it
2331  // doesn't have the same syntactic and semantic oddities as DOS drive
2332  // letters, such as there being a separate current directory per drive).
2333 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
2334  return std::pair<std::string, std::string>("", pathname);
2335 #else
2336  const std::string sep = "\\";
2337  const std::string sepsep = "\\\\";
2338  const std::string altsep = "/";
2339 
2340  if (pathname.size() > 1) {
2341  std::string normPathname = pathname;
2342  std::replace(normPathname.begin(), normPathname.end(), *altsep.c_str(), *sep.c_str());
2343 
2344  if (normPathname.substr(0, 2) == sepsep && normPathname.substr(2, 1) != sep) {
2345  // is a UNC path:
2346  // vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
2347  // \\machine\mountpoint\directory\etc\...
2348  // directory ^^^^^^^^^^^^^^^
2349  size_t index = normPathname.find(sep, 2);
2350  if (index == std::string::npos) {
2351  return std::pair<std::string, std::string>("", pathname);
2352  }
2353 
2354  size_t index2 = normPathname.find(sep, index + 1);
2355  // # a UNC path can't have two slashes in a row
2356  // # (after the initial two)
2357  if (index2 == index + 1) {
2358  return std::pair<std::string, std::string>("", pathname);
2359  }
2360 
2361  if (index2 == std::string::npos) {
2362  index2 = pathname.size();
2363  }
2364 
2365  return std::pair<std::string, std::string>(pathname.substr(0, index2), pathname.substr(index2));
2366  }
2367 
2368  if (normPathname[1] == ':') {
2369  return std::pair<std::string, std::string>(pathname.substr(0, 2), pathname.substr(2));
2370  }
2371  }
2372 
2373  return std::pair<std::string, std::string>("", pathname);
2374 #endif
2375 }
2376 
2425 std::vector<std::string> vpIoTools::splitChain(const std::string &chain, const std::string &sep)
2426 {
2427  size_t startIndex = 0;
2428 
2429  std::string chainToSplit = chain;
2430  std::vector<std::string> subChain;
2431  size_t sepIndex = chainToSplit.find(sep);
2432 
2433  while (sepIndex != std::string::npos) {
2434  std::string sub = chainToSplit.substr(startIndex, sepIndex);
2435  if (!sub.empty()) {
2436  subChain.push_back(sub);
2437  }
2438  chainToSplit = chainToSplit.substr(sepIndex + 1, chain.size() - 1);
2439 
2440  sepIndex = chainToSplit.find(sep);
2441  }
2442  if (!chainToSplit.empty()) {
2443  subChain.push_back(chainToSplit);
2444  }
2445 
2446  return subChain;
2447 }
2448 
2456 std::vector<std::string> vpIoTools::getDirFiles(const std::string &pathname)
2457 {
2458 
2459  if (!checkDirectory(pathname)) {
2460  throw(vpIoException(vpException::fatalError, "Directory %s doesn't exist'", pathname.c_str()));
2461  }
2462  std::string dirName = path(pathname);
2463 
2464 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
2465 
2466  std::vector<std::string> files;
2467  struct dirent **list = nullptr;
2468  int filesCount = scandir(dirName.c_str(), &list, nullptr, nullptr);
2469  if (filesCount == -1) {
2470  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
2471  }
2472  for (int i = 0; i < filesCount; ++i) {
2473  std::string fileName = list[i]->d_name;
2474  if ((fileName != ".") && (fileName != "..")) {
2475  files.push_back(fileName);
2476  }
2477  free(list[i]);
2478  }
2479  free(list);
2480  std::sort(files.begin(), files.end());
2481  return files;
2482 
2483 #elif defined(_WIN32)
2484 #if (!defined(WINRT))
2485 
2486  std::vector<std::string> files;
2487  std::string fileMask = dirName;
2488  fileMask.append("\\*");
2489  WIN32_FIND_DATA FindFileData;
2490  HANDLE hFind = FindFirstFile(fileMask.c_str(), &FindFileData);
2491  // Directory is empty
2492  if (HandleToLong(&hFind) == ERROR_FILE_NOT_FOUND) {
2493  return files;
2494  }
2495  if (hFind == INVALID_HANDLE_VALUE) {
2496  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
2497  }
2498  do {
2499  std::string fileName = FindFileData.cFileName;
2500  if (fileName != "." && fileName != "..") {
2501  files.push_back(fileName);
2502  }
2503  } while (FindNextFile(hFind, &FindFileData));
2504  FindClose(hFind);
2505  std::sort(files.begin(), files.end());
2506  return files;
2507 
2508 #else
2510  "Cannot read files of directory %s: not implemented on "
2511  "Universal Windows Platform",
2512  dirName.c_str()));
2513 #endif
2514 #endif
2515 }
2516 
2520 void vpIoTools::readBinaryValueLE(std::ifstream &file, int16_t &short_value)
2521 {
2522  file.read((char *)(&short_value), sizeof(short_value));
2523 
2524 #ifdef VISP_BIG_ENDIAN
2525  // Swap bytes order from little endian to big endian
2526  short_value = vpEndian::swap16bits((uint16_t)short_value);
2527 #endif
2528 }
2529 
2533 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint16_t &ushort_value)
2534 {
2535  file.read((char *)(&ushort_value), sizeof(ushort_value));
2536 
2537 #ifdef VISP_BIG_ENDIAN
2538  // Swap bytes order from little endian to big endian
2539  ushort_value = vpEndian::swap16bits(ushort_value);
2540 #endif
2541 }
2542 
2546 void vpIoTools::readBinaryValueLE(std::ifstream &file, int32_t &int_value)
2547 {
2548  file.read((char *)(&int_value), sizeof(int_value));
2549 
2550 #ifdef VISP_BIG_ENDIAN
2551  // Swap bytes order from little endian to big endian
2552  int_value = vpEndian::swap32bits((uint32_t)int_value);
2553 #endif
2554 }
2555 
2559 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint32_t &uint_value)
2560 {
2561  file.read((char *)(&uint_value), sizeof(uint_value));
2562 
2563 #ifdef VISP_BIG_ENDIAN
2564  // Swap bytes order from little endian to big endian
2565  uint_value = vpEndian::swap32bits(uint_value);
2566 #endif
2567 }
2568 
2572 void vpIoTools::readBinaryValueLE(std::ifstream &file, float &float_value)
2573 {
2574  file.read((char *)(&float_value), sizeof(float_value));
2575 
2576 #ifdef VISP_BIG_ENDIAN
2577  // Swap bytes order from little endian to big endian
2578  float_value = vpEndian::swapFloat(float_value);
2579 #endif
2580 }
2581 
2585 void vpIoTools::readBinaryValueLE(std::ifstream &file, double &double_value)
2586 {
2587  file.read((char *)(&double_value), sizeof(double_value));
2588 
2589 #ifdef VISP_BIG_ENDIAN
2590  // Swap bytes order from little endian to big endian
2591  double_value = vpEndian::swapDouble(double_value);
2592 #endif
2593 }
2594 
2598 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
2599 {
2600 #ifdef VISP_BIG_ENDIAN
2601  // Swap bytes order to little endian
2602  uint16_t swap_short = vpEndian::swap16bits((uint16_t)short_value);
2603  file.write((char *)(&swap_short), sizeof(swap_short));
2604 #else
2605  file.write((char *)(&short_value), sizeof(short_value));
2606 #endif
2607 }
2608 
2612 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint16_t ushort_value)
2613 {
2614 #ifdef VISP_BIG_ENDIAN
2615  // Swap bytes order to little endian
2616  uint16_t swap_ushort = vpEndian::swap16bits(ushort_value);
2617  file.write((char *)(&swap_ushort), sizeof(swap_ushort));
2618 #else
2619  file.write((char *)(&ushort_value), sizeof(ushort_value));
2620 #endif
2621 }
2622 
2626 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int32_t int_value)
2627 {
2628 #ifdef VISP_BIG_ENDIAN
2629  // Swap bytes order to little endian
2630  uint32_t swap_int = vpEndian::swap32bits((uint32_t)int_value);
2631  file.write((char *)(&swap_int), sizeof(swap_int));
2632 #else
2633  file.write((char *)(&int_value), sizeof(int_value));
2634 #endif
2635 }
2636 
2640 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint32_t uint_value)
2641 {
2642 #ifdef VISP_BIG_ENDIAN
2643  // Swap bytes order to little endian
2644  uint32_t swap_int = vpEndian::swap32bits(uint_value);
2645  file.write((char *)(&swap_int), sizeof(swap_int));
2646 #else
2647  file.write((char *)(&uint_value), sizeof(uint_value));
2648 #endif
2649 }
2650 
2654 void vpIoTools::writeBinaryValueLE(std::ofstream &file, float float_value)
2655 {
2656 #ifdef VISP_BIG_ENDIAN
2657  // Swap bytes order to little endian
2658  float swap_float = vpEndian::swapFloat(float_value);
2659  file.write((char *)(&swap_float), sizeof(swap_float));
2660 #else
2661  file.write((char *)(&float_value), sizeof(float_value));
2662 #endif
2663 }
2664 
2668 void vpIoTools::writeBinaryValueLE(std::ofstream &file, double double_value)
2669 {
2670 #ifdef VISP_BIG_ENDIAN
2671  // Swap bytes order to little endian
2672  double swap_double = vpEndian::swapDouble(double_value);
2673  file.write((char *)(&swap_double), sizeof(swap_double));
2674 #else
2675  file.write((char *)(&double_value), sizeof(double_value));
2676 #endif
2677 }
2678 
2679 bool vpIoTools::parseBoolean(std::string input)
2680 {
2681  std::transform(input.begin(), input.end(), input.begin(), ::tolower);
2682  std::istringstream is(input);
2683  bool b;
2684  // Parse string to boolean either in the textual representation
2685  // (True/False) or in numeric representation (1/0)
2686  is >> (input.size() > 1 ? std::boolalpha : std::noboolalpha) >> b;
2687  return b;
2688 }
2689 
2693 std::string vpIoTools::trim(std::string s) { return ltrim(rtrim(s)); }
unsigned int getCols() const
Definition: vpArray2D.h:327
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:352
unsigned int getRows() const
Definition: vpArray2D.h:337
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:152
static vpColor getColor(const unsigned int &i)
Definition: vpColor.h:307
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ notImplementedError
Not implemented.
Definition: vpException.h:81
@ fatalError
Fatal error.
Definition: vpException.h:84
Error that can be emitted by the vpIoTools class and its derivatives.
Definition: vpIoException.h:54
@ invalidDirectoryName
Directory name is invalid.
Definition: vpIoException.h:62
@ cantCreateDirectory
Unable to create a directory.
Definition: vpIoException.h:63
@ cantGetenv
Cannot get environment variable value.
Definition: vpIoException.h:65
static void getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
Definition: vpIoTools.cpp:789
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1832
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:2425
static std::vector< std::string > configVars
Definition: vpIoTools.h:585
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:1432
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:2153
static std::string toLowerCase(const std::string &input)
Return a lower-case version of the string input . Numbers and special characters stay the same.
Definition: vpIoTools.cpp:2111
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:1213
static bool readConfigVar(const std::string &var, float &value)
Definition: vpIoTools.cpp:1524
static void setBaseName(const std::string &s)
Definition: vpIoTools.cpp:641
static std::pair< std::string, std::string > splitDrive(const std::string &pathname)
Definition: vpIoTools.cpp:2280
static bool isSamePathname(const std::string &pathname1, const std::string &pathname2)
Definition: vpIoTools.cpp:2260
static std::string getTempPath()
Definition: vpIoTools.cpp:601
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:2236
static void setBaseDir(const std::string &dir)
Definition: vpIoTools.cpp:648
static std::string baseDir
Definition: vpIoTools.h:583
static bool loadConfigFile(const std::string &confFile)
Definition: vpIoTools.cpp:1475
static bool copy(const std::string &src, const std::string &dst)
Definition: vpIoTools.cpp:1255
static std::string trim(std::string s)
Definition: vpIoTools.cpp:2693
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
Definition: vpIoTools.cpp:2520
static void saveConfigFile(const bool &actuallySave=true)
Definition: vpIoTools.cpp:1810
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:832
static bool rename(const std::string &oldfilename, const std::string &newfilename)
Definition: vpIoTools.cpp:1412
static bool parseBoolean(std::string input)
Definition: vpIoTools.cpp:2679
static long getIndex(const std::string &filename, const std::string &format)
Definition: vpIoTools.cpp:2044
static std::string getUserName()
Definition: vpIoTools.cpp:725
static std::string getFullName()
Definition: vpIoTools.cpp:662
static void addNameElement(const std::string &strTrue, const bool &cond=true, const std::string &strFalse="")
Definition: vpIoTools.cpp:1747
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2195
static std::string getenv(const std::string &env)
Definition: vpIoTools.cpp:762
static const std::string & getBuildInformation()
Definition: vpIoTools.cpp:542
static std::string getBaseName()
Definition: vpIoTools.cpp:655
static std::string getFileExtension(const std::string &pathname, bool checkFile=false)
Definition: vpIoTools.cpp:1900
static std::string baseName
Definition: vpIoTools.h:582
static void createBaseNamePath(const bool &empty=false)
Definition: vpIoTools.cpp:1784
static std::vector< std::string > getDirFiles(const std::string &dirname)
Definition: vpIoTools.cpp:2456
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:981
static std::string configFile
Definition: vpIoTools.h:584
static std::vector< std::string > configValues
Definition: vpIoTools.h:586
static void writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
Definition: vpIoTools.cpp:2598
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:1348
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:2003
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:1135
static bool checkFifo(const std::string &filename)
Definition: vpIoTools.cpp:892
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:2086
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1981
static std::string toUpperCase(const std::string &input)
Return a upper-case version of the string input . Numbers and special characters stay the same.
Definition: vpIoTools.cpp:2132
static const char separator
Definition: vpIoTools.h:518
static void makeFifo(const std::string &dirname)
Definition: vpIoTools.cpp:1032
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:260
VISP_EXPORT char map_type(const std::type_info &t)
Definition: vpIoTools.cpp:135
VISP_EXPORT npz_t npz_load(std::string fname)
Definition: vpIoTools.cpp:342
VISP_EXPORT void parse_zip_footer(FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
Definition: vpIoTools.cpp:253
VISP_EXPORT void parse_npy_header(FILE *fp, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order)
Definition: vpIoTools.cpp:197
std::map< std::string, NpyArray > npz_t
Definition: vpIoTools.h:126
VISP_EXPORT NpyArray npy_load(std::string fname)
Definition: vpIoTools.cpp:470
VISP_EXPORT char BigEndianTest()
Definition: vpIoTools.cpp:129
VISP_EXPORT float swapFloat(float f)
Definition: vpEndian.cpp:65
VISP_EXPORT uint32_t swap32bits(uint32_t val)
Definition: vpEndian.cpp:55
VISP_EXPORT double swapDouble(double d)
Definition: vpEndian.cpp:84
VISP_EXPORT uint16_t swap16bits(uint16_t val)
Definition: vpEndian.cpp:49