Visual Servoing Platform  version 3.5.1 under development (2023-03-14)
vpIoTools.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2022 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  *****************************************************************************/
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 std::string vpIoTools::baseName = "";
98 std::string vpIoTools::baseDir = "";
99 std::string vpIoTools::configFile = "";
100 std::vector<std::string> vpIoTools::configVars = std::vector<std::string>();
101 std::vector<std::string> vpIoTools::configValues = std::vector<std::string>();
102 
103 namespace
104 {
105 // The following code is not working on iOS since wordexp() is not available
106 // The function is not used on Android
107 #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
108 #if (TARGET_OS_IOS == 0) && !defined(__ANDROID__)
109 void replaceAll(std::string &str, const std::string &search, const std::string &replace)
110 {
111  size_t start_pos = 0;
112  while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
113  str.replace(start_pos, search.length(), replace);
114  start_pos += replace.length(); // Handles case where 'replace' is a
115  // substring of 'search'
116  }
117 }
118 #endif
119 #endif
120 
121 std::string &ltrim(std::string &s)
122 {
123 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
124  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
125 #else
126  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
127 #endif
128  return s;
129 }
130 
131 std::string &rtrim(std::string &s)
132 {
133 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
134  s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
135 #else
136  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
137 #endif
138  return s;
139 }
140 } // namespace
141 
145 const std::string &vpIoTools::getBuildInformation()
146 {
147  static std::string build_info =
148 #include "version_string.inc"
149  ;
150  return build_info;
151 }
152 
205 {
206 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
207  std::string username;
208  vpIoTools::getUserName(username);
209  return "/tmp/" + username;
210 #elif defined(_WIN32) && !defined(WINRT)
211  // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file
212  // Gets the temp path env string (no guarantee it's a valid path).
213  TCHAR lpTempPathBuffer[MAX_PATH];
214  DWORD dwRetVal = GetTempPath(MAX_PATH /* length of the buffer */, lpTempPathBuffer /* buffer for path */);
215  if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
216  throw vpIoException(vpIoException::cantGetenv, "Error with GetTempPath() call!");
217  }
218  std::string temp_path(lpTempPathBuffer);
219  if (!temp_path.empty()) {
220  if (temp_path.back() == '\\') {
221  temp_path.resize(temp_path.size() - 1);
222  }
223  } else {
224  temp_path = "C:\temp";
225  try {
226  vpIoTools::makeDirectory(temp_path);
227  } catch (...) {
228  throw(vpException(vpException::fatalError, "Cannot set temp path to %s", temp_path.c_str()));
229  }
230  }
231  return temp_path;
232 #else
233  throw vpIoException(vpException::fatalError, "Not implemented on this platform!");
234 #endif
235 }
236 
242 void vpIoTools::setBaseName(const std::string &s) { baseName = s; }
243 
249 void vpIoTools::setBaseDir(const std::string &dir) { baseDir = dir + "/"; }
250 
256 std::string vpIoTools::getBaseName() { return baseName; }
257 
263 std::string vpIoTools::getFullName() { return baseDir + baseName; }
264 
278 void vpIoTools::getUserName(std::string &username)
279 {
280 // With MinGW, UNIX and _WIN32 are defined
281 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
282  // Get the user name.
283  char *_username = ::getenv("LOGNAME");
284  if (!_username) {
285  username = "unknown";
286  } else {
287  username = _username;
288  }
289 #elif defined(_WIN32)
290 #if (!defined(WINRT))
291  unsigned int info_buffer_size = 1024;
292  TCHAR *infoBuf = new TCHAR[info_buffer_size];
293  DWORD bufCharCount = (DWORD)info_buffer_size;
294  // Get the user name.
295  if (!GetUserName(infoBuf, &bufCharCount)) {
296  username = "unknown";
297  } else {
298  username = infoBuf;
299  }
300  delete[] infoBuf;
301 #else
302  // Universal platform
303  username = "unknown";
304 #endif
305 #else
306  username = "unknown";
307 #endif
308 }
309 
325 {
326  std::string username;
327  getUserName(username);
328  return username;
329 }
330 
361 std::string vpIoTools::getenv(const std::string &env)
362 {
363 #if defined(_WIN32) && defined(WINRT)
364  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value: not "
365  "implemented on Universal Windows Platform"));
366 #else
367  std::string value;
368  // Get the environment variable value.
369  char *_value = ::getenv(env.c_str());
370  if (!_value) {
371  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value"));
372  }
373  value = _value;
374 
375  return value;
376 #endif
377 }
378 
388 void vpIoTools::getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
389 {
390  if (version.size() == 0) {
391  major = 0;
392  minor = 0;
393  patch = 0;
394  } else {
395  size_t major_pos = version.find('.');
396  std::string major_str = version.substr(0, major_pos);
397  major = static_cast<unsigned>(atoi(major_str.c_str()));
398 
399  if (major_pos != std::string::npos) {
400  size_t minor_pos = version.find('.', major_pos + 1);
401  std::string minor_str = version.substr(major_pos + 1, (minor_pos - (major_pos + 1)));
402  minor = static_cast<unsigned>(atoi(minor_str.c_str()));
403 
404  if (minor_pos != std::string::npos) {
405  std::string patch_str = version.substr(minor_pos + 1);
406  patch = static_cast<unsigned>(atoi(patch_str.c_str()));
407  } else {
408  patch = 0;
409  }
410  } else {
411  minor = 0;
412  patch = 0;
413  }
414  }
415 }
416 
428 bool vpIoTools::checkDirectory(const std::string &dirname)
429 {
430 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
431  struct stat stbuf;
432 #elif defined(_WIN32) && defined(__MINGW32__)
433  struct stat stbuf;
434 #elif defined(_WIN32)
435  struct _stat stbuf;
436 #endif
437 
438  if (dirname.empty()) {
439  return false;
440  }
441 
442  std::string _dirname = path(dirname);
443 
444 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
445  if (stat(_dirname.c_str(), &stbuf) != 0)
446 #elif defined(_WIN32) && defined(__MINGW32__)
447  // Remove trailing separator character if any
448  // AppVeyor: Windows 6.3.9600 AMD64 ; C:/MinGW/bin/g++.exe (ver 5.3.0) ;
449  // GNU Make 3.82.90 Built for i686-pc-mingw32
450  if (_dirname.at(_dirname.size() - 1) == vpIoTools::separator)
451  _dirname = _dirname.substr(0, _dirname.size() - 1);
452  if (stat(_dirname.c_str(), &stbuf) != 0)
453 #elif defined(_WIN32)
454  if (_stat(_dirname.c_str(), &stbuf) != 0)
455 #endif
456  {
457  return false;
458  }
459 #if defined(_WIN32) || (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
460  if ((stbuf.st_mode & S_IFDIR) == 0)
461 #endif
462  {
463  return false;
464  }
465 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
466  if ((stbuf.st_mode & S_IWUSR) == 0)
467 #elif defined(_WIN32)
468  if ((stbuf.st_mode & S_IWRITE) == 0)
469 #endif
470  {
471  return false;
472  }
473  return true;
474 }
475 
488 bool vpIoTools::checkFifo(const std::string &fifofilename)
489 {
490 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
491  struct stat stbuf;
492 
493  std::string _filename = path(fifofilename);
494  if (stat(_filename.c_str(), &stbuf) != 0) {
495  return false;
496  }
497  if ((stbuf.st_mode & S_IFIFO) == 0) {
498  return false;
499  }
500  if ((stbuf.st_mode & S_IRUSR) == 0)
501 
502  {
503  return false;
504  }
505  return true;
506 #elif defined(_WIN32)
507  (void)fifofilename;
508  throw(vpIoException(vpIoException::notImplementedError, "Fifo files are not supported on Windows platforms."));
509 #endif
510 }
511 
512 #ifndef DOXYGEN_SHOULD_SKIP_THIS
513 // See:
514 // https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950
515 int vpIoTools::mkdir_p(const char *path, int mode)
516 {
517  /* Adapted from http://stackoverflow.com/a/2336245/119527 */
518  const size_t len = strlen(path);
519  char _path[PATH_MAX];
520  const char sep = vpIoTools::separator;
521 
522  std::fill(_path, _path + PATH_MAX, 0);
523 
524  errno = 0;
525  if (len > sizeof(_path) - 1) {
526  errno = ENAMETOOLONG;
527  return -1;
528  }
529  /* Copy string so its mutable */
530  strcpy(_path, path);
531 
532  /* Iterate over the string */
533  for (char *p = _path + 1; *p; p++) { // path cannot be empty
534  if (*p == sep) {
535  /* Temporarily truncate */
536  *p = '\0';
537 
538 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
539  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
540 #elif defined(_WIN32)
541  (void)mode; // var not used
542  if (!checkDirectory(_path) && _mkdir(_path) != 0)
543 #endif
544  {
545  if (errno != EEXIST)
546  return -1;
547  }
548  *p = sep;
549  }
550  }
551 
552 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
553  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
554 #elif defined(_WIN32)
555  if (_mkdir(_path) != 0)
556 #endif
557  {
558  if (errno != EEXIST)
559  return -1;
560  }
561 
562  return 0;
563 }
564 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
565 
578 void vpIoTools::makeDirectory(const std::string &dirname)
579 {
580 #if ((!defined(__unix__) && !defined(__unix) && (!defined(__APPLE__) || !defined(__MACH__)))) && !defined(_WIN32)
581  std::cerr << "Unsupported platform for vpIoTools::makeDirectory()!" << std::endl;
582  return;
583 #endif
584 
585 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
586  struct stat stbuf;
587 #elif defined(_WIN32) && defined(__MINGW32__)
588  struct stat stbuf;
589 #elif defined(_WIN32)
590  struct _stat stbuf;
591 #endif
592 
593  if (dirname.empty()) {
594  throw(vpIoException(vpIoException::invalidDirectoryName, "invalid directory name"));
595  }
596 
597  std::string _dirname = path(dirname);
598 
599 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
600  if (stat(_dirname.c_str(), &stbuf) != 0)
601 #elif defined(_WIN32) && defined(__MINGW32__)
602  if (stat(_dirname.c_str(), &stbuf) != 0)
603 #elif defined(_WIN32)
604  if (_stat(_dirname.c_str(), &stbuf) != 0)
605 #endif
606  {
607  if (vpIoTools::mkdir_p(_dirname.c_str(), 0755) != 0) {
608  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
609  }
610  }
611 
612  if (checkDirectory(dirname) == false) {
613  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
614  }
615 }
616 
629 void vpIoTools::makeFifo(const std::string &fifoname)
630 {
631 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
632 
633  // If dirname is a directory, we throw an error
634  if (vpIoTools::checkDirectory(fifoname)) {
636  "Unable to create fifo file. '%s' is an existing directory.", fifoname.c_str()));
637  }
638 
639  // If dirname refers to an already existing file, we throw an error
640  else if (vpIoTools::checkFilename(fifoname)) {
641  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. File already exists.",
642  fifoname.c_str()));
643  // If dirname refers to an already existing fifo, we throw an error
644  } else if (vpIoTools::checkFifo(fifoname)) {
645  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. Fifo already exists.",
646  fifoname.c_str()));
647  }
648 
649  else if (mkfifo(fifoname.c_str(), 0666) < 0) {
650  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo file '%s'.", fifoname.c_str()));
651  }
652 #elif defined(_WIN32)
653  (void)fifoname;
654  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo on Windows platforms."));
655 #endif
656 }
657 
658 #if defined(_WIN32) && !defined(WINRT)
659 std::string getUuid()
660 {
661  UUID uuid;
662  if (UuidCreate(&uuid) != RPC_S_OK) {
663  throw(vpIoException(vpIoException::fatalError, "UuidCreate() failed!"));
664  }
665 
666  RPC_CSTR stringUuid;
667  if (UuidToString(&uuid, &stringUuid) != RPC_S_OK) {
668  throw(vpIoException(vpIoException::fatalError, "UuidToString() failed!"));
669  }
670 
671  return reinterpret_cast<char *>(stringUuid);
672 }
673 #endif
674 
731 std::string vpIoTools::makeTempDirectory(const std::string &dirname)
732 {
733 #if defined(WINRT) || !defined(_WIN32) && !(defined(__unix__) || defined(__unix) || \
734  (defined(__APPLE__) && defined(__MACH__))) // not UNIX and not Windows
735  throw(vpIoException(vpIoException::cantCreateDirectory, "makeTempDirectory() is not supported on this platform!"));
736 #endif
737 
738  std::string dirname_cpy = std::string(dirname);
739  std::string correctEnding = "XXXXXX";
740 
741  // If dirname is an unexisting directory, it should end with XXXXXX in order to create a temp directory
742  if (!vpIoTools::checkDirectory(dirname_cpy)) {
743 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
744  // Check if dirname ends with XXXXXX
745  if (dirname_cpy.rfind(correctEnding) == std::string::npos) {
746  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
747  dirname_cpy = dirname_cpy + "/";
748  }
749  try {
750  vpIoTools::makeDirectory(dirname_cpy);
751  } catch (const vpException &e) {
752  throw e;
753  }
754 
755  dirname_cpy = dirname_cpy + "XXXXXX";
756  }
757 
758 #elif defined(_WIN32) && !defined(WINRT)
759  // Remove XXXXXX
760  dirname_cpy = dirname_cpy.substr(0, dirname_cpy.rfind(correctEnding));
761  // Append UUID
762  dirname_cpy = dirname_cpy + getUuid();
763 #endif
764 
765  } else {
766  // If dirname is an existing directory, we create a temp directory inside
767 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
768  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
769  dirname_cpy = dirname_cpy + "/";
770  }
771  dirname_cpy = dirname_cpy + "XXXXXX";
772 #elif defined(_WIN32) && !defined(WINRT)
773  dirname_cpy = createFilePath(dirname_cpy, getUuid());
774 #endif
775  }
776 
777 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
778  char *dirname_char = new char[dirname_cpy.length() + 1];
779  strcpy(dirname_char, dirname_cpy.c_str());
780 
781  char *computedDirname = mkdtemp(dirname_char);
782 
783  if (!computedDirname) {
784  delete[] dirname_char;
785  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'.", dirname_cpy.c_str()));
786  }
787 
788  std::string res(computedDirname);
789  delete[] dirname_char;
790  return res;
791 #elif defined(_WIN32) && !defined(WINRT)
792  makeDirectory(dirname_cpy);
793  return dirname_cpy;
794 #endif
795 }
796 
807 bool vpIoTools::checkFilename(const std::string &filename)
808 {
809 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
810  struct stat stbuf;
811 #elif defined(_WIN32)
812  struct _stat stbuf;
813 #endif
814 
815  if (filename.empty()) {
816  return false;
817  }
818 
819  std::string _filename = path(filename);
820 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
821  if (stat(_filename.c_str(), &stbuf) != 0)
822 #elif defined(_WIN32)
823  if (_stat(_filename.c_str(), &stbuf) != 0)
824 #endif
825  {
826  return false;
827  }
828  if ((stbuf.st_mode & S_IFREG) == 0) {
829  return false;
830  }
831 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
832  if ((stbuf.st_mode & S_IRUSR) == 0)
833 #elif defined(_WIN32)
834  if ((stbuf.st_mode & S_IREAD) == 0)
835 #endif
836  {
837  return false;
838  }
839  return true;
840 }
841 
849 bool vpIoTools::copy(const std::string &src, const std::string &dst)
850 {
851  // Check if we have to consider a file or a directory
852  if (vpIoTools::checkFilename(src)) {
853 // std::cout << "copy file: " << src << " in " << dst << std::endl;
854 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
855 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
856  // wordexp() is not available
857  std::stringstream cmd;
858  cmd << "cp -p ";
859  cmd << src;
860  cmd << " ";
861  cmd << dst;
862  int ret = system(cmd.str().c_str());
863  if (ret) {
864  }; // to avoid a warning
865  // std::cout << cmd << " return value: " << ret << std::endl;
866  return true;
867 #else
868  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
869  dst.c_str()));
870 #endif
871 #elif defined(_WIN32)
872 #if (!defined(WINRT))
873  std::stringstream cmd;
874  cmd << "copy ";
875  cmd << vpIoTools::path(src);
876  cmd << " ";
877  cmd << vpIoTools::path(dst);
878  int ret = system(cmd.str().c_str());
879  if (ret) {
880  }; // to avoid a warning
881  // std::cout << cmd << " return value: " << ret << std::endl;
882  return true;
883 #else
884  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
885  src.c_str(), dst.c_str()));
886 #endif
887 #endif
888  } else if (vpIoTools::checkDirectory(src)) {
889 // std::cout << "copy directory: " << src << " in " << dst << std::endl;
890 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
891 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
892  // wordexp() is not available
893  std::stringstream cmd;
894  cmd << "cp -p ";
895  cmd << src;
896  cmd << " ";
897  cmd << dst;
898  int ret = system(cmd.str().c_str());
899  if (ret) {
900  }; // to avoid a warning
901  // std::cout << cmd << " return value: " << ret << std::endl;
902  return true;
903 #else
904  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
905  dst.c_str()));
906 #endif
907 #elif defined(_WIN32)
908 #if (!defined(WINRT))
909  std::stringstream cmd;
910  cmd << "copy ";
911  cmd << vpIoTools::path(src);
912  cmd << " ";
913  cmd << vpIoTools::path(dst);
914  int ret = system(cmd.str().c_str());
915  if (ret) {
916  }; // to avoid a warning
917  // std::cout << cmd << " return value: " << ret << std::endl;
918  return true;
919 #else
920  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
921  src.c_str(), dst.c_str()));
922 #endif
923 #endif
924  } else {
925  std::cout << "Cannot copy: " << src << " in " << dst << std::endl;
926  return false;
927  }
928 }
929 
940 bool vpIoTools::remove(const std::string &file_or_dir)
941 {
942  // Check if we have to consider a file or a directory
943  if (vpIoTools::checkFilename(file_or_dir)
944 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
945  || vpIoTools::checkFifo(std::string(file_or_dir))
946 #endif
947  ) {
948  // std::cout << "remove file: " << file_or_dir << std::endl;
949  if (::remove(file_or_dir.c_str()) != 0)
950  return false;
951  else
952  return true;
953  } else if (vpIoTools::checkDirectory(file_or_dir)) {
954 // std::cout << "remove directory: " << file_or_dir << std::endl;
955 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
956 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
957  // wordexp() is not available
958  std::stringstream cmd;
959  cmd << "rm -rf \"";
960  cmd << file_or_dir;
961  cmd << "\"";
962  int ret = system(cmd.str().c_str());
963  if (ret) {
964  }; // to avoid a warning
965  // std::cout << cmd << " return value: " << ret << std::endl;
966  return true;
967 #else
968  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on iOS Platform",
969  file_or_dir.c_str()));
970 #endif
971 #elif defined(_WIN32)
972 #if (!defined(WINRT))
973  std::stringstream cmd;
974  cmd << "rmdir /S /Q ";
975  cmd << vpIoTools::path(file_or_dir);
976  cmd << "\"";
977  int ret = system(cmd.str().c_str());
978  if (ret) {
979  }; // to avoid a warning
980  // std::cout << cmd << " return value: " << ret << std::endl;
981  return true;
982 #else
983  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on Universal Windows Platform",
984  file_or_dir.c_str()));
985 #endif
986 #endif
987  } else {
988  std::cout << "Cannot remove: " << file_or_dir << std::endl;
989  return false;
990  }
991 }
992 
1002 bool vpIoTools::rename(const std::string &oldfilename, const std::string &newfilename)
1003 {
1004  if (::rename(oldfilename.c_str(), newfilename.c_str()) != 0)
1005  return false;
1006  else
1007  return true;
1008 }
1009 
1020 std::string vpIoTools::path(const std::string &pathname)
1021 {
1022  std::string path(pathname);
1023 
1024 #if defined(_WIN32)
1025  for (unsigned int i = 0; i < path.length(); i++)
1026  if (path[i] == '/')
1027  path[i] = '\\';
1028 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
1029  for (unsigned int i = 0; i < path.length(); i++)
1030  if (path[i] == '\\')
1031  path[i] = '/';
1032 #if TARGET_OS_IOS == 0 // The following code is not working on iOS and android since
1033  // wordexp() is not available
1034 #ifdef __ANDROID__
1035 // Do nothing
1036 #else
1037  wordexp_t exp_result;
1038 
1039  // escape quote character
1040  replaceAll(path, "'", "'\\''");
1041  // add quotes to handle special characters like parentheses and spaces
1042  wordexp(std::string("'" + path + "'").c_str(), &exp_result, 0);
1043  path = exp_result.we_wordc == 1 ? exp_result.we_wordv[0] : "";
1044  wordfree(&exp_result);
1045 #endif
1046 #endif
1047 #endif
1048 
1049  return path;
1050 }
1051 
1060 bool vpIoTools::loadConfigFile(const std::string &confFile)
1061 {
1062  configFile = path(confFile);
1063  configVars.clear();
1064  configValues.clear();
1065  std::ifstream confContent(configFile.c_str(), std::ios::in);
1066 
1067  if (confContent.is_open()) {
1068  std::string line, var, val;
1069  long unsigned int k;
1070  int c;
1071  std::string stop[3] = {" ", "\t", "#"};
1072  while (std::getline(confContent, line)) {
1073  if ((line.compare(0, 1, "#") != 0) && (line.size() > 2)) {
1074  try {
1075  // name of the variable
1076  k = static_cast<unsigned long>(line.find(" "));
1077  var = line.substr(0, k);
1078  // look for the end of the actual value
1079  c = 200;
1080  for (unsigned i = 0; i < 3; ++i)
1081  c = vpMath::minimum(c,
1082  static_cast<int>(line.find(stop[i], static_cast<size_t>(k) + static_cast<size_t>(1))));
1083  if (c == -1)
1084  c = static_cast<int>(line.size());
1085  long unsigned int c_ = static_cast<long unsigned int>(c);
1086  val = line.substr(static_cast<size_t>(k) + static_cast<size_t>(1),
1087  static_cast<size_t>(c_) - static_cast<size_t>(k) - static_cast<size_t>(1));
1088  configVars.push_back(var);
1089  configValues.push_back(val);
1090  } catch (...) {
1091  }
1092  }
1093  }
1094  confContent.close();
1095  } else {
1096  return false;
1097  }
1098  return true;
1099 }
1100 
1109 bool vpIoTools::readConfigVar(const std::string &var, float &value)
1110 {
1111  bool found = false;
1112  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1113  if (configVars[k] == var) {
1114  if (configValues[k].compare("PI") == 0)
1115  value = static_cast<float>(M_PI);
1116  else if (configValues[k].compare("PI/2") == 0)
1117  value = static_cast<float>(M_PI / 2.0);
1118  else if (configValues[k].compare("-PI/2") == 0)
1119  value = static_cast<float>(-M_PI / 2.0);
1120  else
1121  value = static_cast<float>(atof(configValues[k].c_str()));
1122  found = true;
1123  }
1124  }
1125  if (found == false)
1126  std::cout << var << " not found in config file" << std::endl;
1127  return found;
1128 }
1137 bool vpIoTools::readConfigVar(const std::string &var, double &value)
1138 {
1139  bool found = false;
1140  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1141  if (configVars[k] == var) {
1142  if (configValues[k].compare("PI") == 0)
1143  value = M_PI;
1144  else if (configValues[k].compare("PI/2") == 0)
1145  value = M_PI / 2;
1146  else if (configValues[k].compare("-PI/2") == 0)
1147  value = -M_PI / 2;
1148  else
1149  value = atof(configValues[k].c_str());
1150  found = true;
1151  }
1152  }
1153  if (found == false)
1154  std::cout << var << " not found in config file" << std::endl;
1155  return found;
1156 }
1157 
1166 bool vpIoTools::readConfigVar(const std::string &var, int &value)
1167 {
1168  bool found = false;
1169  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1170  if (configVars[k] == var) {
1171  value = atoi(configValues[k].c_str());
1172  found = true;
1173  }
1174  }
1175  if (found == false)
1176  std::cout << var << " not found in config file" << std::endl;
1177  return found;
1178 }
1179 
1188 bool vpIoTools::readConfigVar(const std::string &var, unsigned int &value)
1189 {
1190  int v = 0;
1191  bool found = readConfigVar(var, v);
1192  value = static_cast<unsigned int>(v);
1193  return found;
1194 }
1195 
1204 bool vpIoTools::readConfigVar(const std::string &var, bool &value)
1205 {
1206  int v = 0;
1207  bool found = readConfigVar(var, v);
1208  value = (v != 0);
1209  return found;
1210 }
1211 
1220 bool vpIoTools::readConfigVar(const std::string &var, vpColor &value)
1221 {
1222  unsigned int v = 0;
1223  bool found = readConfigVar(var, v);
1224  value = vpColor::getColor(v);
1225  return found;
1226 }
1227 
1236 bool vpIoTools::readConfigVar(const std::string &var, std::string &value)
1237 {
1238  bool found = false;
1239  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1240  if (configVars[k] == var) {
1241  value = configValues[k];
1242  found = true;
1243  }
1244  }
1245  if (found == false)
1246  std::cout << var << " not found in config file" << std::endl;
1247  return found;
1248 }
1249 
1263 bool vpIoTools::readConfigVar(const std::string &var, vpArray2D<double> &value, const unsigned int &nCols,
1264  const unsigned int &nRows)
1265 {
1266  bool found = false;
1267  std::string nb;
1268  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1269  if (configVars[k] == var) {
1270  found = true;
1271  // resize or not
1272  if (nCols != 0 && nRows != 0)
1273  value.resize(nRows, nCols);
1274  size_t ind = 0, ind2;
1275  for (unsigned int i = 0; i < value.getRows(); ++i)
1276  for (unsigned int j = 0; j < value.getCols(); ++j) {
1277  ind2 = configValues[k].find(",", ind);
1278  nb = configValues[k].substr(ind, ind2 - ind);
1279  if (nb.compare("PI") == 0)
1280  value[i][j] = M_PI;
1281  else if (nb.compare("PI/2") == 0)
1282  value[i][j] = M_PI / 2;
1283  else if (nb.compare("-PI/2") == 0)
1284  value[i][j] = -M_PI / 2;
1285  else
1286  value[i][j] = atof(nb.c_str());
1287  ind = ind2 + 1;
1288  }
1289  }
1290  }
1291  if (found == false)
1292  std::cout << var << " not found in config file" << std::endl;
1293  return found;
1294 }
1295 
1296 // construct experiment filename & path
1297 
1306 void vpIoTools::addNameElement(const std::string &strTrue, const bool &cond, const std::string &strFalse)
1307 {
1308  if (cond)
1309  baseName += "_" + strTrue;
1310  else if (strFalse != "")
1311  baseName += "_" + strFalse;
1312 }
1313 
1322 void vpIoTools::addNameElement(const std::string &strTrue, const double &val)
1323 {
1324  // if(val != 0.)
1325  if (std::fabs(val) < std::numeric_limits<double>::epsilon()) {
1326  std::stringstream valS;
1327  valS.precision(4);
1328  valS << val;
1329  baseName += "_" + strTrue + valS.str();
1330  }
1331 }
1332 
1341 void vpIoTools::createBaseNamePath(const bool &empty)
1342 {
1343  if (vpIoTools::checkDirectory(baseDir + baseName) == false) {
1345  std::cout << "creating directory " + baseDir + baseName << std::endl;
1346  } else {
1347  if (empty) {
1348  std::cout << "emptying directory " + baseDir + baseName << std::endl;
1350  }
1351  }
1352 }
1353 
1360 void vpIoTools::saveConfigFile(const bool &actuallySave)
1361 {
1362  if (actuallySave) {
1363  std::string dest = baseDir + "/" + baseName + "_config.txt";
1364  // file copy
1365  vpIoTools::copy(configFile, dest);
1366  }
1367 }
1368 
1383 {
1384  std::string data_path;
1385  std::string file_to_test("mbt/cube.cao");
1386  std::string filename;
1387  // Test if VISP_INPUT_IMAGE_PATH env var is set
1388  try {
1389  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH");
1390  filename = data_path + "/" + file_to_test;
1391  if (vpIoTools::checkFilename(filename))
1392  return data_path;
1393  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/ViSP-images";
1394  filename = data_path + "/" + file_to_test;
1395  if (vpIoTools::checkFilename(filename))
1396  return data_path;
1397  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/visp-images";
1398  filename = data_path + "/" + file_to_test;
1399  if (vpIoTools::checkFilename(filename))
1400  return data_path;
1401  } catch (...) {
1402  }
1403 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1404  // Test if visp-images-data package is installed (Ubuntu and Debian)
1405  data_path = "/usr/share/visp-images-data/ViSP-images";
1406  filename = data_path + "/" + file_to_test;
1407  if (vpIoTools::checkFilename(filename))
1408  return data_path;
1409  data_path = "/usr/share/visp-images-data/visp-images";
1410  filename = data_path + "/" + file_to_test;
1411  if (vpIoTools::checkFilename(filename))
1412  return data_path;
1413 #endif
1414  data_path = "";
1415  return data_path;
1416 }
1417 
1447 std::string vpIoTools::getFileExtension(const std::string &pathname, bool checkFile)
1448 {
1449  if (checkFile && (vpIoTools::checkDirectory(pathname) || !vpIoTools::checkFilename(pathname))) {
1450  return "";
1451  }
1452 
1453 #if defined(_WIN32)
1454  std::string sep = "\\";
1455  std::string altsep = "/";
1456  std::string extsep = ".";
1457 #else
1458  // On Unix, or on the Mac
1459  std::string sep = "/";
1460  std::string altsep = "";
1461  std::string extsep = ".";
1462 #endif
1463 
1464  // Python 2.7.8 module.
1465  //# Split a path in root and extension.
1466  //# The extension is everything starting at the last dot in the last
1467  //# pathname component; the root is everything before that.
1468  //# It is always true that root + ext == p.
1469  //
1470  //# Generic implementation of splitext, to be parametrized with
1471  //# the separators
1472  // def _splitext(p, sep, altsep, extsep):
1473  // """Split the extension from a pathname.
1474  //
1475  // Extension is everything from the last dot to the end, ignoring
1476  // leading dots. Returns "(root, ext)"; ext may be empty."""
1477  //
1478  // sepIndex = p.rfind(sep)
1479  // if altsep:
1480  // altsepIndex = p.rfind(altsep)
1481  // sepIndex = max(sepIndex, altsepIndex)
1482  //
1483  // dotIndex = p.rfind(extsep)
1484  // if dotIndex > sepIndex:
1485  // # skip all leading dots
1486  // filenameIndex = sepIndex + 1
1487  // while filenameIndex < dotIndex:
1488  // if p[filenameIndex] != extsep:
1489  // return p[:dotIndex], p[dotIndex:]
1490  // filenameIndex += 1
1491  //
1492  // return p, ''
1493 
1494  int sepIndex = static_cast<int>(pathname.rfind(sep));
1495  if (!altsep.empty()) {
1496  int altsepIndex = static_cast<int>(pathname.rfind(altsep));
1497  sepIndex = ((std::max))(sepIndex, altsepIndex);
1498  }
1499 
1500  size_t dotIndex = pathname.rfind(extsep);
1501  if (dotIndex != std::string::npos) {
1502  // The extsep character exists
1503  size_t npos = std::string::npos;
1504  if ((sepIndex != static_cast<int>(npos) && static_cast<int>(dotIndex) > sepIndex) ||
1505  sepIndex == static_cast<int>(npos)) {
1506  if (sepIndex == static_cast<int>(npos)) {
1507  sepIndex = 0;
1508  }
1509  size_t filenameIndex = static_cast<size_t>(sepIndex) + static_cast<size_t>(1);
1510 
1511  while (filenameIndex < dotIndex) {
1512  if (pathname.compare(filenameIndex, 1, extsep) != 0) {
1513  return pathname.substr(dotIndex);
1514  }
1515  filenameIndex++;
1516  }
1517  }
1518  }
1519 
1520  return "";
1521 }
1522 
1528 std::string vpIoTools::getName(const std::string &pathname)
1529 {
1530  if (pathname.size() > 0) {
1531  std::string convertedPathname = vpIoTools::path(pathname);
1532 
1533  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1534  if (index != std::string::npos) {
1535  return convertedPathname.substr(index + 1);
1536  }
1537 
1538  return convertedPathname;
1539  }
1540 
1541  return "";
1542 }
1543 
1550 std::string vpIoTools::getNameWE(const std::string &pathname)
1551 {
1552  std::string name = vpIoTools::getName(pathname);
1553  size_t found = name.find_last_of(".");
1554  std::string name_we = name.substr(0, found);
1555  return name_we;
1556 }
1557 
1591 long vpIoTools::getIndex(const std::string &filename, const std::string &format)
1592 {
1593  size_t indexBegin = format.find_last_of('%');
1594  size_t indexEnd = format.find_first_of('d', indexBegin);
1595  size_t suffixLength = format.length() - indexEnd - 1;
1596  // Extracting index
1597  if (filename.length() <= suffixLength + indexBegin) {
1598  return -1;
1599  }
1600  size_t indexLength = filename.length() - suffixLength - indexBegin;
1601  std::string indexSubstr = filename.substr(indexBegin, indexLength);
1602  std::istringstream ss(indexSubstr);
1603  long index = 0;
1604  ss >> index;
1605  if (ss.fail() || index < 0 || !ss.eof()) {
1606  return -1;
1607  }
1608 
1609  // Checking that format with inserted index equals filename
1610  char nameByFormat[FILENAME_MAX];
1611  snprintf(nameByFormat, FILENAME_MAX, format.c_str(), index);
1612  if (std::string(nameByFormat) != filename) {
1613  return -1;
1614  }
1615  return index;
1616 }
1617 
1633 std::string vpIoTools::getParent(const std::string &pathname)
1634 {
1635  if (pathname.size() > 0) {
1636  std::string convertedPathname = vpIoTools::path(pathname);
1637 
1638  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1639  if (index != std::string::npos) {
1640  return convertedPathname.substr(0, index);
1641  }
1642 
1643  return ".";
1644  } else {
1645  return "";
1646  }
1647 }
1648 
1657 std::string vpIoTools::getAbsolutePathname(const std::string &pathname)
1658 {
1659 
1660 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1661  std::string real_path_str = pathname;
1662  char *real_path = realpath(pathname.c_str(), NULL);
1663 
1664  if (real_path) {
1665  real_path_str = real_path;
1666  free(real_path);
1667  }
1668  return real_path_str;
1669 #elif defined(_WIN32)
1670 #if (!defined(WINRT))
1671  std::string real_path_str = pathname;
1672  DWORD retval = 0;
1673  TCHAR buffer[4096] = TEXT("");
1674 
1675  retval = GetFullPathName(pathname.c_str(), 4096, buffer, 0);
1676  if (retval != 0) {
1677  real_path_str = buffer;
1678  }
1679  return real_path_str;
1680 #else
1682  "Cannot get absolute path of %s: not implemented on "
1683  "Universal Windows Platform",
1684  pathname.c_str()));
1685 #endif
1686 #endif
1687 }
1688 
1699 std::string vpIoTools::createFilePath(const std::string &parent, const std::string &child)
1700 {
1701  if (child.size() == 0 && parent.size() == 0) {
1702  return "";
1703  }
1704 
1705  if (child.size() == 0) {
1706  return vpIoTools::path(parent);
1707  }
1708 
1709  if (parent.size() == 0) {
1710  return vpIoTools::path(child);
1711  }
1712 
1713  std::string convertedParent = vpIoTools::path(parent);
1714  std::string convertedChild = vpIoTools::path(child);
1715 
1716  std::stringstream ss;
1717  ss << vpIoTools::separator;
1718  std::string stringSeparator;
1719  ss >> stringSeparator;
1720 
1721  std::string lastConvertedParentChar = convertedParent.substr(convertedParent.size() - 1);
1722  std::string firstConvertedChildChar = convertedChild.substr(0, 1);
1723 
1724  if (lastConvertedParentChar == stringSeparator) {
1725  convertedParent = convertedParent.substr(0, convertedParent.size() - 1);
1726  }
1727 
1728  if (firstConvertedChildChar == stringSeparator) {
1729  convertedChild = convertedChild.substr(1);
1730  }
1731 
1732  return std::string(convertedParent + vpIoTools::separator + convertedChild);
1733 }
1734 
1740 bool vpIoTools::isAbsolutePathname(const std::string &pathname)
1741 {
1742  //# Inspired by the Python 2.7.8 module.
1743  //# Return whether a path is absolute.
1744  //# Trivial in Posix, harder on the Mac or MS-DOS.
1745  //# For DOS it is absolute if it starts with a slash or backslash (current
1746  //# volume), or if a pathname after the volume letter and colon / UNC
1747  // resource # starts with a slash or backslash.
1748  //
1749  // def isabs(s):
1750  // """Test whether a path is absolute"""
1751  // s = splitdrive(s)[1]
1752  // return s != '' and s[:1] in '/\\'
1753  std::string path = splitDrive(pathname).second;
1754  return path.size() > 0 && (path.substr(0, 1) == "/" || path.substr(0, 1) == "\\");
1755 }
1756 
1764 bool vpIoTools::isSamePathname(const std::string &pathname1, const std::string &pathname2)
1765 {
1766  // Normalize path
1767  std::string path1_normalize = vpIoTools::path(pathname1);
1768  std::string path2_normalize = vpIoTools::path(pathname2);
1769 
1770  // Get absolute path
1771  path1_normalize = vpIoTools::getAbsolutePathname(path1_normalize);
1772  path2_normalize = vpIoTools::getAbsolutePathname(path2_normalize);
1773 
1774  return (path1_normalize == path2_normalize);
1775 }
1776 
1784 std::pair<std::string, std::string> vpIoTools::splitDrive(const std::string &pathname)
1785 {
1786 //# Split a path in a drive specification (a drive letter followed by a
1787 //# colon) and the path specification.
1788 //# It is always true that drivespec + pathspec == p
1789 // def splitdrive(p):
1790 // """Split a pathname into drive/UNC sharepoint and relative path
1791 // specifiers. Returns a 2-tuple (drive_or_unc, path); either part may be
1792 // empty.
1793 //
1794 // If you assign
1795 // result = splitdrive(p)
1796 // It is always true that:
1797 // result[0] + result[1] == p
1798 //
1799 // If the path contained a drive letter, drive_or_unc will contain
1800 // everything up to and including the colon. e.g. splitdrive("c:/dir")
1801 // returns ("c:", "/dir")
1802 //
1803 // If the path contained a UNC path, the drive_or_unc will contain the host
1804 // name and share up to but not including the fourth directory separator
1805 // character. e.g. splitdrive("//host/computer/dir") returns
1806 // ("//host/computer", "/dir")
1807 //
1808 // Paths cannot contain both a drive letter and a UNC path.
1809 //
1810 // """
1811 // if len(p) > 1:
1812 // normp = p.replace(altsep, sep)
1813 // if (normp[0:2] == sep*2) and (normp[2] != sep):
1814 // # is a UNC path:
1815 // # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1816 // # \\machine\mountpoint\directory\etc\...
1817 // # directory ^^^^^^^^^^^^^^^
1818 // index = normp.find(sep, 2)
1819 // if index == -1:
1820 // return '', p
1821 // index2 = normp.find(sep, index + 1)
1822 // # a UNC path can't have two slashes in a row
1823 // # (after the initial two)
1824 // if index2 == index + 1:
1825 // return '', p
1826 // if index2 == -1:
1827 // index2 = len(p)
1828 // return p[:index2], p[index2:]
1829 // if normp[1] == ':':
1830 // return p[:2], p[2:]
1831 // return '', p
1832 
1833 // On Unix, the drive is always empty.
1834 // On the Mac, the drive is always empty (don't use the volume name -- it
1835 // doesn't have the same syntactic and semantic oddities as DOS drive
1836 // letters, such as there being a separate current directory per drive).
1837 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
1838  return std::pair<std::string, std::string>("", pathname);
1839 #else
1840  const std::string sep = "\\";
1841  const std::string sepsep = "\\\\";
1842  const std::string altsep = "/";
1843 
1844  if (pathname.size() > 1) {
1845  std::string normPathname = pathname;
1846  std::replace(normPathname.begin(), normPathname.end(), *altsep.c_str(), *sep.c_str());
1847 
1848  if (normPathname.substr(0, 2) == sepsep && normPathname.substr(2, 1) != sep) {
1849  // is a UNC path:
1850  // vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1851  // \\machine\mountpoint\directory\etc\...
1852  // directory ^^^^^^^^^^^^^^^
1853  size_t index = normPathname.find(sep, 2);
1854  if (index == std::string::npos) {
1855  return std::pair<std::string, std::string>("", pathname);
1856  }
1857 
1858  size_t index2 = normPathname.find(sep, index + 1);
1859  //# a UNC path can't have two slashes in a row
1860  //# (after the initial two)
1861  if (index2 == index + 1) {
1862  return std::pair<std::string, std::string>("", pathname);
1863  }
1864 
1865  if (index2 == std::string::npos) {
1866  index2 = pathname.size();
1867  }
1868 
1869  return std::pair<std::string, std::string>(pathname.substr(0, index2), pathname.substr(index2));
1870  }
1871 
1872  if (normPathname[1] == ':') {
1873  return std::pair<std::string, std::string>(pathname.substr(0, 2), pathname.substr(2));
1874  }
1875  }
1876 
1877  return std::pair<std::string, std::string>("", pathname);
1878 #endif
1879 }
1880 
1929 std::vector<std::string> vpIoTools::splitChain(const std::string &chain, const std::string &sep)
1930 {
1931  size_t startIndex = 0;
1932 
1933  std::string chainToSplit = chain;
1934  std::vector<std::string> subChain;
1935  size_t sepIndex = chainToSplit.find(sep);
1936 
1937  while (sepIndex != std::string::npos) {
1938  std::string sub = chainToSplit.substr(startIndex, sepIndex);
1939  if (!sub.empty())
1940  subChain.push_back(sub);
1941  chainToSplit = chainToSplit.substr(sepIndex + 1, chain.size() - 1);
1942 
1943  sepIndex = chainToSplit.find(sep);
1944  }
1945  if (!chainToSplit.empty())
1946  subChain.push_back(chainToSplit);
1947 
1948  return subChain;
1949 }
1950 
1958 std::vector<std::string> vpIoTools::getDirFiles(const std::string &pathname)
1959 {
1960 
1961  if (!checkDirectory(pathname)) {
1962  throw(vpIoException(vpException::fatalError, "Directory %s doesn't exist'", pathname.c_str()));
1963  }
1964  std::string dirName = path(pathname);
1965 
1966 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1967 
1968  std::vector<std::string> files;
1969  struct dirent **list = NULL;
1970  int filesCount = scandir(dirName.c_str(), &list, NULL, NULL);
1971  if (filesCount == -1) {
1972  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1973  }
1974  for (int i = 0; i < filesCount; i++) {
1975  std::string fileName = list[i]->d_name;
1976  if (fileName != "." && fileName != "..") {
1977  files.push_back(fileName);
1978  }
1979  free(list[i]);
1980  }
1981  free(list);
1982  std::sort(files.begin(), files.end());
1983  return files;
1984 
1985 #elif defined(_WIN32)
1986 #if (!defined(WINRT))
1987 
1988  std::vector<std::string> files;
1989  std::string fileMask = dirName;
1990  fileMask.append("\\*");
1991  WIN32_FIND_DATA FindFileData;
1992  HANDLE hFind = FindFirstFile(fileMask.c_str(), &FindFileData);
1993  // Directory is empty
1994  if (HandleToLong(&hFind) == ERROR_FILE_NOT_FOUND) {
1995  return files;
1996  }
1997  if (hFind == INVALID_HANDLE_VALUE) {
1998  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1999  }
2000  do {
2001  std::string fileName = FindFileData.cFileName;
2002  if (fileName != "." && fileName != "..") {
2003  files.push_back(fileName);
2004  }
2005  } while (FindNextFile(hFind, &FindFileData));
2006  FindClose(hFind);
2007  std::sort(files.begin(), files.end());
2008  return files;
2009 
2010 #else
2012  "Cannot read files of directory %s: not implemented on "
2013  "Universal Windows Platform",
2014  dirName.c_str()));
2015 #endif
2016 #endif
2017 }
2018 
2022 void vpIoTools::readBinaryValueLE(std::ifstream &file, int16_t &short_value)
2023 {
2024  file.read((char *)(&short_value), sizeof(short_value));
2025 
2026 #ifdef VISP_BIG_ENDIAN
2027  // Swap bytes order from little endian to big endian
2028  short_value = vpEndian::swap16bits((uint16_t)short_value);
2029 #endif
2030 }
2031 
2035 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint16_t &ushort_value)
2036 {
2037  file.read((char *)(&ushort_value), sizeof(ushort_value));
2038 
2039 #ifdef VISP_BIG_ENDIAN
2040  // Swap bytes order from little endian to big endian
2041  ushort_value = vpEndian::swap16bits(ushort_value);
2042 #endif
2043 }
2044 
2048 void vpIoTools::readBinaryValueLE(std::ifstream &file, int32_t &int_value)
2049 {
2050  file.read((char *)(&int_value), sizeof(int_value));
2051 
2052 #ifdef VISP_BIG_ENDIAN
2053  // Swap bytes order from little endian to big endian
2054  int_value = vpEndian::swap32bits((uint32_t)int_value);
2055 #endif
2056 }
2057 
2061 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint32_t &uint_value)
2062 {
2063  file.read((char *)(&uint_value), sizeof(uint_value));
2064 
2065 #ifdef VISP_BIG_ENDIAN
2066  // Swap bytes order from little endian to big endian
2067  uint_value = vpEndian::swap32bits(uint_value);
2068 #endif
2069 }
2070 
2074 void vpIoTools::readBinaryValueLE(std::ifstream &file, float &float_value)
2075 {
2076  file.read((char *)(&float_value), sizeof(float_value));
2077 
2078 #ifdef VISP_BIG_ENDIAN
2079  // Swap bytes order from little endian to big endian
2080  float_value = vpEndian::swapFloat(float_value);
2081 #endif
2082 }
2083 
2087 void vpIoTools::readBinaryValueLE(std::ifstream &file, double &double_value)
2088 {
2089  file.read((char *)(&double_value), sizeof(double_value));
2090 
2091 #ifdef VISP_BIG_ENDIAN
2092  // Swap bytes order from little endian to big endian
2093  double_value = vpEndian::swapDouble(double_value);
2094 #endif
2095 }
2096 
2100 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
2101 {
2102 #ifdef VISP_BIG_ENDIAN
2103  // Swap bytes order to little endian
2104  uint16_t swap_short = vpEndian::swap16bits((uint16_t)short_value);
2105  file.write((char *)(&swap_short), sizeof(swap_short));
2106 #else
2107  file.write((char *)(&short_value), sizeof(short_value));
2108 #endif
2109 }
2110 
2114 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint16_t ushort_value)
2115 {
2116 #ifdef VISP_BIG_ENDIAN
2117  // Swap bytes order to little endian
2118  uint16_t swap_ushort = vpEndian::swap16bits(ushort_value);
2119  file.write((char *)(&swap_ushort), sizeof(swap_ushort));
2120 #else
2121  file.write((char *)(&ushort_value), sizeof(ushort_value));
2122 #endif
2123 }
2124 
2128 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int32_t int_value)
2129 {
2130 #ifdef VISP_BIG_ENDIAN
2131  // Swap bytes order to little endian
2132  uint32_t swap_int = vpEndian::swap32bits((uint32_t)int_value);
2133  file.write((char *)(&swap_int), sizeof(swap_int));
2134 #else
2135  file.write((char *)(&int_value), sizeof(int_value));
2136 #endif
2137 }
2138 
2142 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint32_t uint_value)
2143 {
2144 #ifdef VISP_BIG_ENDIAN
2145  // Swap bytes order to little endian
2146  uint32_t swap_int = vpEndian::swap32bits(uint_value);
2147  file.write((char *)(&swap_int), sizeof(swap_int));
2148 #else
2149  file.write((char *)(&uint_value), sizeof(uint_value));
2150 #endif
2151 }
2152 
2156 void vpIoTools::writeBinaryValueLE(std::ofstream &file, float float_value)
2157 {
2158 #ifdef VISP_BIG_ENDIAN
2159  // Swap bytes order to little endian
2160  float swap_float = vpEndian::swapFloat(float_value);
2161  file.write((char *)(&swap_float), sizeof(swap_float));
2162 #else
2163  file.write((char *)(&float_value), sizeof(float_value));
2164 #endif
2165 }
2166 
2170 void vpIoTools::writeBinaryValueLE(std::ofstream &file, double double_value)
2171 {
2172 #ifdef VISP_BIG_ENDIAN
2173  // Swap bytes order to little endian
2174  double swap_double = vpEndian::swapDouble(double_value);
2175  file.write((char *)(&swap_double), sizeof(swap_double));
2176 #else
2177  file.write((char *)(&double_value), sizeof(double_value));
2178 #endif
2179 }
2180 
2181 bool vpIoTools::parseBoolean(std::string input)
2182 {
2183  std::transform(input.begin(), input.end(), input.begin(), ::tolower);
2184  std::istringstream is(input);
2185  bool b;
2186  // Parse string to boolean either in the textual representation
2187  // (True/False) or in numeric representation (1/0)
2188  is >> (input.size() > 1 ? std::boolalpha : std::noboolalpha) >> b;
2189  return b;
2190 }
2191 
2195 std::string vpIoTools::trim(std::string s) { return ltrim(rtrim(s)); }
unsigned int getCols() const
Definition: vpArray2D.h:278
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:303
unsigned int getRows() const
Definition: vpArray2D.h:288
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:388
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1382
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1929
static std::vector< std::string > configVars
Definition: vpIoTools.h:256
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:1020
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1657
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:807
static bool readConfigVar(const std::string &var, float &value)
Definition: vpIoTools.cpp:1109
static void setBaseName(const std::string &s)
Definition: vpIoTools.cpp:242
static std::pair< std::string, std::string > splitDrive(const std::string &pathname)
Definition: vpIoTools.cpp:1784
static bool isSamePathname(const std::string &pathname1, const std::string &pathname2)
Definition: vpIoTools.cpp:1764
static std::string getTempPath()
Definition: vpIoTools.cpp:204
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1740
static void setBaseDir(const std::string &dir)
Definition: vpIoTools.cpp:249
static std::string baseDir
Definition: vpIoTools.h:254
static bool loadConfigFile(const std::string &confFile)
Definition: vpIoTools.cpp:1060
static bool copy(const std::string &src, const std::string &dst)
Definition: vpIoTools.cpp:849
static std::string trim(std::string s)
Definition: vpIoTools.cpp:2195
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
Definition: vpIoTools.cpp:2022
static void saveConfigFile(const bool &actuallySave=true)
Definition: vpIoTools.cpp:1360
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:428
static bool rename(const std::string &oldfilename, const std::string &newfilename)
Definition: vpIoTools.cpp:1002
static bool parseBoolean(std::string input)
Definition: vpIoTools.cpp:2181
static long getIndex(const std::string &filename, const std::string &format)
Definition: vpIoTools.cpp:1591
static std::string getUserName()
Definition: vpIoTools.cpp:324
static std::string getFullName()
Definition: vpIoTools.cpp:263
static void addNameElement(const std::string &strTrue, const bool &cond=true, const std::string &strFalse="")
Definition: vpIoTools.cpp:1306
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1699
static std::string getenv(const std::string &env)
Definition: vpIoTools.cpp:361
static const std::string & getBuildInformation()
Definition: vpIoTools.cpp:145
static std::string getBaseName()
Definition: vpIoTools.cpp:256
static std::string getFileExtension(const std::string &pathname, bool checkFile=false)
Definition: vpIoTools.cpp:1447
static std::string baseName
Definition: vpIoTools.h:253
static void createBaseNamePath(const bool &empty=false)
Definition: vpIoTools.cpp:1341
static std::vector< std::string > getDirFiles(const std::string &dirname)
Definition: vpIoTools.cpp:1958
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:578
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:2100
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:940
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:1550
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:731
static bool checkFifo(const std::string &filename)
Definition: vpIoTools.cpp:488
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1633
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1528
static const char separator
Definition: vpIoTools.h:186
static void makeFifo(const std::string &dirname)
Definition: vpIoTools.cpp:629
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:183
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