Visual Servoing Platform  version 3.6.0 under development (2023-09-29)
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 *****************************************************************************/
35 
41 // At this point, to make scandir() working as expected on armv7 virtualized on a x86-64bit architecture
42 // (see github/workflow/other-arch-isolated.yml) we need to define _FILE_OFFSET_BITS=64. Otherwise
43 // testVideo.cpp will fail.
44 // Since adding here something like:
45 // #include <visp3/core/vpConfig.h>
46 // #ifdef VISP_DEFINE_FILE_OFFSET_BITS
47 // # define _FILE_OFFSET_BITS 64
48 // #endif
49 // where VISP_DEFINE_FILE_OFFSET_BITS is defined in vpConfig.h doesn't work (my explanation is that the define
50 // should be done before any other includes; in vpConfig.h there is cstdlib that is included), the other way
51 // that was retained is to add to vpIoTools.cpp COMPILE_DEFINTIONS _FILE_OFFSET_BITS=64 (see CMakeLists.txt)
52 
53 #include <algorithm>
54 #include <cctype>
55 #include <cmath>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <fstream>
59 #include <functional>
60 #include <limits>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <sys/stat.h>
65 #include <sys/types.h>
66 #include <visp3/core/vpDebug.h>
67 #include <visp3/core/vpEndian.h>
68 #include <visp3/core/vpIoException.h>
69 #include <visp3/core/vpIoTools.h>
70 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
71 #include <dirent.h>
72 #include <unistd.h>
73 #elif defined(_WIN32)
74 #include <direct.h>
75 #include <windows.h>
76 #endif
77 #if !defined(_WIN32)
78 #ifdef __ANDROID__
79 // Like IOS, wordexp.cpp is not defined for Android
80 #else
81 #include <wordexp.h>
82 #endif
83 #endif
84 
85 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
86 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IOS macro
87 #endif
88 
89 #ifndef PATH_MAX
90 #ifdef _MAX_PATH
91 #define PATH_MAX _MAX_PATH
92 #else
93 #define PATH_MAX 1024
94 #endif
95 #endif
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 std::string vpIoTools::baseName = "";
108 std::string vpIoTools::baseDir = "";
109 std::string vpIoTools::configFile = "";
110 std::vector<std::string> vpIoTools::configVars = std::vector<std::string>();
111 std::vector<std::string> vpIoTools::configValues = std::vector<std::string>();
112 
113 namespace
114 {
115 // The following code is not working on iOS since wordexp() is not available
116 // The function is not used on Android
117 #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
118 #if (TARGET_OS_IOS == 0) && !defined(__ANDROID__)
119 void replaceAll(std::string &str, const std::string &search, const std::string &replace)
120 {
121  size_t start_pos = 0;
122  while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
123  str.replace(start_pos, search.length(), replace);
124  start_pos += replace.length(); // Handles case where 'replace' is a
125  // substring of 'search'
126  }
127 }
128 #endif
129 #endif
130 
131 std::string &ltrim(std::string &s)
132 {
133 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
134  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) {
135  return !std::isspace(c);
136  }));
137 #else
138  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
139 #endif
140  return s;
141 }
142 
143 std::string &rtrim(std::string &s)
144 {
145 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
146  s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) {
147  return !std::isspace(c);
148  }).base(), s.end());
149 #else
150  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
151 #endif
152  return s;
153 }
154 } // namespace
155 
159 const std::string &vpIoTools::getBuildInformation()
160 {
161  static std::string build_info =
162 #include "version_string.inc"
163  ;
164  return build_info;
165 }
166 
219 {
220 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
221  std::string username;
222  vpIoTools::getUserName(username);
223  return "/tmp/" + username;
224 #elif defined(_WIN32) && !defined(WINRT)
225  // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file
226  // Gets the temp path env string (no guarantee it's a valid path).
227  TCHAR lpTempPathBuffer[MAX_PATH];
228  DWORD dwRetVal = GetTempPath(MAX_PATH /* length of the buffer */, lpTempPathBuffer /* buffer for path */);
229  if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
230  throw vpIoException(vpIoException::cantGetenv, "Error with GetTempPath() call!");
231  }
232  std::string temp_path(lpTempPathBuffer);
233  if (!temp_path.empty()) {
234  if (temp_path.back() == '\\') {
235  temp_path.resize(temp_path.size() - 1);
236  }
237  }
238  else {
239  temp_path = "C:\temp";
240  try {
241  vpIoTools::makeDirectory(temp_path);
242  }
243  catch (...) {
244  throw(vpException(vpException::fatalError, "Cannot set temp path to %s", temp_path.c_str()));
245  }
246  }
247  return temp_path;
248 #else
249  throw vpIoException(vpException::fatalError, "Not implemented on this platform!");
250 #endif
251 }
252 
258 void vpIoTools::setBaseName(const std::string &s) { baseName = s; }
259 
265 void vpIoTools::setBaseDir(const std::string &dir) { baseDir = dir + "/"; }
266 
272 std::string vpIoTools::getBaseName() { return baseName; }
273 
279 std::string vpIoTools::getFullName() { return baseDir + baseName; }
280 
294 void vpIoTools::getUserName(std::string &username)
295 {
296  // With MinGW, UNIX and _WIN32 are defined
297 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
298  // Get the user name.
299  char *_username = ::getenv("LOGNAME");
300  if (!_username) {
301  username = "unknown";
302  }
303  else {
304  username = _username;
305  }
306 #elif defined(_WIN32)
307 #if (!defined(WINRT))
308  unsigned int info_buffer_size = 1024;
309  TCHAR *infoBuf = new TCHAR[info_buffer_size];
310  DWORD bufCharCount = (DWORD)info_buffer_size;
311  // Get the user name.
312  if (!GetUserName(infoBuf, &bufCharCount)) {
313  username = "unknown";
314  }
315  else {
316  username = infoBuf;
317  }
318  delete[] infoBuf;
319 #else
320  // Universal platform
321  username = "unknown";
322 #endif
323 #else
324  username = "unknown";
325 #endif
326 }
327 
343 {
344  std::string username;
345  getUserName(username);
346  return username;
347 }
348 
379 std::string vpIoTools::getenv(const std::string &env)
380 {
381 #if defined(_WIN32) && defined(WINRT)
382  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value: not "
383  "implemented on Universal Windows Platform"));
384 #else
385  std::string value;
386  // Get the environment variable value.
387  char *_value = ::getenv(env.c_str());
388  if (!_value) {
389  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value"));
390  }
391  value = _value;
392 
393  return value;
394 #endif
395 }
396 
406 void vpIoTools::getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
407 {
408  if (version.size() == 0) {
409  major = 0;
410  minor = 0;
411  patch = 0;
412  }
413  else {
414  size_t major_pos = version.find('.');
415  std::string major_str = version.substr(0, major_pos);
416  major = static_cast<unsigned>(atoi(major_str.c_str()));
417 
418  if (major_pos != std::string::npos) {
419  size_t minor_pos = version.find('.', major_pos + 1);
420  std::string minor_str = version.substr(major_pos + 1, (minor_pos - (major_pos + 1)));
421  minor = static_cast<unsigned>(atoi(minor_str.c_str()));
422 
423  if (minor_pos != std::string::npos) {
424  std::string patch_str = version.substr(minor_pos + 1);
425  patch = static_cast<unsigned>(atoi(patch_str.c_str()));
426  }
427  else {
428  patch = 0;
429  }
430  }
431  else {
432  minor = 0;
433  patch = 0;
434  }
435  }
436 }
437 
449 bool vpIoTools::checkDirectory(const std::string &dirname)
450 {
451 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
452  struct stat stbuf;
453 #elif defined(_WIN32) && defined(__MINGW32__)
454  struct stat stbuf;
455 #elif defined(_WIN32)
456  struct _stat stbuf;
457 #endif
458 
459  if (dirname.empty()) {
460  return false;
461  }
462 
463  std::string _dirname = path(dirname);
464 
465  if (VP_STAT(_dirname.c_str(), &stbuf) != 0) {
466  std::cout << "DEBUG 1 _dirname: " << _dirname << " is not a dir" << std::endl;
467  // Test adding the separator if not already present
468  if (_dirname.at(_dirname.size() - 1) != separator) {
469  std::cout << "DEBUG 2 test if _dirname + separator: " << _dirname + separator << " is a dir ?" << std::endl;
470  if (VP_STAT((_dirname + separator).c_str(), &stbuf) != 0) {
471  std::cout << "DEBUG 2 _dirname + separator: " << _dirname + separator << " is not a dir" << std::endl;
472  return false;
473  }
474  }
475  // Test removing the separator if already present
476  if (_dirname.at(_dirname.size() - 1) == separator) {
477  std::cout << "DEBUG 2 test if _dirname - separator: " << _dirname.substr(0, _dirname.size() - 1) << " is a dir ?" << std::endl;
478  if (VP_STAT((_dirname.substr(0, _dirname.size() - 1)).c_str(), &stbuf) != 0) {
479  std::cout << "DEBUG 3 _dirname - separator: " << _dirname.substr(0, _dirname.size() - 1) << " is not a dir" << std::endl;
480  return false;
481  }
482  }
483  }
484 
485 #if defined(_WIN32) || (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
486  if ((stbuf.st_mode & S_IFDIR) == 0)
487 #endif
488  {
489  return false;
490  }
491 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
492  if ((stbuf.st_mode & S_IWUSR) == 0)
493 #elif defined(_WIN32)
494  if ((stbuf.st_mode & S_IWRITE) == 0)
495 #endif
496  {
497  return false;
498  }
499  return true;
500 }
501 
514 bool vpIoTools::checkFifo(const std::string &fifofilename)
515 {
516 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
517  struct stat stbuf;
518 
519  std::string _filename = path(fifofilename);
520  if (stat(_filename.c_str(), &stbuf) != 0) {
521  return false;
522  }
523  if ((stbuf.st_mode & S_IFIFO) == 0) {
524  return false;
525  }
526  if ((stbuf.st_mode & S_IRUSR) == 0)
527 
528  {
529  return false;
530  }
531  return true;
532 #elif defined(_WIN32)
533  (void)fifofilename;
534  throw(vpIoException(vpIoException::notImplementedError, "Fifo files are not supported on Windows platforms."));
535 #endif
536 }
537 
538 #ifndef DOXYGEN_SHOULD_SKIP_THIS
539 int vpIoTools::mkdir_p(const std::string &path, int mode)
540 {
541  errno = 0;
542  if (path.size() > PATH_MAX) {
543  errno = ENAMETOOLONG;
544  return -1;
545  }
546 
547  // Iterate over the string
548  std::string _path = path;
549  std::string _sub_path;
550  for (size_t pos = 0; (pos = _path.find(vpIoTools::separator)) != std::string::npos;) {
551  _sub_path += _path.substr(0, pos + 1);
552  // Continue if sub_path = separator
553  if (pos == 0) {
554  _path.erase(0, pos + 1);
555  continue;
556  }
557 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
558  if (mkdir(_sub_path.c_str(), static_cast<mode_t>(mode)) != 0)
559 #elif defined(_WIN32)
560  (void)mode; // var not used
561  if (!checkDirectory(_sub_path) && _mkdir(_sub_path.c_str()) != 0)
562 #endif
563  {
564  if (errno != EEXIST) {
565  return -1;
566  }
567  }
568  _path.erase(0, pos + 1);
569  }
570 
571  if (!_path.empty()) {
572  _sub_path += _path;
573 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
574  if (mkdir(_sub_path.c_str(), static_cast<mode_t>(mode)) != 0)
575 #elif defined(_WIN32)
576 
577  if (_mkdir(_sub_path.c_str()) != 0)
578 #endif
579  {
580  if (errno != EEXIST) {
581  return -1;
582  }
583  }
584  }
585 
586  return 0;
587 }
588 
589 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
590 
603 void vpIoTools::makeDirectory(const std::string &dirname)
604 {
605 #if ((!defined(__unix__) && !defined(__unix) && (!defined(__APPLE__) || !defined(__MACH__)))) && !defined(_WIN32)
606  std::cerr << "Unsupported platform for vpIoTools::makeDirectory()!" << std::endl;
607  return;
608 #endif
609 
610 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
611  struct stat stbuf;
612 #elif defined(_WIN32) && defined(__MINGW32__)
613  struct stat stbuf;
614 #elif defined(_WIN32)
615  struct _stat stbuf;
616 #endif
617 
618  if (dirname.empty()) {
619  throw(vpIoException(vpIoException::invalidDirectoryName, "invalid directory name"));
620  }
621 
622  std::string _dirname = path(dirname);
623 
624 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
625  if (stat(_dirname.c_str(), &stbuf) != 0)
626 #elif defined(_WIN32) && defined(__MINGW32__)
627  if (stat(_dirname.c_str(), &stbuf) != 0)
628 #elif defined(_WIN32)
629  if (_stat(_dirname.c_str(), &stbuf) != 0)
630 #endif
631  {
632  if (vpIoTools::mkdir_p(_dirname, 0755) != 0) {
633  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
634  }
635  }
636 
637  if (checkDirectory(dirname) == false) {
638  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
639  }
640 }
641 
654 void vpIoTools::makeFifo(const std::string &fifoname)
655 {
656 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
657 
658  // If dirname is a directory, we throw an error
659  if (vpIoTools::checkDirectory(fifoname)) {
661  "Unable to create fifo file. '%s' is an existing directory.", fifoname.c_str()));
662  }
663 
664  // If dirname refers to an already existing file, we throw an error
665  else if (vpIoTools::checkFilename(fifoname)) {
666  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. File already exists.",
667  fifoname.c_str()));
668  // If dirname refers to an already existing fifo, we throw an error
669  }
670  else if (vpIoTools::checkFifo(fifoname)) {
671  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. Fifo already exists.",
672  fifoname.c_str()));
673  }
674 
675  else if (mkfifo(fifoname.c_str(), 0666) < 0) {
676  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo file '%s'.", fifoname.c_str()));
677  }
678 #elif defined(_WIN32)
679  (void)fifoname;
680  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo on Windows platforms."));
681 #endif
682 }
683 
684 #if defined(_WIN32) && !defined(WINRT)
685 std::string getUuid()
686 {
687  UUID uuid;
688  if (UuidCreate(&uuid) != RPC_S_OK) {
689  throw(vpIoException(vpIoException::fatalError, "UuidCreate() failed!"));
690  }
691 
692  RPC_CSTR stringUuid;
693  if (UuidToString(&uuid, &stringUuid) != RPC_S_OK) {
694  throw(vpIoException(vpIoException::fatalError, "UuidToString() failed!"));
695  }
696 
697  return reinterpret_cast<char *>(stringUuid);
698 }
699 #endif
700 
757 std::string vpIoTools::makeTempDirectory(const std::string &dirname)
758 {
759 #if defined(WINRT) || !defined(_WIN32) && !(defined(__unix__) || defined(__unix) || \
760  (defined(__APPLE__) && defined(__MACH__))) // not UNIX and not Windows
761  throw(vpIoException(vpIoException::cantCreateDirectory, "makeTempDirectory() is not supported on this platform!"));
762 #endif
763 
764  std::string dirname_cpy = std::string(dirname);
765  std::string correctEnding = "XXXXXX";
766 
767  // If dirname is an unexisting directory, it should end with XXXXXX in order to create a temp directory
768  if (!vpIoTools::checkDirectory(dirname_cpy)) {
769 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
770  // Check if dirname ends with XXXXXX
771  if (dirname_cpy.rfind(correctEnding) == std::string::npos) {
772  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
773  dirname_cpy = dirname_cpy + "/";
774  }
775  try {
776  vpIoTools::makeDirectory(dirname_cpy);
777  }
778  catch (const vpException &e) {
779  throw e;
780  }
781 
782  dirname_cpy = dirname_cpy + "XXXXXX";
783  }
784 
785 #elif defined(_WIN32) && !defined(WINRT)
786  // Remove XXXXXX
787  dirname_cpy = dirname_cpy.substr(0, dirname_cpy.rfind(correctEnding));
788  // Append UUID
789  dirname_cpy = dirname_cpy + getUuid();
790 #endif
791 
792  }
793  else {
794  // If dirname is an existing directory, we create a temp directory inside
795 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
796  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
797  dirname_cpy = dirname_cpy + "/";
798  }
799  dirname_cpy = dirname_cpy + "XXXXXX";
800 #elif defined(_WIN32) && !defined(WINRT)
801  dirname_cpy = createFilePath(dirname_cpy, getUuid());
802 #endif
803  }
804 
805 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
806  char *dirname_char = new char[dirname_cpy.length() + 1];
807  strcpy(dirname_char, dirname_cpy.c_str());
808 
809  char *computedDirname = mkdtemp(dirname_char);
810 
811  if (!computedDirname) {
812  delete[] dirname_char;
813  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'.", dirname_cpy.c_str()));
814  }
815 
816  std::string res(computedDirname);
817  delete[] dirname_char;
818  return res;
819 #elif defined(_WIN32) && !defined(WINRT)
820  makeDirectory(dirname_cpy);
821  return dirname_cpy;
822 #endif
823 }
824 
835 bool vpIoTools::checkFilename(const std::string &filename)
836 {
837 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
838  struct stat stbuf;
839 #elif defined(_WIN32)
840  struct _stat stbuf;
841 #endif
842 
843  if (filename.empty()) {
844  return false;
845  }
846 
847  std::string _filename = path(filename);
848 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
849  if (stat(_filename.c_str(), &stbuf) != 0)
850 #elif defined(_WIN32)
851  if (_stat(_filename.c_str(), &stbuf) != 0)
852 #endif
853  {
854  return false;
855  }
856  if ((stbuf.st_mode & S_IFREG) == 0) {
857  return false;
858  }
859 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
860  if ((stbuf.st_mode & S_IRUSR) == 0)
861 #elif defined(_WIN32)
862  if ((stbuf.st_mode & S_IREAD) == 0)
863 #endif
864  {
865  return false;
866  }
867  return true;
868 }
869 
877 bool vpIoTools::copy(const std::string &src, const std::string &dst)
878 {
879  // Check if we have to consider a file or a directory
880  if (vpIoTools::checkFilename(src)) {
881  // std::cout << "copy file: " << src << " in " << dst << std::endl;
882 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
883 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
884  // wordexp() is not available
885  std::stringstream cmd;
886  cmd << "cp -p ";
887  cmd << src;
888  cmd << " ";
889  cmd << dst;
890  int ret = system(cmd.str().c_str());
891  if (ret) {
892  }; // to avoid a warning
893  // std::cout << cmd << " return value: " << ret << std::endl;
894  return true;
895 #else
896  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
897  dst.c_str()));
898 #endif
899 #elif defined(_WIN32)
900 #if (!defined(WINRT))
901  std::stringstream cmd;
902  cmd << "copy ";
903  cmd << vpIoTools::path(src);
904  cmd << " ";
905  cmd << vpIoTools::path(dst);
906  int ret = system(cmd.str().c_str());
907  if (ret) {
908  }; // to avoid a warning
909  // std::cout << cmd << " return value: " << ret << std::endl;
910  return true;
911 #else
912  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
913  src.c_str(), dst.c_str()));
914 #endif
915 #endif
916  }
917  else if (vpIoTools::checkDirectory(src)) {
918  // std::cout << "copy directory: " << src << " in " << dst << std::endl;
919 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
920 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
921  // wordexp() is not available
922  std::stringstream cmd;
923  cmd << "cp -p ";
924  cmd << src;
925  cmd << " ";
926  cmd << dst;
927  int ret = system(cmd.str().c_str());
928  if (ret) {
929  }; // to avoid a warning
930  // std::cout << cmd << " return value: " << ret << std::endl;
931  return true;
932 #else
933  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
934  dst.c_str()));
935 #endif
936 #elif defined(_WIN32)
937 #if (!defined(WINRT))
938  std::stringstream cmd;
939  cmd << "copy ";
940  cmd << vpIoTools::path(src);
941  cmd << " ";
942  cmd << vpIoTools::path(dst);
943  int ret = system(cmd.str().c_str());
944  if (ret) {
945  }; // to avoid a warning
946  // std::cout << cmd << " return value: " << ret << std::endl;
947  return true;
948 #else
949  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
950  src.c_str(), dst.c_str()));
951 #endif
952 #endif
953  }
954  else {
955  std::cout << "Cannot copy: " << src << " in " << dst << std::endl;
956  return false;
957  }
958 }
959 
970 bool vpIoTools::remove(const std::string &file_or_dir)
971 {
972  // Check if we have to consider a file or a directory
973  if (vpIoTools::checkFilename(file_or_dir)
974 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
975  || vpIoTools::checkFifo(std::string(file_or_dir))
976 #endif
977  ) {
978  // std::cout << "remove file: " << file_or_dir << std::endl;
979  if (::remove(file_or_dir.c_str()) != 0)
980  return false;
981  else
982  return true;
983  }
984  else if (vpIoTools::checkDirectory(file_or_dir)) {
985  // std::cout << "remove directory: " << file_or_dir << std::endl;
986 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
987 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
988  // wordexp() is not available
989  std::stringstream cmd;
990  cmd << "rm -rf \"";
991  cmd << file_or_dir;
992  cmd << "\"";
993  int ret = system(cmd.str().c_str());
994  if (ret) {
995  }; // to avoid a warning
996  // std::cout << cmd << " return value: " << ret << std::endl;
997  return true;
998 #else
999  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on iOS Platform",
1000  file_or_dir.c_str()));
1001 #endif
1002 #elif defined(_WIN32)
1003 #if (!defined(WINRT))
1004  std::stringstream cmd;
1005  cmd << "rmdir /S /Q ";
1006  cmd << vpIoTools::path(file_or_dir);
1007  cmd << "\"";
1008  int ret = system(cmd.str().c_str());
1009  if (ret) {
1010  }; // to avoid a warning
1011  // std::cout << cmd << " return value: " << ret << std::endl;
1012  return true;
1013 #else
1014  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on Universal Windows Platform",
1015  file_or_dir.c_str()));
1016 #endif
1017 #endif
1018  }
1019  else {
1020  std::cout << "Cannot remove: " << file_or_dir << std::endl;
1021  return false;
1022  }
1023 }
1024 
1034 bool vpIoTools::rename(const std::string &oldfilename, const std::string &newfilename)
1035 {
1036  if (::rename(oldfilename.c_str(), newfilename.c_str()) != 0)
1037  return false;
1038  else
1039  return true;
1040 }
1041 
1052 std::string vpIoTools::path(const std::string &pathname)
1053 {
1054  std::string path(pathname);
1055 
1056 #if defined(_WIN32)
1057  for (unsigned int i = 0; i < path.length(); i++)
1058  if (path[i] == '/')
1059  path[i] = '\\';
1060 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
1061  for (unsigned int i = 0; i < path.length(); i++)
1062  if (path[i] == '\\')
1063  path[i] = '/';
1064 #if TARGET_OS_IOS == 0 // The following code is not working on iOS and android since
1065  // wordexp() is not available
1066 #ifdef __ANDROID__
1067 // Do nothing
1068 #else
1069  wordexp_t exp_result;
1070 
1071  // escape quote character
1072  replaceAll(path, "'", "'\\''");
1073  // add quotes to handle special characters like parentheses and spaces
1074  wordexp(std::string("'" + path + "'").c_str(), &exp_result, 0);
1075  path = exp_result.we_wordc == 1 ? exp_result.we_wordv[0] : "";
1076  wordfree(&exp_result);
1077 #endif
1078 #endif
1079 #endif
1080 
1081  return path;
1082 }
1083 
1092 bool vpIoTools::loadConfigFile(const std::string &confFile)
1093 {
1094  configFile = path(confFile);
1095  configVars.clear();
1096  configValues.clear();
1097  std::ifstream confContent(configFile.c_str(), std::ios::in);
1098 
1099  if (confContent.is_open()) {
1100  std::string line, var, val;
1101  long unsigned int k;
1102  int c;
1103  std::string stop[3] = { " ", "\t", "#" };
1104  while (std::getline(confContent, line)) {
1105  if ((line.compare(0, 1, "#") != 0) && (line.size() > 2)) {
1106  try {
1107  // name of the variable
1108  k = static_cast<unsigned long>(line.find(" "));
1109  var = line.substr(0, k);
1110  // look for the end of the actual value
1111  c = 200;
1112  for (unsigned i = 0; i < 3; ++i)
1113  c = vpMath::minimum(c,
1114  static_cast<int>(line.find(stop[i], static_cast<size_t>(k) + static_cast<size_t>(1))));
1115  if (c == -1)
1116  c = static_cast<int>(line.size());
1117  long unsigned int c_ = static_cast<long unsigned int>(c);
1118  val = line.substr(static_cast<size_t>(k) + static_cast<size_t>(1),
1119  static_cast<size_t>(c_) - static_cast<size_t>(k) - static_cast<size_t>(1));
1120  configVars.push_back(var);
1121  configValues.push_back(val);
1122  }
1123  catch (...) {
1124  }
1125  }
1126  }
1127  confContent.close();
1128  }
1129  else {
1130  return false;
1131  }
1132  return true;
1133 }
1134 
1143 bool vpIoTools::readConfigVar(const std::string &var, float &value)
1144 {
1145  bool found = false;
1146  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1147  if (configVars[k] == var) {
1148  if (configValues[k].compare("PI") == 0)
1149  value = static_cast<float>(M_PI);
1150  else if (configValues[k].compare("PI/2") == 0)
1151  value = static_cast<float>(M_PI / 2.0);
1152  else if (configValues[k].compare("-PI/2") == 0)
1153  value = static_cast<float>(-M_PI / 2.0);
1154  else
1155  value = static_cast<float>(atof(configValues[k].c_str()));
1156  found = true;
1157  }
1158  }
1159  if (found == false)
1160  std::cout << var << " not found in config file" << std::endl;
1161  return found;
1162 }
1171 bool vpIoTools::readConfigVar(const std::string &var, double &value)
1172 {
1173  bool found = false;
1174  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1175  if (configVars[k] == var) {
1176  if (configValues[k].compare("PI") == 0)
1177  value = M_PI;
1178  else if (configValues[k].compare("PI/2") == 0)
1179  value = M_PI / 2;
1180  else if (configValues[k].compare("-PI/2") == 0)
1181  value = -M_PI / 2;
1182  else
1183  value = atof(configValues[k].c_str());
1184  found = true;
1185  }
1186  }
1187  if (found == false)
1188  std::cout << var << " not found in config file" << std::endl;
1189  return found;
1190 }
1191 
1200 bool vpIoTools::readConfigVar(const std::string &var, int &value)
1201 {
1202  bool found = false;
1203  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1204  if (configVars[k] == var) {
1205  value = atoi(configValues[k].c_str());
1206  found = true;
1207  }
1208  }
1209  if (found == false)
1210  std::cout << var << " not found in config file" << std::endl;
1211  return found;
1212 }
1213 
1222 bool vpIoTools::readConfigVar(const std::string &var, unsigned int &value)
1223 {
1224  int v = 0;
1225  bool found = readConfigVar(var, v);
1226  value = static_cast<unsigned int>(v);
1227  return found;
1228 }
1229 
1238 bool vpIoTools::readConfigVar(const std::string &var, bool &value)
1239 {
1240  int v = 0;
1241  bool found = readConfigVar(var, v);
1242  value = (v != 0);
1243  return found;
1244 }
1245 
1254 bool vpIoTools::readConfigVar(const std::string &var, vpColor &value)
1255 {
1256  unsigned int v = 0;
1257  bool found = readConfigVar(var, v);
1258  value = vpColor::getColor(v);
1259  return found;
1260 }
1261 
1270 bool vpIoTools::readConfigVar(const std::string &var, std::string &value)
1271 {
1272  bool found = false;
1273  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1274  if (configVars[k] == var) {
1275  value = configValues[k];
1276  found = true;
1277  }
1278  }
1279  if (found == false)
1280  std::cout << var << " not found in config file" << std::endl;
1281  return found;
1282 }
1283 
1297 bool vpIoTools::readConfigVar(const std::string &var, vpArray2D<double> &value, const unsigned int &nCols,
1298  const unsigned int &nRows)
1299 {
1300  bool found = false;
1301  std::string nb;
1302  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1303  if (configVars[k] == var) {
1304  found = true;
1305  // resize or not
1306  if (nCols != 0 && nRows != 0)
1307  value.resize(nRows, nCols);
1308  size_t ind = 0, ind2;
1309  for (unsigned int i = 0; i < value.getRows(); ++i)
1310  for (unsigned int j = 0; j < value.getCols(); ++j) {
1311  ind2 = configValues[k].find(",", ind);
1312  nb = configValues[k].substr(ind, ind2 - ind);
1313  if (nb.compare("PI") == 0)
1314  value[i][j] = M_PI;
1315  else if (nb.compare("PI/2") == 0)
1316  value[i][j] = M_PI / 2;
1317  else if (nb.compare("-PI/2") == 0)
1318  value[i][j] = -M_PI / 2;
1319  else
1320  value[i][j] = atof(nb.c_str());
1321  ind = ind2 + 1;
1322  }
1323  }
1324  }
1325  if (found == false)
1326  std::cout << var << " not found in config file" << std::endl;
1327  return found;
1328 }
1329 
1330 // construct experiment filename & path
1331 
1340 void vpIoTools::addNameElement(const std::string &strTrue, const bool &cond, const std::string &strFalse)
1341 {
1342  if (cond)
1343  baseName += "_" + strTrue;
1344  else if (strFalse != "")
1345  baseName += "_" + strFalse;
1346 }
1347 
1356 void vpIoTools::addNameElement(const std::string &strTrue, const double &val)
1357 {
1358  // if(val != 0.)
1359  if (std::fabs(val) < std::numeric_limits<double>::epsilon()) {
1360  std::stringstream valS;
1361  valS.precision(4);
1362  valS << val;
1363  baseName += "_" + strTrue + valS.str();
1364  }
1365 }
1366 
1375 void vpIoTools::createBaseNamePath(const bool &empty)
1376 {
1377  if (vpIoTools::checkDirectory(baseDir + baseName) == false) {
1379  std::cout << "creating directory " + baseDir + baseName << std::endl;
1380  }
1381  else {
1382  if (empty) {
1383  std::cout << "emptying directory " + baseDir + baseName << std::endl;
1385  }
1386  }
1387 }
1388 
1395 void vpIoTools::saveConfigFile(const bool &actuallySave)
1396 {
1397  if (actuallySave) {
1398  std::string dest = baseDir + "/" + baseName + "_config.txt";
1399  // file copy
1400  vpIoTools::copy(configFile, dest);
1401  }
1402 }
1403 
1418 {
1419  std::string data_path;
1420  std::string file_to_test("mbt/cube.cao");
1421  std::string filename;
1422  // Test if VISP_INPUT_IMAGE_PATH env var is set
1423  try {
1424  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH");
1425  filename = data_path + "/" + file_to_test;
1426  if (vpIoTools::checkFilename(filename))
1427  return data_path;
1428  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/ViSP-images";
1429  filename = data_path + "/" + file_to_test;
1430  if (vpIoTools::checkFilename(filename))
1431  return data_path;
1432  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/visp-images";
1433  filename = data_path + "/" + file_to_test;
1434  if (vpIoTools::checkFilename(filename))
1435  return data_path;
1436  }
1437  catch (...) {
1438  }
1439 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1440  // Test if visp-images-data package is installed (Ubuntu and Debian)
1441  data_path = "/usr/share/visp-images-data/ViSP-images";
1442  filename = data_path + "/" + file_to_test;
1443  if (vpIoTools::checkFilename(filename))
1444  return data_path;
1445  data_path = "/usr/share/visp-images-data/visp-images";
1446  filename = data_path + "/" + file_to_test;
1447  if (vpIoTools::checkFilename(filename))
1448  return data_path;
1449 #endif
1450  data_path = "";
1451  return data_path;
1452 }
1453 
1483 std::string vpIoTools::getFileExtension(const std::string &pathname, bool checkFile)
1484 {
1485  if (checkFile && (vpIoTools::checkDirectory(pathname) || !vpIoTools::checkFilename(pathname))) {
1486  return "";
1487  }
1488 
1489 #if defined(_WIN32)
1490  std::string sep = "\\";
1491  std::string altsep = "/";
1492  std::string extsep = ".";
1493 #else
1494  // On Unix, or on the Mac
1495  std::string sep = "/";
1496  std::string altsep = "";
1497  std::string extsep = ".";
1498 #endif
1499 
1500  // Python 2.7.8 module.
1501  // # Split a path in root and extension.
1502  // # The extension is everything starting at the last dot in the last
1503  // # pathname component; the root is everything before that.
1504  // # It is always true that root + ext == p.
1505  //
1506  // # Generic implementation of splitext, to be parametrized with
1507  // # the separators
1508  // def _splitext(p, sep, altsep, extsep):
1509  // """Split the extension from a pathname.
1510  //
1511  // Extension is everything from the last dot to the end, ignoring
1512  // leading dots. Returns "(root, ext)"; ext may be empty."""
1513  //
1514  // sepIndex = p.rfind(sep)
1515  // if altsep:
1516  // altsepIndex = p.rfind(altsep)
1517  // sepIndex = max(sepIndex, altsepIndex)
1518  //
1519  // dotIndex = p.rfind(extsep)
1520  // if dotIndex > sepIndex:
1521  // # skip all leading dots
1522  // filenameIndex = sepIndex + 1
1523  // while filenameIndex < dotIndex:
1524  // if p[filenameIndex] != extsep:
1525  // return p[:dotIndex], p[dotIndex:]
1526  // filenameIndex += 1
1527  //
1528  // return p, ''
1529 
1530  int sepIndex = static_cast<int>(pathname.rfind(sep));
1531  if (!altsep.empty()) {
1532  int altsepIndex = static_cast<int>(pathname.rfind(altsep));
1533  sepIndex = ((std::max))(sepIndex, altsepIndex);
1534  }
1535 
1536  size_t dotIndex = pathname.rfind(extsep);
1537  if (dotIndex != std::string::npos) {
1538  // The extsep character exists
1539  size_t npos = std::string::npos;
1540  if ((sepIndex != static_cast<int>(npos) && static_cast<int>(dotIndex) > sepIndex) ||
1541  sepIndex == static_cast<int>(npos)) {
1542  if (sepIndex == static_cast<int>(npos)) {
1543  sepIndex = 0;
1544  }
1545  size_t filenameIndex = static_cast<size_t>(sepIndex) + static_cast<size_t>(1);
1546 
1547  while (filenameIndex < dotIndex) {
1548  if (pathname.compare(filenameIndex, 1, extsep) != 0) {
1549  return pathname.substr(dotIndex);
1550  }
1551  filenameIndex++;
1552  }
1553  }
1554  }
1555 
1556  return "";
1557 }
1558 
1564 std::string vpIoTools::getName(const std::string &pathname)
1565 {
1566  if (pathname.size() > 0) {
1567  std::string convertedPathname = vpIoTools::path(pathname);
1568 
1569  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1570  if (index != std::string::npos) {
1571  return convertedPathname.substr(index + 1);
1572  }
1573 
1574  return convertedPathname;
1575  }
1576 
1577  return "";
1578 }
1579 
1586 std::string vpIoTools::getNameWE(const std::string &pathname)
1587 {
1588  std::string name = vpIoTools::getName(pathname);
1589  size_t found = name.find_last_of(".");
1590  std::string name_we = name.substr(0, found);
1591  return name_we;
1592 }
1593 
1627 long vpIoTools::getIndex(const std::string &filename, const std::string &format)
1628 {
1629  size_t indexBegin = format.find_last_of('%');
1630  size_t indexEnd = format.find_first_of('d', indexBegin);
1631  size_t suffixLength = format.length() - indexEnd - 1;
1632  // Extracting index
1633  if (filename.length() <= suffixLength + indexBegin) {
1634  return -1;
1635  }
1636  size_t indexLength = filename.length() - suffixLength - indexBegin;
1637  std::string indexSubstr = filename.substr(indexBegin, indexLength);
1638  std::istringstream ss(indexSubstr);
1639  long index = 0;
1640  ss >> index;
1641  if (ss.fail() || index < 0 || !ss.eof()) {
1642  return -1;
1643  }
1644 
1645  // Checking that format with inserted index equals filename
1646  char nameByFormat[FILENAME_MAX];
1647  snprintf(nameByFormat, FILENAME_MAX, format.c_str(), index);
1648  if (std::string(nameByFormat) != filename) {
1649  return -1;
1650  }
1651  return index;
1652 }
1653 
1669 std::string vpIoTools::getParent(const std::string &pathname)
1670 {
1671  if (pathname.size() > 0) {
1672  std::string convertedPathname = vpIoTools::path(pathname);
1673 
1674  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1675  if (index != std::string::npos) {
1676  return convertedPathname.substr(0, index);
1677  }
1678 
1679  return ".";
1680  }
1681  else {
1682  return "";
1683  }
1684 }
1685 
1694 std::string vpIoTools::toLowerCase(const std::string &input)
1695 {
1696  std::string out;
1697 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
1698  for (size_t i = 0; i < input.size(); i++) {
1699  out += std::tolower(input[i]);
1700  }
1701 #else
1702  for (std::string::const_iterator it = input.cbegin(); it != input.cend(); it++) {
1703  out += std::tolower(*it);
1704  }
1705 #endif
1706  return out;
1707 }
1708 
1717 std::string vpIoTools::toUpperCase(const std::string &input)
1718 {
1719  std::string out;
1720 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
1721  for (size_t i = 0; i < input.size(); i++) {
1722  out += std::toupper(input[i]);
1723  }
1724 #else
1725  for (std::string::const_iterator it = input.cbegin(); it != input.cend(); it++) {
1726  out += std::toupper(*it);
1727  }
1728 #endif
1729  return out;
1730 }
1731 
1740 std::string vpIoTools::getAbsolutePathname(const std::string &pathname)
1741 {
1742 
1743 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1744  std::string real_path_str = pathname;
1745  char *real_path = realpath(pathname.c_str(), NULL);
1746 
1747  if (real_path) {
1748  real_path_str = real_path;
1749  free(real_path);
1750  }
1751  return real_path_str;
1752 #elif defined(_WIN32)
1753 #if (!defined(WINRT))
1754  std::string real_path_str = pathname;
1755  DWORD retval = 0;
1756  TCHAR buffer[4096] = TEXT("");
1757 
1758  retval = GetFullPathName(pathname.c_str(), 4096, buffer, 0);
1759  if (retval != 0) {
1760  real_path_str = buffer;
1761  }
1762  return real_path_str;
1763 #else
1765  "Cannot get absolute path of %s: not implemented on "
1766  "Universal Windows Platform",
1767  pathname.c_str()));
1768 #endif
1769 #endif
1770 }
1771 
1782 std::string vpIoTools::createFilePath(const std::string &parent, const std::string &child)
1783 {
1784  if (child.size() == 0 && parent.size() == 0) {
1785  return "";
1786  }
1787 
1788  if (child.size() == 0) {
1789  return vpIoTools::path(parent);
1790  }
1791 
1792  if (parent.size() == 0) {
1793  return vpIoTools::path(child);
1794  }
1795 
1796  std::string convertedParent = vpIoTools::path(parent);
1797  std::string convertedChild = vpIoTools::path(child);
1798 
1799  std::stringstream ss;
1800  ss << vpIoTools::separator;
1801  std::string stringSeparator;
1802  ss >> stringSeparator;
1803 
1804  std::string lastConvertedParentChar = convertedParent.substr(convertedParent.size() - 1);
1805  std::string firstConvertedChildChar = convertedChild.substr(0, 1);
1806 
1807  if (lastConvertedParentChar == stringSeparator) {
1808  convertedParent = convertedParent.substr(0, convertedParent.size() - 1);
1809  }
1810 
1811  if (firstConvertedChildChar == stringSeparator) {
1812  convertedChild = convertedChild.substr(1);
1813  }
1814 
1815  return std::string(convertedParent + vpIoTools::separator + convertedChild);
1816 }
1817 
1823 bool vpIoTools::isAbsolutePathname(const std::string &pathname)
1824 {
1825  // # Inspired by the Python 2.7.8 module.
1826  // # Return whether a path is absolute.
1827  // # Trivial in Posix, harder on the Mac or MS-DOS.
1828  // # For DOS it is absolute if it starts with a slash or backslash (current
1829  // # volume), or if a pathname after the volume letter and colon / UNC
1830  // resource # starts with a slash or backslash.
1831  //
1832  // def isabs(s):
1833  // """Test whether a path is absolute"""
1834  // s = splitdrive(s)[1]
1835  // return s != '' and s[:1] in '/\\'
1836  std::string path = splitDrive(pathname).second;
1837  return path.size() > 0 && (path.substr(0, 1) == "/" || path.substr(0, 1) == "\\");
1838 }
1839 
1847 bool vpIoTools::isSamePathname(const std::string &pathname1, const std::string &pathname2)
1848 {
1849  // Normalize path
1850  std::string path1_normalize = vpIoTools::path(pathname1);
1851  std::string path2_normalize = vpIoTools::path(pathname2);
1852 
1853  // Get absolute path
1854  path1_normalize = vpIoTools::getAbsolutePathname(path1_normalize);
1855  path2_normalize = vpIoTools::getAbsolutePathname(path2_normalize);
1856 
1857  return (path1_normalize == path2_normalize);
1858 }
1859 
1867 std::pair<std::string, std::string> vpIoTools::splitDrive(const std::string &pathname)
1868 {
1869  // # Split a path in a drive specification (a drive letter followed by a
1870  // # colon) and the path specification.
1871  // # It is always true that drivespec + pathspec == p
1872  // def splitdrive(p):
1873  // """Split a pathname into drive/UNC sharepoint and relative path
1874  // specifiers. Returns a 2-tuple (drive_or_unc, path); either part may be
1875  // empty.
1876  //
1877  // If you assign
1878  // result = splitdrive(p)
1879  // It is always true that:
1880  // result[0] + result[1] == p
1881  //
1882  // If the path contained a drive letter, drive_or_unc will contain
1883  // everything up to and including the colon. e.g. splitdrive("c:/dir")
1884  // returns ("c:", "/dir")
1885  //
1886  // If the path contained a UNC path, the drive_or_unc will contain the host
1887  // name and share up to but not including the fourth directory separator
1888  // character. e.g. splitdrive("//host/computer/dir") returns
1889  // ("//host/computer", "/dir")
1890  //
1891  // Paths cannot contain both a drive letter and a UNC path.
1892  //
1893  // """
1894  // if len(p) > 1:
1895  // normp = p.replace(altsep, sep)
1896  // if (normp[0:2] == sep*2) and (normp[2] != sep):
1897  // # is a UNC path:
1898  // # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1899  // # \\machine\mountpoint\directory\etc\...
1900  // # directory ^^^^^^^^^^^^^^^
1901  // index = normp.find(sep, 2)
1902  // if index == -1:
1903  // return '', p
1904  // index2 = normp.find(sep, index + 1)
1905  // # a UNC path can't have two slashes in a row
1906  // # (after the initial two)
1907  // if index2 == index + 1:
1908  // return '', p
1909  // if index2 == -1:
1910  // index2 = len(p)
1911  // return p[:index2], p[index2:]
1912  // if normp[1] == ':':
1913  // return p[:2], p[2:]
1914  // return '', p
1915 
1916  // On Unix, the drive is always empty.
1917  // On the Mac, the drive is always empty (don't use the volume name -- it
1918  // doesn't have the same syntactic and semantic oddities as DOS drive
1919  // letters, such as there being a separate current directory per drive).
1920 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
1921  return std::pair<std::string, std::string>("", pathname);
1922 #else
1923  const std::string sep = "\\";
1924  const std::string sepsep = "\\\\";
1925  const std::string altsep = "/";
1926 
1927  if (pathname.size() > 1) {
1928  std::string normPathname = pathname;
1929  std::replace(normPathname.begin(), normPathname.end(), *altsep.c_str(), *sep.c_str());
1930 
1931  if (normPathname.substr(0, 2) == sepsep && normPathname.substr(2, 1) != sep) {
1932  // is a UNC path:
1933  // vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1934  // \\machine\mountpoint\directory\etc\...
1935  // directory ^^^^^^^^^^^^^^^
1936  size_t index = normPathname.find(sep, 2);
1937  if (index == std::string::npos) {
1938  return std::pair<std::string, std::string>("", pathname);
1939  }
1940 
1941  size_t index2 = normPathname.find(sep, index + 1);
1942  // # a UNC path can't have two slashes in a row
1943  // # (after the initial two)
1944  if (index2 == index + 1) {
1945  return std::pair<std::string, std::string>("", pathname);
1946  }
1947 
1948  if (index2 == std::string::npos) {
1949  index2 = pathname.size();
1950  }
1951 
1952  return std::pair<std::string, std::string>(pathname.substr(0, index2), pathname.substr(index2));
1953  }
1954 
1955  if (normPathname[1] == ':') {
1956  return std::pair<std::string, std::string>(pathname.substr(0, 2), pathname.substr(2));
1957  }
1958  }
1959 
1960  return std::pair<std::string, std::string>("", pathname);
1961 #endif
1962 }
1963 
2012 std::vector<std::string> vpIoTools::splitChain(const std::string &chain, const std::string &sep)
2013 {
2014  size_t startIndex = 0;
2015 
2016  std::string chainToSplit = chain;
2017  std::vector<std::string> subChain;
2018  size_t sepIndex = chainToSplit.find(sep);
2019 
2020  while (sepIndex != std::string::npos) {
2021  std::string sub = chainToSplit.substr(startIndex, sepIndex);
2022  if (!sub.empty())
2023  subChain.push_back(sub);
2024  chainToSplit = chainToSplit.substr(sepIndex + 1, chain.size() - 1);
2025 
2026  sepIndex = chainToSplit.find(sep);
2027  }
2028  if (!chainToSplit.empty())
2029  subChain.push_back(chainToSplit);
2030 
2031  return subChain;
2032 }
2033 
2041 std::vector<std::string> vpIoTools::getDirFiles(const std::string &pathname)
2042 {
2043 
2044  if (!checkDirectory(pathname)) {
2045  throw(vpIoException(vpException::fatalError, "Directory %s doesn't exist'", pathname.c_str()));
2046  }
2047  std::string dirName = path(pathname);
2048 
2049 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
2050 
2051  std::vector<std::string> files;
2052  struct dirent **list = NULL;
2053  int filesCount = scandir(dirName.c_str(), &list, NULL, NULL);
2054  if (filesCount == -1) {
2055  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
2056  }
2057  for (int i = 0; i < filesCount; i++) {
2058  std::string fileName = list[i]->d_name;
2059  if (fileName != "." && fileName != "..") {
2060  files.push_back(fileName);
2061  }
2062  free(list[i]);
2063  }
2064  free(list);
2065  std::sort(files.begin(), files.end());
2066  return files;
2067 
2068 #elif defined(_WIN32)
2069 #if (!defined(WINRT))
2070 
2071  std::vector<std::string> files;
2072  std::string fileMask = dirName;
2073  fileMask.append("\\*");
2074  WIN32_FIND_DATA FindFileData;
2075  HANDLE hFind = FindFirstFile(fileMask.c_str(), &FindFileData);
2076  // Directory is empty
2077  if (HandleToLong(&hFind) == ERROR_FILE_NOT_FOUND) {
2078  return files;
2079  }
2080  if (hFind == INVALID_HANDLE_VALUE) {
2081  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
2082  }
2083  do {
2084  std::string fileName = FindFileData.cFileName;
2085  if (fileName != "." && fileName != "..") {
2086  files.push_back(fileName);
2087  }
2088  } while (FindNextFile(hFind, &FindFileData));
2089  FindClose(hFind);
2090  std::sort(files.begin(), files.end());
2091  return files;
2092 
2093 #else
2095  "Cannot read files of directory %s: not implemented on "
2096  "Universal Windows Platform",
2097  dirName.c_str()));
2098 #endif
2099 #endif
2100 }
2101 
2105 void vpIoTools::readBinaryValueLE(std::ifstream &file, int16_t &short_value)
2106 {
2107  file.read((char *)(&short_value), sizeof(short_value));
2108 
2109 #ifdef VISP_BIG_ENDIAN
2110  // Swap bytes order from little endian to big endian
2111  short_value = vpEndian::swap16bits((uint16_t)short_value);
2112 #endif
2113 }
2114 
2118 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint16_t &ushort_value)
2119 {
2120  file.read((char *)(&ushort_value), sizeof(ushort_value));
2121 
2122 #ifdef VISP_BIG_ENDIAN
2123  // Swap bytes order from little endian to big endian
2124  ushort_value = vpEndian::swap16bits(ushort_value);
2125 #endif
2126 }
2127 
2131 void vpIoTools::readBinaryValueLE(std::ifstream &file, int32_t &int_value)
2132 {
2133  file.read((char *)(&int_value), sizeof(int_value));
2134 
2135 #ifdef VISP_BIG_ENDIAN
2136  // Swap bytes order from little endian to big endian
2137  int_value = vpEndian::swap32bits((uint32_t)int_value);
2138 #endif
2139 }
2140 
2144 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint32_t &uint_value)
2145 {
2146  file.read((char *)(&uint_value), sizeof(uint_value));
2147 
2148 #ifdef VISP_BIG_ENDIAN
2149  // Swap bytes order from little endian to big endian
2150  uint_value = vpEndian::swap32bits(uint_value);
2151 #endif
2152 }
2153 
2157 void vpIoTools::readBinaryValueLE(std::ifstream &file, float &float_value)
2158 {
2159  file.read((char *)(&float_value), sizeof(float_value));
2160 
2161 #ifdef VISP_BIG_ENDIAN
2162  // Swap bytes order from little endian to big endian
2163  float_value = vpEndian::swapFloat(float_value);
2164 #endif
2165 }
2166 
2170 void vpIoTools::readBinaryValueLE(std::ifstream &file, double &double_value)
2171 {
2172  file.read((char *)(&double_value), sizeof(double_value));
2173 
2174 #ifdef VISP_BIG_ENDIAN
2175  // Swap bytes order from little endian to big endian
2176  double_value = vpEndian::swapDouble(double_value);
2177 #endif
2178 }
2179 
2183 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
2184 {
2185 #ifdef VISP_BIG_ENDIAN
2186  // Swap bytes order to little endian
2187  uint16_t swap_short = vpEndian::swap16bits((uint16_t)short_value);
2188  file.write((char *)(&swap_short), sizeof(swap_short));
2189 #else
2190  file.write((char *)(&short_value), sizeof(short_value));
2191 #endif
2192 }
2193 
2197 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint16_t ushort_value)
2198 {
2199 #ifdef VISP_BIG_ENDIAN
2200  // Swap bytes order to little endian
2201  uint16_t swap_ushort = vpEndian::swap16bits(ushort_value);
2202  file.write((char *)(&swap_ushort), sizeof(swap_ushort));
2203 #else
2204  file.write((char *)(&ushort_value), sizeof(ushort_value));
2205 #endif
2206 }
2207 
2211 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int32_t int_value)
2212 {
2213 #ifdef VISP_BIG_ENDIAN
2214  // Swap bytes order to little endian
2215  uint32_t swap_int = vpEndian::swap32bits((uint32_t)int_value);
2216  file.write((char *)(&swap_int), sizeof(swap_int));
2217 #else
2218  file.write((char *)(&int_value), sizeof(int_value));
2219 #endif
2220 }
2221 
2225 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint32_t uint_value)
2226 {
2227 #ifdef VISP_BIG_ENDIAN
2228  // Swap bytes order to little endian
2229  uint32_t swap_int = vpEndian::swap32bits(uint_value);
2230  file.write((char *)(&swap_int), sizeof(swap_int));
2231 #else
2232  file.write((char *)(&uint_value), sizeof(uint_value));
2233 #endif
2234 }
2235 
2239 void vpIoTools::writeBinaryValueLE(std::ofstream &file, float float_value)
2240 {
2241 #ifdef VISP_BIG_ENDIAN
2242  // Swap bytes order to little endian
2243  float swap_float = vpEndian::swapFloat(float_value);
2244  file.write((char *)(&swap_float), sizeof(swap_float));
2245 #else
2246  file.write((char *)(&float_value), sizeof(float_value));
2247 #endif
2248 }
2249 
2253 void vpIoTools::writeBinaryValueLE(std::ofstream &file, double double_value)
2254 {
2255 #ifdef VISP_BIG_ENDIAN
2256  // Swap bytes order to little endian
2257  double swap_double = vpEndian::swapDouble(double_value);
2258  file.write((char *)(&swap_double), sizeof(swap_double));
2259 #else
2260  file.write((char *)(&double_value), sizeof(double_value));
2261 #endif
2262 }
2263 
2264 bool vpIoTools::parseBoolean(std::string input)
2265 {
2266  std::transform(input.begin(), input.end(), input.begin(), ::tolower);
2267  std::istringstream is(input);
2268  bool b;
2269  // Parse string to boolean either in the textual representation
2270  // (True/False) or in numeric representation (1/0)
2271  is >> (input.size() > 1 ? std::boolalpha : std::noboolalpha) >> b;
2272  return b;
2273 }
2274 
2278 std::string vpIoTools::trim(std::string s) { return ltrim(rtrim(s)); }
unsigned int getCols() const
Definition: vpArray2D.h:280
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:305
unsigned int getRows() const
Definition: vpArray2D.h:290
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:406
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1417
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:2012
static std::vector< std::string > configVars
Definition: vpIoTools.h:252
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:1052
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1740
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:1694
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:835
static bool readConfigVar(const std::string &var, float &value)
Definition: vpIoTools.cpp:1143
static void setBaseName(const std::string &s)
Definition: vpIoTools.cpp:258
static std::pair< std::string, std::string > splitDrive(const std::string &pathname)
Definition: vpIoTools.cpp:1867
static bool isSamePathname(const std::string &pathname1, const std::string &pathname2)
Definition: vpIoTools.cpp:1847
static std::string getTempPath()
Definition: vpIoTools.cpp:218
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1823
static void setBaseDir(const std::string &dir)
Definition: vpIoTools.cpp:265
static std::string baseDir
Definition: vpIoTools.h:250
static bool loadConfigFile(const std::string &confFile)
Definition: vpIoTools.cpp:1092
static bool copy(const std::string &src, const std::string &dst)
Definition: vpIoTools.cpp:877
static std::string trim(std::string s)
Definition: vpIoTools.cpp:2278
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
Definition: vpIoTools.cpp:2105
static void saveConfigFile(const bool &actuallySave=true)
Definition: vpIoTools.cpp:1395
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:449
static bool rename(const std::string &oldfilename, const std::string &newfilename)
Definition: vpIoTools.cpp:1034
static bool parseBoolean(std::string input)
Definition: vpIoTools.cpp:2264
static long getIndex(const std::string &filename, const std::string &format)
Definition: vpIoTools.cpp:1627
static std::string getUserName()
Definition: vpIoTools.cpp:342
static std::string getFullName()
Definition: vpIoTools.cpp:279
static void addNameElement(const std::string &strTrue, const bool &cond=true, const std::string &strFalse="")
Definition: vpIoTools.cpp:1340
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1782
static std::string getenv(const std::string &env)
Definition: vpIoTools.cpp:379
static const std::string & getBuildInformation()
Definition: vpIoTools.cpp:159
static std::string getBaseName()
Definition: vpIoTools.cpp:272
static std::string getFileExtension(const std::string &pathname, bool checkFile=false)
Definition: vpIoTools.cpp:1483
static std::string baseName
Definition: vpIoTools.h:249
static void createBaseNamePath(const bool &empty=false)
Definition: vpIoTools.cpp:1375
static std::vector< std::string > getDirFiles(const std::string &dirname)
Definition: vpIoTools.cpp:2041
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:603
static std::string configFile
Definition: vpIoTools.h:251
static std::vector< std::string > configValues
Definition: vpIoTools.h:253
static void writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
Definition: vpIoTools.cpp:2183
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:970
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:1586
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:757
static bool checkFifo(const std::string &filename)
Definition: vpIoTools.cpp:514
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1669
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1564
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:1717
static const char separator
Definition: vpIoTools.h:181
static void makeFifo(const std::string &dirname)
Definition: vpIoTools.cpp:654
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:180
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