Visual Servoing Platform  version 3.5.1 under development (2022-07-05)
vpIoTools.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 http://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  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
43 #include <algorithm>
44 #include <cctype>
45 #include <cmath>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <fstream>
49 #include <functional>
50 #include <limits>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <sys/stat.h>
55 #include <sys/types.h>
56 #include <visp3/core/vpDebug.h>
57 #include <visp3/core/vpEndian.h>
58 #include <visp3/core/vpIoException.h>
59 #include <visp3/core/vpIoTools.h>
60 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
61 #include <dirent.h>
62 #include <unistd.h>
63 #elif defined(_WIN32)
64 #include <direct.h>
65 #include <windows.h>
66 #endif
67 #if !defined(_WIN32)
68 #ifdef __ANDROID__
69 // Like IOS, wordexp.cpp is not defined for Android
70 #else
71 #include <wordexp.h>
72 #endif
73 #endif
74 
75 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
76 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IOS macro
77 #endif
78 
79 #ifndef PATH_MAX
80 #ifdef _MAX_PATH
81 #define PATH_MAX _MAX_PATH
82 #else
83 #define PATH_MAX 1024
84 #endif
85 #endif
86 
87 std::string vpIoTools::baseName = "";
88 std::string vpIoTools::baseDir = "";
89 std::string vpIoTools::configFile = "";
90 std::vector<std::string> vpIoTools::configVars = std::vector<std::string>();
91 std::vector<std::string> vpIoTools::configValues = std::vector<std::string>();
92 
93 namespace
94 {
95 // The following code is not working on iOS since wordexp() is not available
96 // The function is not used on Android
97 #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
98 #if (TARGET_OS_IOS == 0) && !defined(__ANDROID__)
99 void replaceAll(std::string &str, const std::string &search, const std::string &replace)
100 {
101  size_t start_pos = 0;
102  while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
103  str.replace(start_pos, search.length(), replace);
104  start_pos += replace.length(); // Handles case where 'replace' is a
105  // substring of 'search'
106  }
107 }
108 #endif
109 #endif
110 
111 std::string &ltrim(std::string &s)
112 {
113 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
114  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
115 #else
116  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
117 #endif
118  return s;
119 }
120 
121 std::string &rtrim(std::string &s)
122 {
123 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
124  s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
125 #else
126  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
127 #endif
128  return s;
129 }
130 } // namespace
131 
135 const std::string &vpIoTools::getBuildInformation()
136 {
137  static std::string build_info =
138 #include "version_string.inc"
139  ;
140  return build_info;
141 }
142 
195 {
196 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
197  std::string username;
198  vpIoTools::getUserName(username);
199  return "/tmp/" + username;
200 #elif defined(_WIN32) && !defined(WINRT)
201  // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file
202  // Gets the temp path env string (no guarantee it's a valid path).
203  TCHAR lpTempPathBuffer[MAX_PATH];
204  DWORD dwRetVal = GetTempPath(MAX_PATH /* length of the buffer */, lpTempPathBuffer /* buffer for path */);
205  if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
206  throw vpIoException(vpIoException::cantGetenv, "Error with GetTempPath() call!");
207  }
208  std::string temp_path(lpTempPathBuffer);
209  if (!temp_path.empty()) {
210  if (temp_path.back() == '\\') {
211  temp_path.resize(temp_path.size() - 1);
212  }
213  } else {
214  temp_path = "C:\temp";
215  try {
216  vpIoTools::makeDirectory(temp_path);
217  } catch (...) {
218  throw(vpException(vpException::fatalError, "Cannot set temp path to %s", temp_path.c_str()));
219  }
220  }
221  return temp_path;
222 #else
223  throw vpIoException(vpException::fatalError, "Not implemented on this platform!");
224 #endif
225 }
226 
232 void vpIoTools::setBaseName(const std::string &s) { baseName = s; }
233 
239 void vpIoTools::setBaseDir(const std::string &dir) { baseDir = dir + "/"; }
240 
246 std::string vpIoTools::getBaseName() { return baseName; }
247 
253 std::string vpIoTools::getFullName() { return baseDir + baseName; }
254 
268 void vpIoTools::getUserName(std::string &username)
269 {
270 // With MinGW, UNIX and _WIN32 are defined
271 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
272  // Get the user name.
273  char *_username = ::getenv("LOGNAME");
274  if (!_username) {
275  username = "unknown";
276  } else {
277  username = _username;
278  }
279 #elif defined(_WIN32)
280 #if (!defined(WINRT))
281  unsigned int info_buffer_size = 1024;
282  TCHAR *infoBuf = new TCHAR[info_buffer_size];
283  DWORD bufCharCount = (DWORD)info_buffer_size;
284  // Get the user name.
285  if (!GetUserName(infoBuf, &bufCharCount)) {
286  username = "unknown";
287  } else {
288  username = infoBuf;
289  }
290  delete[] infoBuf;
291 #else
292  // Universal platform
293  username = "unknown";
294 #endif
295 #else
296  username = "unknown";
297 #endif
298 }
299 
315 {
316  std::string username;
317  getUserName(username);
318  return username;
319 }
320 
351 std::string vpIoTools::getenv(const std::string &env)
352 {
353 #if defined(_WIN32) && defined(WINRT)
354  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value: not "
355  "implemented on Universal Windows Platform"));
356 #else
357  std::string value;
358  // Get the environment variable value.
359  char *_value = ::getenv(env.c_str());
360  if (!_value) {
361  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value"));
362  }
363  value = _value;
364 
365  return value;
366 #endif
367 }
368 
378 void vpIoTools::getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
379 {
380  if (version.size() == 0) {
381  major = 0;
382  minor = 0;
383  patch = 0;
384  } else {
385  size_t major_pos = version.find('.');
386  std::string major_str = version.substr(0, major_pos);
387  major = static_cast<unsigned>(atoi(major_str.c_str()));
388 
389  if (major_pos != std::string::npos) {
390  size_t minor_pos = version.find('.', major_pos + 1);
391  std::string minor_str = version.substr(major_pos + 1, (minor_pos - (major_pos + 1)));
392  minor = static_cast<unsigned>(atoi(minor_str.c_str()));
393 
394  if (minor_pos != std::string::npos) {
395  std::string patch_str = version.substr(minor_pos + 1);
396  patch = static_cast<unsigned>(atoi(patch_str.c_str()));
397  } else {
398  patch = 0;
399  }
400  } else {
401  minor = 0;
402  patch = 0;
403  }
404  }
405 }
406 
418 bool vpIoTools::checkDirectory(const std::string &dirname)
419 {
420 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
421  struct stat stbuf;
422 #elif defined(_WIN32) && defined(__MINGW32__)
423  struct stat stbuf;
424 #elif defined(_WIN32)
425  struct _stat stbuf;
426 #endif
427 
428  if (dirname.empty()) {
429  return false;
430  }
431 
432  std::string _dirname = path(dirname);
433 
434 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
435  if (stat(_dirname.c_str(), &stbuf) != 0)
436 #elif defined(_WIN32) && defined(__MINGW32__)
437  // Remove trailing separator character if any
438  // AppVeyor: Windows 6.3.9600 AMD64 ; C:/MinGW/bin/g++.exe (ver 5.3.0) ;
439  // GNU Make 3.82.90 Built for i686-pc-mingw32
440  if (_dirname.at(_dirname.size() - 1) == vpIoTools::separator)
441  _dirname = _dirname.substr(0, _dirname.size() - 1);
442  if (stat(_dirname.c_str(), &stbuf) != 0)
443 #elif defined(_WIN32)
444  if (_stat(_dirname.c_str(), &stbuf) != 0)
445 #endif
446  {
447  return false;
448  }
449 #if defined(_WIN32) || (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
450  if ((stbuf.st_mode & S_IFDIR) == 0)
451 #endif
452  {
453  return false;
454  }
455 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
456  if ((stbuf.st_mode & S_IWUSR) == 0)
457 #elif defined(_WIN32)
458  if ((stbuf.st_mode & S_IWRITE) == 0)
459 #endif
460  {
461  return false;
462  }
463  return true;
464 }
465 
478 bool vpIoTools::checkFifo(const std::string &fifofilename)
479 {
480 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
481  struct stat stbuf;
482 
483  std::string _filename = path(fifofilename);
484  if (stat(_filename.c_str(), &stbuf) != 0) {
485  return false;
486  }
487  if ((stbuf.st_mode & S_IFIFO) == 0) {
488  return false;
489  }
490  if ((stbuf.st_mode & S_IRUSR) == 0)
491 
492  {
493  return false;
494  }
495  return true;
496 #elif defined(_WIN32)
497  (void)fifofilename;
498  throw(vpIoException(vpIoException::notImplementedError, "Fifo files are not supported on Windows platforms."));
499 #endif
500 }
501 
502 #ifndef DOXYGEN_SHOULD_SKIP_THIS
503 // See:
504 // https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950
505 int vpIoTools::mkdir_p(const char *path, int mode)
506 {
507  /* Adapted from http://stackoverflow.com/a/2336245/119527 */
508  const size_t len = strlen(path);
509  char _path[PATH_MAX];
510  const char sep = vpIoTools::separator;
511 
512  std::fill(_path, _path + PATH_MAX, 0);
513 
514  errno = 0;
515  if (len > sizeof(_path) - 1) {
516  errno = ENAMETOOLONG;
517  return -1;
518  }
519  /* Copy string so its mutable */
520  strcpy(_path, path);
521 
522  /* Iterate over the string */
523  for (char *p = _path + 1; *p; p++) { // path cannot be empty
524  if (*p == sep) {
525  /* Temporarily truncate */
526  *p = '\0';
527 
528 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
529  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
530 #elif defined(_WIN32)
531  (void)mode; // var not used
532  if (!checkDirectory(_path) && _mkdir(_path) != 0)
533 #endif
534  {
535  if (errno != EEXIST)
536  return -1;
537  }
538  *p = sep;
539  }
540  }
541 
542 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
543  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
544 #elif defined(_WIN32)
545  if (_mkdir(_path) != 0)
546 #endif
547  {
548  if (errno != EEXIST)
549  return -1;
550  }
551 
552  return 0;
553 }
554 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
555 
568 void vpIoTools::makeDirectory(const std::string &dirname)
569 {
570 #if ((!defined(__unix__) && !defined(__unix) && (!defined(__APPLE__) || !defined(__MACH__)))) && !defined(_WIN32)
571  std::cerr << "Unsupported platform for vpIoTools::makeDirectory()!" << std::endl;
572  return;
573 #endif
574 
575 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
576  struct stat stbuf;
577 #elif defined(_WIN32) && defined(__MINGW32__)
578  struct stat stbuf;
579 #elif defined(_WIN32)
580  struct _stat stbuf;
581 #endif
582 
583  if (dirname.empty()) {
584  throw(vpIoException(vpIoException::invalidDirectoryName, "invalid directory name"));
585  }
586 
587  std::string _dirname = path(dirname);
588 
589 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
590  if (stat(_dirname.c_str(), &stbuf) != 0)
591 #elif defined(_WIN32) && defined(__MINGW32__)
592  if (stat(_dirname.c_str(), &stbuf) != 0)
593 #elif defined(_WIN32)
594  if (_stat(_dirname.c_str(), &stbuf) != 0)
595 #endif
596  {
597  if (vpIoTools::mkdir_p(_dirname.c_str(), 0755) != 0) {
598  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
599  }
600  }
601 
602  if (checkDirectory(dirname) == false) {
603  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
604  }
605 }
606 
619 void vpIoTools::makeFifo(const std::string &fifoname)
620 {
621 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
622 
623  // If dirname is a directory, we throw an error
624  if (vpIoTools::checkDirectory(fifoname)) {
626  "Unable to create fifo file. '%s' is an existing directory.", fifoname.c_str()));
627  }
628 
629  // If dirname refers to an already existing file, we throw an error
630  else if (vpIoTools::checkFilename(fifoname)) {
631  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. File already exists.",
632  fifoname.c_str()));
633  // If dirname refers to an already existing fifo, we throw an error
634  } else if (vpIoTools::checkFifo(fifoname)) {
635  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. Fifo already exists.",
636  fifoname.c_str()));
637  }
638 
639  else if (mkfifo(fifoname.c_str(), 0666) < 0) {
640  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo file '%s'.", fifoname.c_str()));
641  }
642 #elif defined(_WIN32)
643  (void)fifoname;
644  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo on Windows platforms."));
645 #endif
646 }
647 
648 #if defined(_WIN32) && !defined(WINRT)
649 std::string getUuid()
650 {
651  UUID uuid;
652  if (UuidCreate(&uuid) != RPC_S_OK) {
653  throw(vpIoException(vpIoException::fatalError, "UuidCreate() failed!"));
654  }
655 
656  RPC_CSTR stringUuid;
657  if (UuidToString(&uuid, &stringUuid) != RPC_S_OK) {
658  throw(vpIoException(vpIoException::fatalError, "UuidToString() failed!"));
659  }
660 
661  return reinterpret_cast<char *>(stringUuid);
662 }
663 #endif
664 
726 std::string vpIoTools::makeTempDirectory(const std::string &dirname)
727 {
728 #if defined(WINRT) || !defined(_WIN32) && !(defined(__unix__) || defined(__unix) || \
729  (defined(__APPLE__) && defined(__MACH__))) // not UNIX and not Windows
730  throw(vpIoException(vpIoException::cantCreateDirectory, "makeTempDirectory() is not supported on this platform!"));
731 #endif
732 
733  std::string dirname_cpy = std::string(dirname);
734  std::string correctEnding = "XXXXXX";
735 
736  size_t endingLength = correctEnding.length();
737  size_t dirNameLength = dirname_cpy.length();
738 
739  // If dirname is an unexisting directory, it should end with XXXXXX in order to create a temp directory
740  if (!vpIoTools::checkDirectory(dirname_cpy)) {
741  if (endingLength > dirNameLength) {
743  "Unable to create temp directory '%s'. It should end with XXXXXX.", dirname_cpy.c_str()));
744  }
745 
746  if (dirname.compare(dirNameLength - endingLength, endingLength, correctEnding) != 0) {
748  "Unable to create temp directory '%s'. It should end with XXXXXX.", dirname_cpy.c_str()));
749  }
750 
751 #if defined(_WIN32) && !defined(WINRT)
752  // Remove XXXXXX
753  dirname_cpy = dirname_cpy.substr(0, dirname_cpy.rfind(correctEnding));
754  // Append UUID
755  dirname_cpy = dirname_cpy + getUuid();
756 #endif
757 
758  } else {
759  // If dirname is an existing directory, we create a temp directory inside
760 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
761  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
762  dirname_cpy = dirname_cpy + "/";
763  }
764  dirname_cpy = dirname_cpy + "XXXXXX";
765 #elif defined(_WIN32) && !defined(WINRT)
766  dirname_cpy = createFilePath(dirname_cpy, getUuid());
767 #endif
768  }
769 
770 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
771  char *dirname_char = new char[dirname_cpy.length() + 1];
772  strcpy(dirname_char, dirname_cpy.c_str());
773 
774  char *computedDirname = mkdtemp(dirname_char);
775 
776  if (!computedDirname) {
777  delete[] dirname_char;
778  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'.", dirname_cpy.c_str()));
779  }
780 
781  std::string res(computedDirname);
782  delete[] dirname_char;
783  return res;
784 #elif defined(_WIN32) && !defined(WINRT)
785  makeDirectory(dirname_cpy);
786  return dirname_cpy;
787 #endif
788 }
789 
800 bool vpIoTools::checkFilename(const std::string &filename)
801 {
802 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
803  struct stat stbuf;
804 #elif defined(_WIN32)
805  struct _stat stbuf;
806 #endif
807 
808  if (filename.empty()) {
809  return false;
810  }
811 
812  std::string _filename = path(filename);
813 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
814  if (stat(_filename.c_str(), &stbuf) != 0)
815 #elif defined(_WIN32)
816  if (_stat(_filename.c_str(), &stbuf) != 0)
817 #endif
818  {
819  return false;
820  }
821  if ((stbuf.st_mode & S_IFREG) == 0) {
822  return false;
823  }
824 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
825  if ((stbuf.st_mode & S_IRUSR) == 0)
826 #elif defined(_WIN32)
827  if ((stbuf.st_mode & S_IREAD) == 0)
828 #endif
829  {
830  return false;
831  }
832  return true;
833 }
834 
842 bool vpIoTools::copy(const std::string &src, const std::string &dst)
843 {
844  // Check if we have to consider a file or a directory
845  if (vpIoTools::checkFilename(src)) {
846 // std::cout << "copy file: " << src << " in " << dst << std::endl;
847 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
848 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
849  // wordexp() is not available
850  char cmd[FILENAME_MAX];
851  int ret;
852  sprintf(cmd, "cp -p %s %s", src.c_str(), dst.c_str());
853  ret = system(cmd);
854  if (ret) {
855  }; // to avoid a warning
856  // std::cout << cmd << " return value: " << ret << std::endl;
857  return true;
858 #else
859  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
860  dst.c_str()));
861 #endif
862 #elif defined(_WIN32)
863 #if (!defined(WINRT))
864  char cmd[FILENAME_MAX];
865  int ret;
866  std::string src_ = vpIoTools::path(src);
867  std::string dst_ = vpIoTools::path(dst);
868  sprintf(cmd, "copy %s %s", src_.c_str(), dst_.c_str());
869  ret = system(cmd);
870  if (ret) {
871  }; // to avoid a warning
872  // std::cout << cmd << " return value: " << ret << std::endl;
873  return true;
874 #else
875  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
876  src.c_str(), dst.c_str()));
877 #endif
878 #endif
879  } else if (vpIoTools::checkDirectory(src)) {
880 // std::cout << "copy directory: " << src << " in " << dst << std::endl;
881 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
882 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
883  // wordexp() is not available
884  char cmd[FILENAME_MAX];
885  int ret;
886  sprintf(cmd, "cp -p -r %s %s", src.c_str(), dst.c_str());
887  ret = system(cmd);
888  if (ret) {
889  }; // to avoid a warning
890  // std::cout << cmd << " return value: " << ret << std::endl;
891  return true;
892 #else
893  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
894  dst.c_str()));
895 #endif
896 #elif defined(_WIN32)
897 #if (!defined(WINRT))
898  char cmd[FILENAME_MAX];
899  int ret;
900  std::string src_ = vpIoTools::path(src);
901  std::string dst_ = vpIoTools::path(dst);
902  sprintf(cmd, "copy %s %s", src_.c_str(), dst_.c_str());
903  ret = system(cmd);
904  if (ret) {
905  }; // to avoid a warning
906  // std::cout << cmd << " return value: " << ret << std::endl;
907  return true;
908 #else
909  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
910  src.c_str(), dst.c_str()));
911 #endif
912 #endif
913  } else {
914  std::cout << "Cannot copy: " << src << " in " << dst << std::endl;
915  return false;
916  }
917 }
918 
929 bool vpIoTools::remove(const std::string &file_or_dir)
930 {
931  // Check if we have to consider a file or a directory
932  if (vpIoTools::checkFilename(file_or_dir)
933 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
934  || vpIoTools::checkFifo(std::string(file_or_dir))
935 #endif
936  ) {
937  // std::cout << "remove file: " << file_or_dir << std::endl;
938  if (::remove(file_or_dir.c_str()) != 0)
939  return false;
940  else
941  return true;
942  } else if (vpIoTools::checkDirectory(file_or_dir)) {
943 // std::cout << "remove directory: " << file_or_dir << std::endl;
944 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
945 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
946  // wordexp() is not available
947  char cmd[FILENAME_MAX];
948  sprintf(cmd, "rm -rf \"%s\"", file_or_dir.c_str());
949  int ret = system(cmd);
950  if (ret) {
951  }; // to avoid a warning
952  // std::cout << cmd << " return value: " << ret << std::endl;
953  return true;
954 #else
955  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on iOS Platform",
956  file_or_dir.c_str()));
957 #endif
958 #elif defined(_WIN32)
959 #if (!defined(WINRT))
960  char cmd[FILENAME_MAX];
961  std::string file_or_dir_ = vpIoTools::path(file_or_dir);
962  sprintf(cmd, "rmdir /S /Q %s", file_or_dir_.c_str());
963  int ret = system(cmd);
964  if (ret) {
965  }; // to avoid a warning
966  // std::cout << cmd << " return value: " << ret << std::endl;
967  return true;
968 #else
969  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on Universal Windows Platform",
970  file_or_dir.c_str()));
971 #endif
972 #endif
973  } else {
974  std::cout << "Cannot remove: " << file_or_dir << std::endl;
975  return false;
976  }
977 }
978 
988 bool vpIoTools::rename(const std::string &oldfilename, const std::string &newfilename)
989 {
990  if (::rename(oldfilename.c_str(), newfilename.c_str()) != 0)
991  return false;
992  else
993  return true;
994 }
995 
1006 std::string vpIoTools::path(const std::string &pathname)
1007 {
1008  std::string path(pathname);
1009 
1010 #if defined(_WIN32)
1011  for (unsigned int i = 0; i < path.length(); i++)
1012  if (path[i] == '/')
1013  path[i] = '\\';
1014 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
1015  for (unsigned int i = 0; i < path.length(); i++)
1016  if (path[i] == '\\')
1017  path[i] = '/';
1018 #if TARGET_OS_IOS == 0 // The following code is not working on iOS and android since
1019  // wordexp() is not available
1020 #ifdef __ANDROID__
1021 // Do nothing
1022 #else
1023  wordexp_t exp_result;
1024 
1025  // escape quote character
1026  replaceAll(path, "'", "'\\''");
1027  // add quotes to handle special characters like parentheses and spaces
1028  wordexp(std::string("'" + path + "'").c_str(), &exp_result, 0);
1029  path = exp_result.we_wordc == 1 ? exp_result.we_wordv[0] : "";
1030  wordfree(&exp_result);
1031 #endif
1032 #endif
1033 #endif
1034 
1035  return path;
1036 }
1037 
1046 bool vpIoTools::loadConfigFile(const std::string &confFile)
1047 {
1048  configFile = path(confFile);
1049  configVars.clear();
1050  configValues.clear();
1051  std::ifstream confContent(configFile.c_str(), std::ios::in);
1052 
1053  if (confContent.is_open()) {
1054  std::string line, var, val;
1055  long unsigned int k;
1056  int c;
1057  std::string stop[3] = {" ", "\t", "#"};
1058  while (std::getline(confContent, line)) {
1059  if ((line.compare(0, 1, "#") != 0) && (line.size() > 2)) {
1060  try {
1061  // name of the variable
1062  k = static_cast<unsigned long>(line.find(" "));
1063  var = line.substr(0, k);
1064  // look for the end of the actual value
1065  c = 200;
1066  for (unsigned i = 0; i < 3; ++i)
1067  c = vpMath::minimum(c,
1068  static_cast<int>(line.find(stop[i], static_cast<size_t>(k) + static_cast<size_t>(1))));
1069  if (c == -1)
1070  c = static_cast<int>(line.size());
1071  long unsigned int c_ = static_cast<long unsigned int>(c);
1072  val = line.substr(static_cast<size_t>(k) + static_cast<size_t>(1),
1073  static_cast<size_t>(c_) - static_cast<size_t>(k) - static_cast<size_t>(1));
1074  configVars.push_back(var);
1075  configValues.push_back(val);
1076  } catch (...) {
1077  }
1078  }
1079  }
1080  confContent.close();
1081  } else {
1082  return false;
1083  }
1084  return true;
1085 }
1086 
1095 bool vpIoTools::readConfigVar(const std::string &var, float &value)
1096 {
1097  bool found = false;
1098  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1099  if (configVars[k] == var) {
1100  if (configValues[k].compare("PI") == 0)
1101  value = static_cast<float>(M_PI);
1102  else if (configValues[k].compare("PI/2") == 0)
1103  value = static_cast<float>(M_PI / 2.0);
1104  else if (configValues[k].compare("-PI/2") == 0)
1105  value = static_cast<float>(-M_PI / 2.0);
1106  else
1107  value = static_cast<float>(atof(configValues[k].c_str()));
1108  found = true;
1109  }
1110  }
1111  if (found == false)
1112  std::cout << var << " not found in config file" << std::endl;
1113  return found;
1114 }
1123 bool vpIoTools::readConfigVar(const std::string &var, double &value)
1124 {
1125  bool found = false;
1126  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1127  if (configVars[k] == var) {
1128  if (configValues[k].compare("PI") == 0)
1129  value = M_PI;
1130  else if (configValues[k].compare("PI/2") == 0)
1131  value = M_PI / 2;
1132  else if (configValues[k].compare("-PI/2") == 0)
1133  value = -M_PI / 2;
1134  else
1135  value = atof(configValues[k].c_str());
1136  found = true;
1137  }
1138  }
1139  if (found == false)
1140  std::cout << var << " not found in config file" << std::endl;
1141  return found;
1142 }
1143 
1152 bool vpIoTools::readConfigVar(const std::string &var, int &value)
1153 {
1154  bool found = false;
1155  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1156  if (configVars[k] == var) {
1157  value = atoi(configValues[k].c_str());
1158  found = true;
1159  }
1160  }
1161  if (found == false)
1162  std::cout << var << " not found in config file" << std::endl;
1163  return found;
1164 }
1165 
1174 bool vpIoTools::readConfigVar(const std::string &var, unsigned int &value)
1175 {
1176  int v = 0;
1177  bool found = readConfigVar(var, v);
1178  value = static_cast<unsigned int>(v);
1179  return found;
1180 }
1181 
1190 bool vpIoTools::readConfigVar(const std::string &var, bool &value)
1191 {
1192  int v = 0;
1193  bool found = readConfigVar(var, v);
1194  value = (v != 0);
1195  return found;
1196 }
1197 
1206 bool vpIoTools::readConfigVar(const std::string &var, vpColor &value)
1207 {
1208  unsigned int v = 0;
1209  bool found = readConfigVar(var, v);
1210  value = vpColor::getColor(v);
1211  return found;
1212 }
1213 
1222 bool vpIoTools::readConfigVar(const std::string &var, std::string &value)
1223 {
1224  bool found = false;
1225  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1226  if (configVars[k] == var) {
1227  value = configValues[k];
1228  found = true;
1229  }
1230  }
1231  if (found == false)
1232  std::cout << var << " not found in config file" << std::endl;
1233  return found;
1234 }
1235 
1249 bool vpIoTools::readConfigVar(const std::string &var, vpArray2D<double> &value, const unsigned int &nCols,
1250  const unsigned int &nRows)
1251 {
1252  bool found = false;
1253  std::string nb;
1254  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1255  if (configVars[k] == var) {
1256  found = true;
1257  // resize or not
1258  if (nCols != 0 && nRows != 0)
1259  value.resize(nRows, nCols);
1260  size_t ind = 0, ind2;
1261  for (unsigned int i = 0; i < value.getRows(); ++i)
1262  for (unsigned int j = 0; j < value.getCols(); ++j) {
1263  ind2 = configValues[k].find(",", ind);
1264  nb = configValues[k].substr(ind, ind2 - ind);
1265  if (nb.compare("PI") == 0)
1266  value[i][j] = M_PI;
1267  else if (nb.compare("PI/2") == 0)
1268  value[i][j] = M_PI / 2;
1269  else if (nb.compare("-PI/2") == 0)
1270  value[i][j] = -M_PI / 2;
1271  else
1272  value[i][j] = atof(nb.c_str());
1273  ind = ind2 + 1;
1274  }
1275  }
1276  }
1277  if (found == false)
1278  std::cout << var << " not found in config file" << std::endl;
1279  return found;
1280 }
1281 
1282 // construct experiment filename & path
1283 
1292 void vpIoTools::addNameElement(const std::string &strTrue, const bool &cond, const std::string &strFalse)
1293 {
1294  if (cond)
1295  baseName += "_" + strTrue;
1296  else if (strFalse != "")
1297  baseName += "_" + strFalse;
1298 }
1299 
1308 void vpIoTools::addNameElement(const std::string &strTrue, const double &val)
1309 {
1310  // if(val != 0.)
1311  if (std::fabs(val) < std::numeric_limits<double>::epsilon()) {
1312  char valC[256];
1313  sprintf(valC, "%.3f", val);
1314  std::string valS(valC);
1315  baseName += "_" + strTrue + valS;
1316  }
1317 }
1318 
1327 void vpIoTools::createBaseNamePath(const bool &empty)
1328 {
1329  if (vpIoTools::checkDirectory(baseDir + baseName) == false) {
1331  std::cout << "creating directory " + baseDir + baseName << std::endl;
1332  } else {
1333  if (empty) {
1334  std::cout << "emptying directory " + baseDir + baseName << std::endl;
1336  }
1337  }
1338 }
1339 
1346 void vpIoTools::saveConfigFile(const bool &actuallySave)
1347 {
1348  if (actuallySave) {
1349  std::string dest = baseDir + "/" + baseName + "_config.txt";
1350  // file copy
1351  vpIoTools::copy(configFile, dest);
1352  }
1353 }
1354 
1369 {
1370  std::string data_path;
1371  std::string file_to_test("mbt/cube.cao");
1372  std::string filename;
1373  // Test if VISP_INPUT_IMAGE_PATH env var is set
1374  try {
1375  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH");
1376  filename = data_path + "/" + file_to_test;
1377  if (vpIoTools::checkFilename(filename))
1378  return data_path;
1379  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/ViSP-images";
1380  filename = data_path + "/" + file_to_test;
1381  if (vpIoTools::checkFilename(filename))
1382  return data_path;
1383  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/visp-images";
1384  filename = data_path + "/" + file_to_test;
1385  if (vpIoTools::checkFilename(filename))
1386  return data_path;
1387  } catch (...) {
1388  }
1389 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1390  // Test if visp-images-data package is installed (Ubuntu and Debian)
1391  data_path = "/usr/share/visp-images-data/ViSP-images";
1392  filename = data_path + "/" + file_to_test;
1393  if (vpIoTools::checkFilename(filename))
1394  return data_path;
1395  data_path = "/usr/share/visp-images-data/visp-images";
1396  filename = data_path + "/" + file_to_test;
1397  if (vpIoTools::checkFilename(filename))
1398  return data_path;
1399 #endif
1400  data_path = "";
1401  return data_path;
1402 }
1403 
1433 std::string vpIoTools::getFileExtension(const std::string &pathname, bool checkFile)
1434 {
1435  if (checkFile && (vpIoTools::checkDirectory(pathname) || !vpIoTools::checkFilename(pathname))) {
1436  return "";
1437  }
1438 
1439 #if defined(_WIN32)
1440  std::string sep = "\\";
1441  std::string altsep = "/";
1442  std::string extsep = ".";
1443 #else
1444  // On Unix, or on the Mac
1445  std::string sep = "/";
1446  std::string altsep = "";
1447  std::string extsep = ".";
1448 #endif
1449 
1450  // Python 2.7.8 module.
1451  //# Split a path in root and extension.
1452  //# The extension is everything starting at the last dot in the last
1453  //# pathname component; the root is everything before that.
1454  //# It is always true that root + ext == p.
1455  //
1456  //# Generic implementation of splitext, to be parametrized with
1457  //# the separators
1458  // def _splitext(p, sep, altsep, extsep):
1459  // """Split the extension from a pathname.
1460  //
1461  // Extension is everything from the last dot to the end, ignoring
1462  // leading dots. Returns "(root, ext)"; ext may be empty."""
1463  //
1464  // sepIndex = p.rfind(sep)
1465  // if altsep:
1466  // altsepIndex = p.rfind(altsep)
1467  // sepIndex = max(sepIndex, altsepIndex)
1468  //
1469  // dotIndex = p.rfind(extsep)
1470  // if dotIndex > sepIndex:
1471  // # skip all leading dots
1472  // filenameIndex = sepIndex + 1
1473  // while filenameIndex < dotIndex:
1474  // if p[filenameIndex] != extsep:
1475  // return p[:dotIndex], p[dotIndex:]
1476  // filenameIndex += 1
1477  //
1478  // return p, ''
1479 
1480  int sepIndex = static_cast<int>(pathname.rfind(sep));
1481  if (!altsep.empty()) {
1482  int altsepIndex = static_cast<int>(pathname.rfind(altsep));
1483  sepIndex = ((std::max))(sepIndex, altsepIndex);
1484  }
1485 
1486  size_t dotIndex = pathname.rfind(extsep);
1487  if (dotIndex != std::string::npos) {
1488  // The extsep character exists
1489  size_t npos = std::string::npos;
1490  if ((sepIndex != static_cast<int>(npos) && static_cast<int>(dotIndex) > sepIndex) ||
1491  sepIndex == static_cast<int>(npos)) {
1492  if (sepIndex == static_cast<int>(npos)) {
1493  sepIndex = 0;
1494  }
1495  size_t filenameIndex = static_cast<size_t>(sepIndex) + static_cast<size_t>(1);
1496 
1497  while (filenameIndex < dotIndex) {
1498  if (pathname.compare(filenameIndex, 1, extsep) != 0) {
1499  return pathname.substr(dotIndex);
1500  }
1501  filenameIndex++;
1502  }
1503  }
1504  }
1505 
1506  return "";
1507 }
1508 
1514 std::string vpIoTools::getName(const std::string &pathname)
1515 {
1516  if (pathname.size() > 0) {
1517  std::string convertedPathname = vpIoTools::path(pathname);
1518 
1519  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1520  if (index != std::string::npos) {
1521  return convertedPathname.substr(index + 1);
1522  }
1523 
1524  return convertedPathname;
1525  }
1526 
1527  return "";
1528 }
1529 
1536 std::string vpIoTools::getNameWE(const std::string &pathname)
1537 {
1538  std::string name = vpIoTools::getName(pathname);
1539  size_t found = name.find_last_of(".");
1540  std::string name_we = name.substr(0, found);
1541  return name_we;
1542 }
1543 
1577 long vpIoTools::getIndex(const std::string &filename, const std::string &format)
1578 {
1579  size_t indexBegin = format.find_last_of('%');
1580  size_t indexEnd = format.find_first_of('d', indexBegin);
1581  size_t suffixLength = format.length() - indexEnd - 1;
1582 
1583  // Extracting index
1584  if (filename.length() <= suffixLength + indexBegin) {
1585  return -1;
1586  }
1587  size_t indexLength = filename.length() - suffixLength - indexBegin;
1588  std::string indexSubstr = filename.substr(indexBegin, indexLength);
1589  std::istringstream ss(indexSubstr);
1590  long index = 0;
1591  ss >> index;
1592  if (ss.fail() || index < 0 || !ss.eof()) {
1593  return -1;
1594  }
1595 
1596  // Checking that format with inserted index equals filename
1597  char nameByFormat[FILENAME_MAX];
1598  sprintf(nameByFormat, format.c_str(), index);
1599  if (std::string(nameByFormat) != filename) {
1600  return -1;
1601  }
1602  return index;
1603 }
1604 
1620 std::string vpIoTools::getParent(const std::string &pathname)
1621 {
1622  if (pathname.size() > 0) {
1623  std::string convertedPathname = vpIoTools::path(pathname);
1624 
1625  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1626  if (index != std::string::npos) {
1627  return convertedPathname.substr(0, index);
1628  }
1629 
1630  return ".";
1631  }
1632  else {
1633  return "";
1634  }
1635 }
1636 
1645 std::string vpIoTools::getAbsolutePathname(const std::string &pathname)
1646 {
1647 
1648 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1649  std::string real_path_str = pathname;
1650  char *real_path = realpath(pathname.c_str(), NULL);
1651 
1652  if (real_path) {
1653  real_path_str = real_path;
1654  free(real_path);
1655  }
1656  return real_path_str;
1657 #elif defined(_WIN32)
1658 #if (!defined(WINRT))
1659  std::string real_path_str = pathname;
1660  DWORD retval = 0;
1661  TCHAR buffer[4096] = TEXT("");
1662 
1663  retval = GetFullPathName(pathname.c_str(), 4096, buffer, 0);
1664  if (retval != 0) {
1665  real_path_str = buffer;
1666  }
1667  return real_path_str;
1668 #else
1670  "Cannot get absolute path of %s: not implemented on "
1671  "Universal Windows Platform",
1672  pathname.c_str()));
1673 #endif
1674 #endif
1675 }
1676 
1687 std::string vpIoTools::createFilePath(const std::string &parent, const std::string &child)
1688 {
1689  if (child.size() == 0 && parent.size() == 0) {
1690  return "";
1691  }
1692 
1693  if (child.size() == 0) {
1694  return vpIoTools::path(parent);
1695  }
1696 
1697  if (parent.size() == 0) {
1698  return vpIoTools::path(child);
1699  }
1700 
1701  std::string convertedParent = vpIoTools::path(parent);
1702  std::string convertedChild = vpIoTools::path(child);
1703 
1704  std::stringstream ss;
1705  ss << vpIoTools::separator;
1706  std::string stringSeparator;
1707  ss >> stringSeparator;
1708 
1709  std::string lastConvertedParentChar = convertedParent.substr(convertedParent.size() - 1);
1710  std::string firstConvertedChildChar = convertedChild.substr(0, 1);
1711 
1712  if (lastConvertedParentChar == stringSeparator) {
1713  convertedParent = convertedParent.substr(0, convertedParent.size() - 1);
1714  }
1715 
1716  if (firstConvertedChildChar == stringSeparator) {
1717  convertedChild = convertedChild.substr(1);
1718  }
1719 
1720  return std::string(convertedParent + vpIoTools::separator + convertedChild);
1721 }
1722 
1728 bool vpIoTools::isAbsolutePathname(const std::string &pathname)
1729 {
1730  //# Inspired by the Python 2.7.8 module.
1731  //# Return whether a path is absolute.
1732  //# Trivial in Posix, harder on the Mac or MS-DOS.
1733  //# For DOS it is absolute if it starts with a slash or backslash (current
1734  //# volume), or if a pathname after the volume letter and colon / UNC
1735  // resource # starts with a slash or backslash.
1736  //
1737  // def isabs(s):
1738  // """Test whether a path is absolute"""
1739  // s = splitdrive(s)[1]
1740  // return s != '' and s[:1] in '/\\'
1741  std::string path = splitDrive(pathname).second;
1742  return path.size() > 0 && (path.substr(0, 1) == "/" || path.substr(0, 1) == "\\");
1743 }
1744 
1752 bool vpIoTools::isSamePathname(const std::string &pathname1, const std::string &pathname2)
1753 {
1754  // Normalize path
1755  std::string path1_normalize = vpIoTools::path(pathname1);
1756  std::string path2_normalize = vpIoTools::path(pathname2);
1757 
1758  // Get absolute path
1759  path1_normalize = vpIoTools::getAbsolutePathname(path1_normalize);
1760  path2_normalize = vpIoTools::getAbsolutePathname(path2_normalize);
1761 
1762  return (path1_normalize == path2_normalize);
1763 }
1764 
1772 std::pair<std::string, std::string> vpIoTools::splitDrive(const std::string &pathname)
1773 {
1774 //# Split a path in a drive specification (a drive letter followed by a
1775 //# colon) and the path specification.
1776 //# It is always true that drivespec + pathspec == p
1777 // def splitdrive(p):
1778 // """Split a pathname into drive/UNC sharepoint and relative path
1779 // specifiers. Returns a 2-tuple (drive_or_unc, path); either part may be
1780 // empty.
1781 //
1782 // If you assign
1783 // result = splitdrive(p)
1784 // It is always true that:
1785 // result[0] + result[1] == p
1786 //
1787 // If the path contained a drive letter, drive_or_unc will contain
1788 // everything up to and including the colon. e.g. splitdrive("c:/dir")
1789 // returns ("c:", "/dir")
1790 //
1791 // If the path contained a UNC path, the drive_or_unc will contain the host
1792 // name and share up to but not including the fourth directory separator
1793 // character. e.g. splitdrive("//host/computer/dir") returns
1794 // ("//host/computer", "/dir")
1795 //
1796 // Paths cannot contain both a drive letter and a UNC path.
1797 //
1798 // """
1799 // if len(p) > 1:
1800 // normp = p.replace(altsep, sep)
1801 // if (normp[0:2] == sep*2) and (normp[2] != sep):
1802 // # is a UNC path:
1803 // # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1804 // # \\machine\mountpoint\directory\etc\...
1805 // # directory ^^^^^^^^^^^^^^^
1806 // index = normp.find(sep, 2)
1807 // if index == -1:
1808 // return '', p
1809 // index2 = normp.find(sep, index + 1)
1810 // # a UNC path can't have two slashes in a row
1811 // # (after the initial two)
1812 // if index2 == index + 1:
1813 // return '', p
1814 // if index2 == -1:
1815 // index2 = len(p)
1816 // return p[:index2], p[index2:]
1817 // if normp[1] == ':':
1818 // return p[:2], p[2:]
1819 // return '', p
1820 
1821 // On Unix, the drive is always empty.
1822 // On the Mac, the drive is always empty (don't use the volume name -- it
1823 // doesn't have the same syntactic and semantic oddities as DOS drive
1824 // letters, such as there being a separate current directory per drive).
1825 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
1826  return std::pair<std::string, std::string>("", pathname);
1827 #else
1828  const std::string sep = "\\";
1829  const std::string sepsep = "\\\\";
1830  const std::string altsep = "/";
1831 
1832  if (pathname.size() > 1) {
1833  std::string normPathname = pathname;
1834  std::replace(normPathname.begin(), normPathname.end(), *altsep.c_str(), *sep.c_str());
1835 
1836  if (normPathname.substr(0, 2) == sepsep && normPathname.substr(2, 1) != sep) {
1837  // is a UNC path:
1838  // vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1839  // \\machine\mountpoint\directory\etc\...
1840  // directory ^^^^^^^^^^^^^^^
1841  size_t index = normPathname.find(sep, 2);
1842  if (index == std::string::npos) {
1843  return std::pair<std::string, std::string>("", pathname);
1844  }
1845 
1846  size_t index2 = normPathname.find(sep, index + 1);
1847  //# a UNC path can't have two slashes in a row
1848  //# (after the initial two)
1849  if (index2 == index + 1) {
1850  return std::pair<std::string, std::string>("", pathname);
1851  }
1852 
1853  if (index2 == std::string::npos) {
1854  index2 = pathname.size();
1855  }
1856 
1857  return std::pair<std::string, std::string>(pathname.substr(0, index2), pathname.substr(index2));
1858  }
1859 
1860  if (normPathname[1] == ':') {
1861  return std::pair<std::string, std::string>(pathname.substr(0, 2), pathname.substr(2));
1862  }
1863  }
1864 
1865  return std::pair<std::string, std::string>("", pathname);
1866 #endif
1867 }
1868 
1917 std::vector<std::string> vpIoTools::splitChain(const std::string &chain, const std::string &sep)
1918 {
1919  size_t startIndex = 0;
1920 
1921  std::string chainToSplit = chain;
1922  std::vector<std::string> subChain;
1923  size_t sepIndex = chainToSplit.find(sep);
1924 
1925  while (sepIndex != std::string::npos) {
1926  std::string sub = chainToSplit.substr(startIndex, sepIndex);
1927  if (!sub.empty())
1928  subChain.push_back(sub);
1929  chainToSplit = chainToSplit.substr(sepIndex + 1, chain.size() - 1);
1930 
1931  sepIndex = chainToSplit.find(sep);
1932  }
1933  if (!chainToSplit.empty())
1934  subChain.push_back(chainToSplit);
1935 
1936  return subChain;
1937 }
1938 
1946 std::vector<std::string> vpIoTools::getDirFiles(const std::string &pathname)
1947 {
1948 
1949  if (!checkDirectory(pathname)) {
1950  throw(vpIoException(vpException::fatalError, "Directory %s doesn't exist'", pathname.c_str()));
1951  }
1952  std::string dirName = path(pathname);
1953 
1954 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1955 
1956  std::vector<std::string> files;
1957  struct dirent **list = NULL;
1958  int filesCount = scandir(dirName.c_str(), &list, NULL, NULL);
1959  if (filesCount == -1) {
1960  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1961  }
1962  for (int i = 0; i < filesCount; i++) {
1963  std::string fileName = list[i]->d_name;
1964  if (fileName != "." && fileName != "..") {
1965  files.push_back(fileName);
1966  }
1967  free(list[i]);
1968  }
1969  free(list);
1970  std::sort(files.begin(), files.end());
1971  return files;
1972 
1973 #elif defined(_WIN32)
1974 #if (!defined(WINRT))
1975 
1976  std::vector<std::string> files;
1977  std::string fileMask = dirName;
1978  fileMask.append("\\*");
1979  WIN32_FIND_DATA FindFileData;
1980  HANDLE hFind = FindFirstFile(fileMask.c_str(), &FindFileData);
1981  // Directory is empty
1982  if (HandleToLong(&hFind) == ERROR_FILE_NOT_FOUND) {
1983  return files;
1984  }
1985  if (hFind == INVALID_HANDLE_VALUE) {
1986  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1987  }
1988  do {
1989  std::string fileName = FindFileData.cFileName;
1990  if (fileName != "." && fileName != "..") {
1991  files.push_back(fileName);
1992  }
1993  } while (FindNextFile(hFind, &FindFileData));
1994  FindClose(hFind);
1995  std::sort(files.begin(), files.end());
1996  return files;
1997 
1998 #else
2000  "Cannot read files of directory %s: not implemented on "
2001  "Universal Windows Platform",
2002  dirName.c_str()));
2003 #endif
2004 #endif
2005 }
2006 
2010 void vpIoTools::readBinaryValueLE(std::ifstream &file, int16_t &short_value)
2011 {
2012  file.read((char *)(&short_value), sizeof(short_value));
2013 
2014 #ifdef VISP_BIG_ENDIAN
2015  // Swap bytes order from little endian to big endian
2016  short_value = vpEndian::swap16bits((uint16_t)short_value);
2017 #endif
2018 }
2019 
2023 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint16_t &ushort_value)
2024 {
2025  file.read((char *)(&ushort_value), sizeof(ushort_value));
2026 
2027 #ifdef VISP_BIG_ENDIAN
2028  // Swap bytes order from little endian to big endian
2029  ushort_value = vpEndian::swap16bits(ushort_value);
2030 #endif
2031 }
2032 
2036 void vpIoTools::readBinaryValueLE(std::ifstream &file, int32_t &int_value)
2037 {
2038  file.read((char *)(&int_value), sizeof(int_value));
2039 
2040 #ifdef VISP_BIG_ENDIAN
2041  // Swap bytes order from little endian to big endian
2042  int_value = vpEndian::swap32bits((uint32_t)int_value);
2043 #endif
2044 }
2045 
2049 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint32_t &uint_value)
2050 {
2051  file.read((char *)(&uint_value), sizeof(uint_value));
2052 
2053 #ifdef VISP_BIG_ENDIAN
2054  // Swap bytes order from little endian to big endian
2055  uint_value = vpEndian::swap32bits(uint_value);
2056 #endif
2057 }
2058 
2062 void vpIoTools::readBinaryValueLE(std::ifstream &file, float &float_value)
2063 {
2064  file.read((char *)(&float_value), sizeof(float_value));
2065 
2066 #ifdef VISP_BIG_ENDIAN
2067  // Swap bytes order from little endian to big endian
2068  float_value = vpEndian::swapFloat(float_value);
2069 #endif
2070 }
2071 
2075 void vpIoTools::readBinaryValueLE(std::ifstream &file, double &double_value)
2076 {
2077  file.read((char *)(&double_value), sizeof(double_value));
2078 
2079 #ifdef VISP_BIG_ENDIAN
2080  // Swap bytes order from little endian to big endian
2081  double_value = vpEndian::swapDouble(double_value);
2082 #endif
2083 }
2084 
2088 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
2089 {
2090 #ifdef VISP_BIG_ENDIAN
2091  // Swap bytes order to little endian
2092  uint16_t swap_short = vpEndian::swap16bits((uint16_t)short_value);
2093  file.write((char *)(&swap_short), sizeof(swap_short));
2094 #else
2095  file.write((char *)(&short_value), sizeof(short_value));
2096 #endif
2097 }
2098 
2102 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint16_t ushort_value)
2103 {
2104 #ifdef VISP_BIG_ENDIAN
2105  // Swap bytes order to little endian
2106  uint16_t swap_ushort = vpEndian::swap16bits(ushort_value);
2107  file.write((char *)(&swap_ushort), sizeof(swap_ushort));
2108 #else
2109  file.write((char *)(&ushort_value), sizeof(ushort_value));
2110 #endif
2111 }
2112 
2116 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int32_t int_value)
2117 {
2118 #ifdef VISP_BIG_ENDIAN
2119  // Swap bytes order to little endian
2120  uint32_t swap_int = vpEndian::swap32bits((uint32_t)int_value);
2121  file.write((char *)(&swap_int), sizeof(swap_int));
2122 #else
2123  file.write((char *)(&int_value), sizeof(int_value));
2124 #endif
2125 }
2126 
2130 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint32_t uint_value)
2131 {
2132 #ifdef VISP_BIG_ENDIAN
2133  // Swap bytes order to little endian
2134  uint32_t swap_int = vpEndian::swap32bits(uint_value);
2135  file.write((char *)(&swap_int), sizeof(swap_int));
2136 #else
2137  file.write((char *)(&uint_value), sizeof(uint_value));
2138 #endif
2139 }
2140 
2144 void vpIoTools::writeBinaryValueLE(std::ofstream &file, float float_value)
2145 {
2146 #ifdef VISP_BIG_ENDIAN
2147  // Swap bytes order to little endian
2148  float swap_float = vpEndian::swapFloat(float_value);
2149  file.write((char *)(&swap_float), sizeof(swap_float));
2150 #else
2151  file.write((char *)(&float_value), sizeof(float_value));
2152 #endif
2153 }
2154 
2158 void vpIoTools::writeBinaryValueLE(std::ofstream &file, double double_value)
2159 {
2160 #ifdef VISP_BIG_ENDIAN
2161  // Swap bytes order to little endian
2162  double swap_double = vpEndian::swapDouble(double_value);
2163  file.write((char *)(&swap_double), sizeof(swap_double));
2164 #else
2165  file.write((char *)(&double_value), sizeof(double_value));
2166 #endif
2167 }
2168 
2169 bool vpIoTools::parseBoolean(std::string input)
2170 {
2171  std::transform(input.begin(), input.end(), input.begin(), ::tolower);
2172  std::istringstream is(input);
2173  bool b;
2174  // Parse string to boolean either in the textual representation
2175  // (True/False) or in numeric representation (1/0)
2176  is >> (input.size() > 1 ? std::boolalpha : std::noboolalpha) >> b;
2177  return b;
2178 }
2179 
2183 std::string vpIoTools::trim(std::string s) { return ltrim(rtrim(s)); }
unsigned int getCols() const
Definition: vpArray2D.h:281
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:306
unsigned int getRows() const
Definition: vpArray2D.h:291
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
static vpColor getColor(const unsigned int &i)
Definition: vpColor.h:313
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ notImplementedError
Not implemented.
Definition: vpException.h:93
@ fatalError
Fatal error.
Definition: vpException.h:96
Error that can be emited by the vpIoTools class and its derivates.
Definition: vpIoException.h:73
static void getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
Definition: vpIoTools.cpp:378
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1368
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1917
static std::vector< std::string > configVars
Definition: vpIoTools.h:256
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:1006
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1645
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:800
static bool readConfigVar(const std::string &var, float &value)
Definition: vpIoTools.cpp:1095
static void setBaseName(const std::string &s)
Definition: vpIoTools.cpp:232
static std::pair< std::string, std::string > splitDrive(const std::string &pathname)
Definition: vpIoTools.cpp:1772
static bool isSamePathname(const std::string &pathname1, const std::string &pathname2)
Definition: vpIoTools.cpp:1752
static std::string getTempPath()
Definition: vpIoTools.cpp:194
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1728
static void setBaseDir(const std::string &dir)
Definition: vpIoTools.cpp:239
static std::string baseDir
Definition: vpIoTools.h:254
static bool loadConfigFile(const std::string &confFile)
Definition: vpIoTools.cpp:1046
static bool copy(const std::string &src, const std::string &dst)
Definition: vpIoTools.cpp:842
static std::string trim(std::string s)
Definition: vpIoTools.cpp:2183
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
Definition: vpIoTools.cpp:2010
static void saveConfigFile(const bool &actuallySave=true)
Definition: vpIoTools.cpp:1346
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:418
static bool rename(const std::string &oldfilename, const std::string &newfilename)
Definition: vpIoTools.cpp:988
static bool parseBoolean(std::string input)
Definition: vpIoTools.cpp:2169
static long getIndex(const std::string &filename, const std::string &format)
Definition: vpIoTools.cpp:1577
static std::string getUserName()
Definition: vpIoTools.cpp:314
static std::string getFullName()
Definition: vpIoTools.cpp:253
static void addNameElement(const std::string &strTrue, const bool &cond=true, const std::string &strFalse="")
Definition: vpIoTools.cpp:1292
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1687
static std::string getenv(const std::string &env)
Definition: vpIoTools.cpp:351
static const std::string & getBuildInformation()
Definition: vpIoTools.cpp:135
static std::string getBaseName()
Definition: vpIoTools.cpp:246
static std::string getFileExtension(const std::string &pathname, bool checkFile=false)
Definition: vpIoTools.cpp:1433
static std::string baseName
Definition: vpIoTools.h:253
static void createBaseNamePath(const bool &empty=false)
Definition: vpIoTools.cpp:1327
static std::vector< std::string > getDirFiles(const std::string &dirname)
Definition: vpIoTools.cpp:1946
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:568
static std::string configFile
Definition: vpIoTools.h:255
static std::vector< std::string > configValues
Definition: vpIoTools.h:257
static void writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
Definition: vpIoTools.cpp:2088
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:929
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:1536
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:726
static bool checkFifo(const std::string &filename)
Definition: vpIoTools.cpp:478
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1620
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1514
static const char separator
Definition: vpIoTools.h:186
static void makeFifo(const std::string &dirname)
Definition: vpIoTools.cpp:619
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:179
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