Visual Servoing Platform  version 3.5.1 under development (2022-12-04)
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 
44 // At this point, to make scandir() working as expected on armv7 virtualized on a x86-64bit architecture
45 // (see github/workflow/other-arch-isolated.yml) we need to define _FILE_OFFSET_BITS=64. Otherwise
46 // testVideo.cpp will fail.
47 // Since adding here something like:
48 // #include <visp3/core/vpConfig.h>
49 // #ifdef VISP_DEFINE_FILE_OFFSET_BITS
50 // # define _FILE_OFFSET_BITS 64
51 // #endif
52 // where VISP_DEFINE_FILE_OFFSET_BITS is defined in vpConfig.h doesn't work (my explanation is that the define
53 // should be done before any other includes; in vpConfig.h there is cstdlib that is included), the other way
54 // that was retained is to add to vpIoTools.cpp COMPILE_DEFINTIONS _FILE_OFFSET_BITS=64 (see CMakeLists.txt)
55 
56 #include <algorithm>
57 #include <cctype>
58 #include <cmath>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <fstream>
62 #include <functional>
63 #include <limits>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <sys/stat.h>
68 #include <sys/types.h>
69 #include <visp3/core/vpDebug.h>
70 #include <visp3/core/vpEndian.h>
71 #include <visp3/core/vpIoException.h>
72 #include <visp3/core/vpIoTools.h>
73 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
74 #include <dirent.h>
75 #include <unistd.h>
76 #elif defined(_WIN32)
77 #include <direct.h>
78 #include <windows.h>
79 #endif
80 #if !defined(_WIN32)
81 #ifdef __ANDROID__
82 // Like IOS, wordexp.cpp is not defined for Android
83 #else
84 #include <wordexp.h>
85 #endif
86 #endif
87 
88 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
89 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IOS macro
90 #endif
91 
92 #ifndef PATH_MAX
93 #ifdef _MAX_PATH
94 #define PATH_MAX _MAX_PATH
95 #else
96 #define PATH_MAX 1024
97 #endif
98 #endif
99 
100 std::string vpIoTools::baseName = "";
101 std::string vpIoTools::baseDir = "";
102 std::string vpIoTools::configFile = "";
103 std::vector<std::string> vpIoTools::configVars = std::vector<std::string>();
104 std::vector<std::string> vpIoTools::configValues = std::vector<std::string>();
105 
106 namespace
107 {
108 // The following code is not working on iOS since wordexp() is not available
109 // The function is not used on Android
110 #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
111 #if (TARGET_OS_IOS == 0) && !defined(__ANDROID__)
112 void replaceAll(std::string &str, const std::string &search, const std::string &replace)
113 {
114  size_t start_pos = 0;
115  while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
116  str.replace(start_pos, search.length(), replace);
117  start_pos += replace.length(); // Handles case where 'replace' is a
118  // substring of 'search'
119  }
120 }
121 #endif
122 #endif
123 
124 std::string &ltrim(std::string &s)
125 {
126 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
127  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
128 #else
129  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
130 #endif
131  return s;
132 }
133 
134 std::string &rtrim(std::string &s)
135 {
136 #if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
137  s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
138 #else
139  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
140 #endif
141  return s;
142 }
143 } // namespace
144 
148 const std::string &vpIoTools::getBuildInformation()
149 {
150  static std::string build_info =
151 #include "version_string.inc"
152  ;
153  return build_info;
154 }
155 
208 {
209 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
210  std::string username;
211  vpIoTools::getUserName(username);
212  return "/tmp/" + username;
213 #elif defined(_WIN32) && !defined(WINRT)
214  // https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-using-a-temporary-file
215  // Gets the temp path env string (no guarantee it's a valid path).
216  TCHAR lpTempPathBuffer[MAX_PATH];
217  DWORD dwRetVal = GetTempPath(MAX_PATH /* length of the buffer */, lpTempPathBuffer /* buffer for path */);
218  if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
219  throw vpIoException(vpIoException::cantGetenv, "Error with GetTempPath() call!");
220  }
221  std::string temp_path(lpTempPathBuffer);
222  if (!temp_path.empty()) {
223  if (temp_path.back() == '\\') {
224  temp_path.resize(temp_path.size() - 1);
225  }
226  } else {
227  temp_path = "C:\temp";
228  try {
229  vpIoTools::makeDirectory(temp_path);
230  } catch (...) {
231  throw(vpException(vpException::fatalError, "Cannot set temp path to %s", temp_path.c_str()));
232  }
233  }
234  return temp_path;
235 #else
236  throw vpIoException(vpException::fatalError, "Not implemented on this platform!");
237 #endif
238 }
239 
245 void vpIoTools::setBaseName(const std::string &s) { baseName = s; }
246 
252 void vpIoTools::setBaseDir(const std::string &dir) { baseDir = dir + "/"; }
253 
259 std::string vpIoTools::getBaseName() { return baseName; }
260 
266 std::string vpIoTools::getFullName() { return baseDir + baseName; }
267 
281 void vpIoTools::getUserName(std::string &username)
282 {
283 // With MinGW, UNIX and _WIN32 are defined
284 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
285  // Get the user name.
286  char *_username = ::getenv("LOGNAME");
287  if (!_username) {
288  username = "unknown";
289  } else {
290  username = _username;
291  }
292 #elif defined(_WIN32)
293 #if (!defined(WINRT))
294  unsigned int info_buffer_size = 1024;
295  TCHAR *infoBuf = new TCHAR[info_buffer_size];
296  DWORD bufCharCount = (DWORD)info_buffer_size;
297  // Get the user name.
298  if (!GetUserName(infoBuf, &bufCharCount)) {
299  username = "unknown";
300  } else {
301  username = infoBuf;
302  }
303  delete[] infoBuf;
304 #else
305  // Universal platform
306  username = "unknown";
307 #endif
308 #else
309  username = "unknown";
310 #endif
311 }
312 
328 {
329  std::string username;
330  getUserName(username);
331  return username;
332 }
333 
364 std::string vpIoTools::getenv(const std::string &env)
365 {
366 #if defined(_WIN32) && defined(WINRT)
367  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value: not "
368  "implemented on Universal Windows Platform"));
369 #else
370  std::string value;
371  // Get the environment variable value.
372  char *_value = ::getenv(env.c_str());
373  if (!_value) {
374  throw(vpIoException(vpIoException::cantGetenv, "Cannot get the environment variable value"));
375  }
376  value = _value;
377 
378  return value;
379 #endif
380 }
381 
391 void vpIoTools::getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
392 {
393  if (version.size() == 0) {
394  major = 0;
395  minor = 0;
396  patch = 0;
397  } else {
398  size_t major_pos = version.find('.');
399  std::string major_str = version.substr(0, major_pos);
400  major = static_cast<unsigned>(atoi(major_str.c_str()));
401 
402  if (major_pos != std::string::npos) {
403  size_t minor_pos = version.find('.', major_pos + 1);
404  std::string minor_str = version.substr(major_pos + 1, (minor_pos - (major_pos + 1)));
405  minor = static_cast<unsigned>(atoi(minor_str.c_str()));
406 
407  if (minor_pos != std::string::npos) {
408  std::string patch_str = version.substr(minor_pos + 1);
409  patch = static_cast<unsigned>(atoi(patch_str.c_str()));
410  } else {
411  patch = 0;
412  }
413  } else {
414  minor = 0;
415  patch = 0;
416  }
417  }
418 }
419 
431 bool vpIoTools::checkDirectory(const std::string &dirname)
432 {
433 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
434  struct stat stbuf;
435 #elif defined(_WIN32) && defined(__MINGW32__)
436  struct stat stbuf;
437 #elif defined(_WIN32)
438  struct _stat stbuf;
439 #endif
440 
441  if (dirname.empty()) {
442  return false;
443  }
444 
445  std::string _dirname = path(dirname);
446 
447 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
448  if (stat(_dirname.c_str(), &stbuf) != 0)
449 #elif defined(_WIN32) && defined(__MINGW32__)
450  // Remove trailing separator character if any
451  // AppVeyor: Windows 6.3.9600 AMD64 ; C:/MinGW/bin/g++.exe (ver 5.3.0) ;
452  // GNU Make 3.82.90 Built for i686-pc-mingw32
453  if (_dirname.at(_dirname.size() - 1) == vpIoTools::separator)
454  _dirname = _dirname.substr(0, _dirname.size() - 1);
455  if (stat(_dirname.c_str(), &stbuf) != 0)
456 #elif defined(_WIN32)
457  if (_stat(_dirname.c_str(), &stbuf) != 0)
458 #endif
459  {
460  return false;
461  }
462 #if defined(_WIN32) || (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
463  if ((stbuf.st_mode & S_IFDIR) == 0)
464 #endif
465  {
466  return false;
467  }
468 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
469  if ((stbuf.st_mode & S_IWUSR) == 0)
470 #elif defined(_WIN32)
471  if ((stbuf.st_mode & S_IWRITE) == 0)
472 #endif
473  {
474  return false;
475  }
476  return true;
477 }
478 
491 bool vpIoTools::checkFifo(const std::string &fifofilename)
492 {
493 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
494  struct stat stbuf;
495 
496  std::string _filename = path(fifofilename);
497  if (stat(_filename.c_str(), &stbuf) != 0) {
498  return false;
499  }
500  if ((stbuf.st_mode & S_IFIFO) == 0) {
501  return false;
502  }
503  if ((stbuf.st_mode & S_IRUSR) == 0)
504 
505  {
506  return false;
507  }
508  return true;
509 #elif defined(_WIN32)
510  (void)fifofilename;
511  throw(vpIoException(vpIoException::notImplementedError, "Fifo files are not supported on Windows platforms."));
512 #endif
513 }
514 
515 #ifndef DOXYGEN_SHOULD_SKIP_THIS
516 // See:
517 // https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950
518 int vpIoTools::mkdir_p(const char *path, int mode)
519 {
520  /* Adapted from http://stackoverflow.com/a/2336245/119527 */
521  const size_t len = strlen(path);
522  char _path[PATH_MAX];
523  const char sep = vpIoTools::separator;
524 
525  std::fill(_path, _path + PATH_MAX, 0);
526 
527  errno = 0;
528  if (len > sizeof(_path) - 1) {
529  errno = ENAMETOOLONG;
530  return -1;
531  }
532  /* Copy string so its mutable */
533  strcpy(_path, path);
534 
535  /* Iterate over the string */
536  for (char *p = _path + 1; *p; p++) { // path cannot be empty
537  if (*p == sep) {
538  /* Temporarily truncate */
539  *p = '\0';
540 
541 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
542  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
543 #elif defined(_WIN32)
544  (void)mode; // var not used
545  if (!checkDirectory(_path) && _mkdir(_path) != 0)
546 #endif
547  {
548  if (errno != EEXIST)
549  return -1;
550  }
551  *p = sep;
552  }
553  }
554 
555 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
556  if (mkdir(_path, static_cast<mode_t>(mode)) != 0)
557 #elif defined(_WIN32)
558  if (_mkdir(_path) != 0)
559 #endif
560  {
561  if (errno != EEXIST)
562  return -1;
563  }
564 
565  return 0;
566 }
567 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
568 
581 void vpIoTools::makeDirectory(const std::string &dirname)
582 {
583 #if ((!defined(__unix__) && !defined(__unix) && (!defined(__APPLE__) || !defined(__MACH__)))) && !defined(_WIN32)
584  std::cerr << "Unsupported platform for vpIoTools::makeDirectory()!" << std::endl;
585  return;
586 #endif
587 
588 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
589  struct stat stbuf;
590 #elif defined(_WIN32) && defined(__MINGW32__)
591  struct stat stbuf;
592 #elif defined(_WIN32)
593  struct _stat stbuf;
594 #endif
595 
596  if (dirname.empty()) {
597  throw(vpIoException(vpIoException::invalidDirectoryName, "invalid directory name"));
598  }
599 
600  std::string _dirname = path(dirname);
601 
602 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
603  if (stat(_dirname.c_str(), &stbuf) != 0)
604 #elif defined(_WIN32) && defined(__MINGW32__)
605  if (stat(_dirname.c_str(), &stbuf) != 0)
606 #elif defined(_WIN32)
607  if (_stat(_dirname.c_str(), &stbuf) != 0)
608 #endif
609  {
610  if (vpIoTools::mkdir_p(_dirname.c_str(), 0755) != 0) {
611  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
612  }
613  }
614 
615  if (checkDirectory(dirname) == false) {
616  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'", dirname.c_str()));
617  }
618 }
619 
632 void vpIoTools::makeFifo(const std::string &fifoname)
633 {
634 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
635 
636  // If dirname is a directory, we throw an error
637  if (vpIoTools::checkDirectory(fifoname)) {
639  "Unable to create fifo file. '%s' is an existing directory.", fifoname.c_str()));
640  }
641 
642  // If dirname refers to an already existing file, we throw an error
643  else if (vpIoTools::checkFilename(fifoname)) {
644  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. File already exists.",
645  fifoname.c_str()));
646  // If dirname refers to an already existing fifo, we throw an error
647  } else if (vpIoTools::checkFifo(fifoname)) {
648  throw(vpIoException(vpIoException::invalidDirectoryName, "Unable to create fifo file '%s'. Fifo already exists.",
649  fifoname.c_str()));
650  }
651 
652  else if (mkfifo(fifoname.c_str(), 0666) < 0) {
653  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo file '%s'.", fifoname.c_str()));
654  }
655 #elif defined(_WIN32)
656  (void)fifoname;
657  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create fifo on Windows platforms."));
658 #endif
659 }
660 
661 #if defined(_WIN32) && !defined(WINRT)
662 std::string getUuid()
663 {
664  UUID uuid;
665  if (UuidCreate(&uuid) != RPC_S_OK) {
666  throw(vpIoException(vpIoException::fatalError, "UuidCreate() failed!"));
667  }
668 
669  RPC_CSTR stringUuid;
670  if (UuidToString(&uuid, &stringUuid) != RPC_S_OK) {
671  throw(vpIoException(vpIoException::fatalError, "UuidToString() failed!"));
672  }
673 
674  return reinterpret_cast<char *>(stringUuid);
675 }
676 #endif
677 
734 std::string vpIoTools::makeTempDirectory(const std::string &dirname)
735 {
736 #if defined(WINRT) || !defined(_WIN32) && !(defined(__unix__) || defined(__unix) || \
737  (defined(__APPLE__) && defined(__MACH__))) // not UNIX and not Windows
738  throw(vpIoException(vpIoException::cantCreateDirectory, "makeTempDirectory() is not supported on this platform!"));
739 #endif
740 
741  std::string dirname_cpy = std::string(dirname);
742  std::string correctEnding = "XXXXXX";
743 
744  // If dirname is an unexisting directory, it should end with XXXXXX in order to create a temp directory
745  if (!vpIoTools::checkDirectory(dirname_cpy)) {
746 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
747  // Check if dirname ends with XXXXXX
748  if (dirname_cpy.rfind(correctEnding) == std::string::npos) {
749  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
750  dirname_cpy = dirname_cpy + "/";
751  }
752  try {
753  vpIoTools::makeDirectory(dirname_cpy);
754  } catch (const vpException &e) {
755  throw e;
756  }
757 
758  dirname_cpy = dirname_cpy + "XXXXXX";
759  }
760 
761 #elif defined(_WIN32) && !defined(WINRT)
762  // Remove XXXXXX
763  dirname_cpy = dirname_cpy.substr(0, dirname_cpy.rfind(correctEnding));
764  // Append UUID
765  dirname_cpy = dirname_cpy + getUuid();
766 #endif
767 
768  } else {
769  // If dirname is an existing directory, we create a temp directory inside
770 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
771  if (dirname_cpy.at(dirname_cpy.length() - 1) != '/') {
772  dirname_cpy = dirname_cpy + "/";
773  }
774  dirname_cpy = dirname_cpy + "XXXXXX";
775 #elif defined(_WIN32) && !defined(WINRT)
776  dirname_cpy = createFilePath(dirname_cpy, getUuid());
777 #endif
778  }
779 
780 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
781  char *dirname_char = new char[dirname_cpy.length() + 1];
782  strcpy(dirname_char, dirname_cpy.c_str());
783 
784  char *computedDirname = mkdtemp(dirname_char);
785 
786  if (!computedDirname) {
787  delete[] dirname_char;
788  throw(vpIoException(vpIoException::cantCreateDirectory, "Unable to create directory '%s'.", dirname_cpy.c_str()));
789  }
790 
791  std::string res(computedDirname);
792  delete[] dirname_char;
793  return res;
794 #elif defined(_WIN32) && !defined(WINRT)
795  makeDirectory(dirname_cpy);
796  return dirname_cpy;
797 #endif
798 }
799 
810 bool vpIoTools::checkFilename(const std::string &filename)
811 {
812 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
813  struct stat stbuf;
814 #elif defined(_WIN32)
815  struct _stat stbuf;
816 #endif
817 
818  if (filename.empty()) {
819  return false;
820  }
821 
822  std::string _filename = path(filename);
823 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
824  if (stat(_filename.c_str(), &stbuf) != 0)
825 #elif defined(_WIN32)
826  if (_stat(_filename.c_str(), &stbuf) != 0)
827 #endif
828  {
829  return false;
830  }
831  if ((stbuf.st_mode & S_IFREG) == 0) {
832  return false;
833  }
834 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
835  if ((stbuf.st_mode & S_IRUSR) == 0)
836 #elif defined(_WIN32)
837  if ((stbuf.st_mode & S_IREAD) == 0)
838 #endif
839  {
840  return false;
841  }
842  return true;
843 }
844 
852 bool vpIoTools::copy(const std::string &src, const std::string &dst)
853 {
854  // Check if we have to consider a file or a directory
855  if (vpIoTools::checkFilename(src)) {
856 // std::cout << "copy file: " << src << " in " << dst << std::endl;
857 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
858 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
859  // wordexp() is not available
860  char cmd[FILENAME_MAX];
861  int ret;
862  sprintf(cmd, "cp -p %s %s", src.c_str(), dst.c_str());
863  ret = system(cmd);
864  if (ret) {
865  }; // to avoid a warning
866  // std::cout << cmd << " return value: " << ret << std::endl;
867  return true;
868 #else
869  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
870  dst.c_str()));
871 #endif
872 #elif defined(_WIN32)
873 #if (!defined(WINRT))
874  char cmd[FILENAME_MAX];
875  int ret;
876  std::string src_ = vpIoTools::path(src);
877  std::string dst_ = vpIoTools::path(dst);
878  sprintf(cmd, "copy %s %s", src_.c_str(), dst_.c_str());
879  ret = system(cmd);
880  if (ret) {
881  }; // to avoid a warning
882  // std::cout << cmd << " return value: " << ret << std::endl;
883  return true;
884 #else
885  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
886  src.c_str(), dst.c_str()));
887 #endif
888 #endif
889  } else if (vpIoTools::checkDirectory(src)) {
890 // std::cout << "copy directory: " << src << " in " << dst << std::endl;
891 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
892 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
893  // wordexp() is not available
894  char cmd[FILENAME_MAX];
895  int ret;
896  sprintf(cmd, "cp -p -r %s %s", src.c_str(), dst.c_str());
897  ret = system(cmd);
898  if (ret) {
899  }; // to avoid a warning
900  // std::cout << cmd << " return value: " << ret << std::endl;
901  return true;
902 #else
903  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on iOS Platform", src.c_str(),
904  dst.c_str()));
905 #endif
906 #elif defined(_WIN32)
907 #if (!defined(WINRT))
908  char cmd[FILENAME_MAX];
909  int ret;
910  std::string src_ = vpIoTools::path(src);
911  std::string dst_ = vpIoTools::path(dst);
912  sprintf(cmd, "copy %s %s", src_.c_str(), dst_.c_str());
913  ret = system(cmd);
914  if (ret) {
915  }; // to avoid a warning
916  // std::cout << cmd << " return value: " << ret << std::endl;
917  return true;
918 #else
919  throw(vpIoException(vpException::fatalError, "Cannot copy %s in %s: not implemented on Universal Windows Platform",
920  src.c_str(), dst.c_str()));
921 #endif
922 #endif
923  } else {
924  std::cout << "Cannot copy: " << src << " in " << dst << std::endl;
925  return false;
926  }
927 }
928 
939 bool vpIoTools::remove(const std::string &file_or_dir)
940 {
941  // Check if we have to consider a file or a directory
942  if (vpIoTools::checkFilename(file_or_dir)
943 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
944  || vpIoTools::checkFifo(std::string(file_or_dir))
945 #endif
946  ) {
947  // std::cout << "remove file: " << file_or_dir << std::endl;
948  if (::remove(file_or_dir.c_str()) != 0)
949  return false;
950  else
951  return true;
952  } else if (vpIoTools::checkDirectory(file_or_dir)) {
953 // std::cout << "remove directory: " << file_or_dir << std::endl;
954 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
955 #if TARGET_OS_IOS == 0 // The following code is not working on iOS since
956  // wordexp() is not available
957  char cmd[FILENAME_MAX];
958  sprintf(cmd, "rm -rf \"%s\"", file_or_dir.c_str());
959  int ret = system(cmd);
960  if (ret) {
961  }; // to avoid a warning
962  // std::cout << cmd << " return value: " << ret << std::endl;
963  return true;
964 #else
965  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on iOS Platform",
966  file_or_dir.c_str()));
967 #endif
968 #elif defined(_WIN32)
969 #if (!defined(WINRT))
970  char cmd[FILENAME_MAX];
971  std::string file_or_dir_ = vpIoTools::path(file_or_dir);
972  sprintf(cmd, "rmdir /S /Q %s", file_or_dir_.c_str());
973  int ret = system(cmd);
974  if (ret) {
975  }; // to avoid a warning
976  // std::cout << cmd << " return value: " << ret << std::endl;
977  return true;
978 #else
979  throw(vpIoException(vpException::fatalError, "Cannot remove %s: not implemented on Universal Windows Platform",
980  file_or_dir.c_str()));
981 #endif
982 #endif
983  } else {
984  std::cout << "Cannot remove: " << file_or_dir << std::endl;
985  return false;
986  }
987 }
988 
998 bool vpIoTools::rename(const std::string &oldfilename, const std::string &newfilename)
999 {
1000  if (::rename(oldfilename.c_str(), newfilename.c_str()) != 0)
1001  return false;
1002  else
1003  return true;
1004 }
1005 
1016 std::string vpIoTools::path(const std::string &pathname)
1017 {
1018  std::string path(pathname);
1019 
1020 #if defined(_WIN32)
1021  for (unsigned int i = 0; i < path.length(); i++)
1022  if (path[i] == '/')
1023  path[i] = '\\';
1024 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
1025  for (unsigned int i = 0; i < path.length(); i++)
1026  if (path[i] == '\\')
1027  path[i] = '/';
1028 #if TARGET_OS_IOS == 0 // The following code is not working on iOS and android since
1029  // wordexp() is not available
1030 #ifdef __ANDROID__
1031 // Do nothing
1032 #else
1033  wordexp_t exp_result;
1034 
1035  // escape quote character
1036  replaceAll(path, "'", "'\\''");
1037  // add quotes to handle special characters like parentheses and spaces
1038  wordexp(std::string("'" + path + "'").c_str(), &exp_result, 0);
1039  path = exp_result.we_wordc == 1 ? exp_result.we_wordv[0] : "";
1040  wordfree(&exp_result);
1041 #endif
1042 #endif
1043 #endif
1044 
1045  return path;
1046 }
1047 
1056 bool vpIoTools::loadConfigFile(const std::string &confFile)
1057 {
1058  configFile = path(confFile);
1059  configVars.clear();
1060  configValues.clear();
1061  std::ifstream confContent(configFile.c_str(), std::ios::in);
1062 
1063  if (confContent.is_open()) {
1064  std::string line, var, val;
1065  long unsigned int k;
1066  int c;
1067  std::string stop[3] = {" ", "\t", "#"};
1068  while (std::getline(confContent, line)) {
1069  if ((line.compare(0, 1, "#") != 0) && (line.size() > 2)) {
1070  try {
1071  // name of the variable
1072  k = static_cast<unsigned long>(line.find(" "));
1073  var = line.substr(0, k);
1074  // look for the end of the actual value
1075  c = 200;
1076  for (unsigned i = 0; i < 3; ++i)
1077  c = vpMath::minimum(c,
1078  static_cast<int>(line.find(stop[i], static_cast<size_t>(k) + static_cast<size_t>(1))));
1079  if (c == -1)
1080  c = static_cast<int>(line.size());
1081  long unsigned int c_ = static_cast<long unsigned int>(c);
1082  val = line.substr(static_cast<size_t>(k) + static_cast<size_t>(1),
1083  static_cast<size_t>(c_) - static_cast<size_t>(k) - static_cast<size_t>(1));
1084  configVars.push_back(var);
1085  configValues.push_back(val);
1086  } catch (...) {
1087  }
1088  }
1089  }
1090  confContent.close();
1091  } else {
1092  return false;
1093  }
1094  return true;
1095 }
1096 
1105 bool vpIoTools::readConfigVar(const std::string &var, float &value)
1106 {
1107  bool found = false;
1108  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1109  if (configVars[k] == var) {
1110  if (configValues[k].compare("PI") == 0)
1111  value = static_cast<float>(M_PI);
1112  else if (configValues[k].compare("PI/2") == 0)
1113  value = static_cast<float>(M_PI / 2.0);
1114  else if (configValues[k].compare("-PI/2") == 0)
1115  value = static_cast<float>(-M_PI / 2.0);
1116  else
1117  value = static_cast<float>(atof(configValues[k].c_str()));
1118  found = true;
1119  }
1120  }
1121  if (found == false)
1122  std::cout << var << " not found in config file" << std::endl;
1123  return found;
1124 }
1133 bool vpIoTools::readConfigVar(const std::string &var, double &value)
1134 {
1135  bool found = false;
1136  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1137  if (configVars[k] == var) {
1138  if (configValues[k].compare("PI") == 0)
1139  value = M_PI;
1140  else if (configValues[k].compare("PI/2") == 0)
1141  value = M_PI / 2;
1142  else if (configValues[k].compare("-PI/2") == 0)
1143  value = -M_PI / 2;
1144  else
1145  value = atof(configValues[k].c_str());
1146  found = true;
1147  }
1148  }
1149  if (found == false)
1150  std::cout << var << " not found in config file" << std::endl;
1151  return found;
1152 }
1153 
1162 bool vpIoTools::readConfigVar(const std::string &var, int &value)
1163 {
1164  bool found = false;
1165  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1166  if (configVars[k] == var) {
1167  value = atoi(configValues[k].c_str());
1168  found = true;
1169  }
1170  }
1171  if (found == false)
1172  std::cout << var << " not found in config file" << std::endl;
1173  return found;
1174 }
1175 
1184 bool vpIoTools::readConfigVar(const std::string &var, unsigned int &value)
1185 {
1186  int v = 0;
1187  bool found = readConfigVar(var, v);
1188  value = static_cast<unsigned int>(v);
1189  return found;
1190 }
1191 
1200 bool vpIoTools::readConfigVar(const std::string &var, bool &value)
1201 {
1202  int v = 0;
1203  bool found = readConfigVar(var, v);
1204  value = (v != 0);
1205  return found;
1206 }
1207 
1216 bool vpIoTools::readConfigVar(const std::string &var, vpColor &value)
1217 {
1218  unsigned int v = 0;
1219  bool found = readConfigVar(var, v);
1220  value = vpColor::getColor(v);
1221  return found;
1222 }
1223 
1232 bool vpIoTools::readConfigVar(const std::string &var, std::string &value)
1233 {
1234  bool found = false;
1235  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1236  if (configVars[k] == var) {
1237  value = configValues[k];
1238  found = true;
1239  }
1240  }
1241  if (found == false)
1242  std::cout << var << " not found in config file" << std::endl;
1243  return found;
1244 }
1245 
1259 bool vpIoTools::readConfigVar(const std::string &var, vpArray2D<double> &value, const unsigned int &nCols,
1260  const unsigned int &nRows)
1261 {
1262  bool found = false;
1263  std::string nb;
1264  for (unsigned int k = 0; k < configVars.size() && found == false; ++k) {
1265  if (configVars[k] == var) {
1266  found = true;
1267  // resize or not
1268  if (nCols != 0 && nRows != 0)
1269  value.resize(nRows, nCols);
1270  size_t ind = 0, ind2;
1271  for (unsigned int i = 0; i < value.getRows(); ++i)
1272  for (unsigned int j = 0; j < value.getCols(); ++j) {
1273  ind2 = configValues[k].find(",", ind);
1274  nb = configValues[k].substr(ind, ind2 - ind);
1275  if (nb.compare("PI") == 0)
1276  value[i][j] = M_PI;
1277  else if (nb.compare("PI/2") == 0)
1278  value[i][j] = M_PI / 2;
1279  else if (nb.compare("-PI/2") == 0)
1280  value[i][j] = -M_PI / 2;
1281  else
1282  value[i][j] = atof(nb.c_str());
1283  ind = ind2 + 1;
1284  }
1285  }
1286  }
1287  if (found == false)
1288  std::cout << var << " not found in config file" << std::endl;
1289  return found;
1290 }
1291 
1292 // construct experiment filename & path
1293 
1302 void vpIoTools::addNameElement(const std::string &strTrue, const bool &cond, const std::string &strFalse)
1303 {
1304  if (cond)
1305  baseName += "_" + strTrue;
1306  else if (strFalse != "")
1307  baseName += "_" + strFalse;
1308 }
1309 
1318 void vpIoTools::addNameElement(const std::string &strTrue, const double &val)
1319 {
1320  // if(val != 0.)
1321  if (std::fabs(val) < std::numeric_limits<double>::epsilon()) {
1322  char valC[256];
1323  sprintf(valC, "%.3f", val);
1324  std::string valS(valC);
1325  baseName += "_" + strTrue + valS;
1326  }
1327 }
1328 
1337 void vpIoTools::createBaseNamePath(const bool &empty)
1338 {
1339  if (vpIoTools::checkDirectory(baseDir + baseName) == false) {
1341  std::cout << "creating directory " + baseDir + baseName << std::endl;
1342  } else {
1343  if (empty) {
1344  std::cout << "emptying directory " + baseDir + baseName << std::endl;
1346  }
1347  }
1348 }
1349 
1356 void vpIoTools::saveConfigFile(const bool &actuallySave)
1357 {
1358  if (actuallySave) {
1359  std::string dest = baseDir + "/" + baseName + "_config.txt";
1360  // file copy
1361  vpIoTools::copy(configFile, dest);
1362  }
1363 }
1364 
1379 {
1380  std::string data_path;
1381  std::string file_to_test("mbt/cube.cao");
1382  std::string filename;
1383  // Test if VISP_INPUT_IMAGE_PATH env var is set
1384  try {
1385  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH");
1386  filename = data_path + "/" + file_to_test;
1387  if (vpIoTools::checkFilename(filename))
1388  return data_path;
1389  data_path = vpIoTools::getenv("VISP_INPUT_IMAGE_PATH") + "/ViSP-images";
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  } catch (...) {
1398  }
1399 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1400  // Test if visp-images-data package is installed (Ubuntu and Debian)
1401  data_path = "/usr/share/visp-images-data/ViSP-images";
1402  filename = data_path + "/" + file_to_test;
1403  if (vpIoTools::checkFilename(filename))
1404  return data_path;
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 #endif
1410  data_path = "";
1411  return data_path;
1412 }
1413 
1443 std::string vpIoTools::getFileExtension(const std::string &pathname, bool checkFile)
1444 {
1445  if (checkFile && (vpIoTools::checkDirectory(pathname) || !vpIoTools::checkFilename(pathname))) {
1446  return "";
1447  }
1448 
1449 #if defined(_WIN32)
1450  std::string sep = "\\";
1451  std::string altsep = "/";
1452  std::string extsep = ".";
1453 #else
1454  // On Unix, or on the Mac
1455  std::string sep = "/";
1456  std::string altsep = "";
1457  std::string extsep = ".";
1458 #endif
1459 
1460  // Python 2.7.8 module.
1461  //# Split a path in root and extension.
1462  //# The extension is everything starting at the last dot in the last
1463  //# pathname component; the root is everything before that.
1464  //# It is always true that root + ext == p.
1465  //
1466  //# Generic implementation of splitext, to be parametrized with
1467  //# the separators
1468  // def _splitext(p, sep, altsep, extsep):
1469  // """Split the extension from a pathname.
1470  //
1471  // Extension is everything from the last dot to the end, ignoring
1472  // leading dots. Returns "(root, ext)"; ext may be empty."""
1473  //
1474  // sepIndex = p.rfind(sep)
1475  // if altsep:
1476  // altsepIndex = p.rfind(altsep)
1477  // sepIndex = max(sepIndex, altsepIndex)
1478  //
1479  // dotIndex = p.rfind(extsep)
1480  // if dotIndex > sepIndex:
1481  // # skip all leading dots
1482  // filenameIndex = sepIndex + 1
1483  // while filenameIndex < dotIndex:
1484  // if p[filenameIndex] != extsep:
1485  // return p[:dotIndex], p[dotIndex:]
1486  // filenameIndex += 1
1487  //
1488  // return p, ''
1489 
1490  int sepIndex = static_cast<int>(pathname.rfind(sep));
1491  if (!altsep.empty()) {
1492  int altsepIndex = static_cast<int>(pathname.rfind(altsep));
1493  sepIndex = ((std::max))(sepIndex, altsepIndex);
1494  }
1495 
1496  size_t dotIndex = pathname.rfind(extsep);
1497  if (dotIndex != std::string::npos) {
1498  // The extsep character exists
1499  size_t npos = std::string::npos;
1500  if ((sepIndex != static_cast<int>(npos) && static_cast<int>(dotIndex) > sepIndex) ||
1501  sepIndex == static_cast<int>(npos)) {
1502  if (sepIndex == static_cast<int>(npos)) {
1503  sepIndex = 0;
1504  }
1505  size_t filenameIndex = static_cast<size_t>(sepIndex) + static_cast<size_t>(1);
1506 
1507  while (filenameIndex < dotIndex) {
1508  if (pathname.compare(filenameIndex, 1, extsep) != 0) {
1509  return pathname.substr(dotIndex);
1510  }
1511  filenameIndex++;
1512  }
1513  }
1514  }
1515 
1516  return "";
1517 }
1518 
1524 std::string vpIoTools::getName(const std::string &pathname)
1525 {
1526  if (pathname.size() > 0) {
1527  std::string convertedPathname = vpIoTools::path(pathname);
1528 
1529  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1530  if (index != std::string::npos) {
1531  return convertedPathname.substr(index + 1);
1532  }
1533 
1534  return convertedPathname;
1535  }
1536 
1537  return "";
1538 }
1539 
1546 std::string vpIoTools::getNameWE(const std::string &pathname)
1547 {
1548  std::string name = vpIoTools::getName(pathname);
1549  size_t found = name.find_last_of(".");
1550  std::string name_we = name.substr(0, found);
1551  return name_we;
1552 }
1553 
1587 long vpIoTools::getIndex(const std::string &filename, const std::string &format)
1588 {
1589  size_t indexBegin = format.find_last_of('%');
1590  size_t indexEnd = format.find_first_of('d', indexBegin);
1591  size_t suffixLength = format.length() - indexEnd - 1;
1592 
1593  // Extracting index
1594  if (filename.length() <= suffixLength + indexBegin) {
1595  return -1;
1596  }
1597  size_t indexLength = filename.length() - suffixLength - indexBegin;
1598  std::string indexSubstr = filename.substr(indexBegin, indexLength);
1599  std::istringstream ss(indexSubstr);
1600  long index = 0;
1601  ss >> index;
1602  if (ss.fail() || index < 0 || !ss.eof()) {
1603  return -1;
1604  }
1605 
1606  // Checking that format with inserted index equals filename
1607  char nameByFormat[FILENAME_MAX];
1608  sprintf(nameByFormat, format.c_str(), index);
1609  if (std::string(nameByFormat) != filename) {
1610  return -1;
1611  }
1612  return index;
1613 }
1614 
1630 std::string vpIoTools::getParent(const std::string &pathname)
1631 {
1632  if (pathname.size() > 0) {
1633  std::string convertedPathname = vpIoTools::path(pathname);
1634 
1635  size_t index = convertedPathname.find_last_of(vpIoTools::separator);
1636  if (index != std::string::npos) {
1637  return convertedPathname.substr(0, index);
1638  }
1639 
1640  return ".";
1641  } else {
1642  return "";
1643  }
1644 }
1645 
1654 std::string vpIoTools::getAbsolutePathname(const std::string &pathname)
1655 {
1656 
1657 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1658  std::string real_path_str = pathname;
1659  char *real_path = realpath(pathname.c_str(), NULL);
1660 
1661  if (real_path) {
1662  real_path_str = real_path;
1663  free(real_path);
1664  }
1665  return real_path_str;
1666 #elif defined(_WIN32)
1667 #if (!defined(WINRT))
1668  std::string real_path_str = pathname;
1669  DWORD retval = 0;
1670  TCHAR buffer[4096] = TEXT("");
1671 
1672  retval = GetFullPathName(pathname.c_str(), 4096, buffer, 0);
1673  if (retval != 0) {
1674  real_path_str = buffer;
1675  }
1676  return real_path_str;
1677 #else
1679  "Cannot get absolute path of %s: not implemented on "
1680  "Universal Windows Platform",
1681  pathname.c_str()));
1682 #endif
1683 #endif
1684 }
1685 
1696 std::string vpIoTools::createFilePath(const std::string &parent, const std::string &child)
1697 {
1698  if (child.size() == 0 && parent.size() == 0) {
1699  return "";
1700  }
1701 
1702  if (child.size() == 0) {
1703  return vpIoTools::path(parent);
1704  }
1705 
1706  if (parent.size() == 0) {
1707  return vpIoTools::path(child);
1708  }
1709 
1710  std::string convertedParent = vpIoTools::path(parent);
1711  std::string convertedChild = vpIoTools::path(child);
1712 
1713  std::stringstream ss;
1714  ss << vpIoTools::separator;
1715  std::string stringSeparator;
1716  ss >> stringSeparator;
1717 
1718  std::string lastConvertedParentChar = convertedParent.substr(convertedParent.size() - 1);
1719  std::string firstConvertedChildChar = convertedChild.substr(0, 1);
1720 
1721  if (lastConvertedParentChar == stringSeparator) {
1722  convertedParent = convertedParent.substr(0, convertedParent.size() - 1);
1723  }
1724 
1725  if (firstConvertedChildChar == stringSeparator) {
1726  convertedChild = convertedChild.substr(1);
1727  }
1728 
1729  return std::string(convertedParent + vpIoTools::separator + convertedChild);
1730 }
1731 
1737 bool vpIoTools::isAbsolutePathname(const std::string &pathname)
1738 {
1739  //# Inspired by the Python 2.7.8 module.
1740  //# Return whether a path is absolute.
1741  //# Trivial in Posix, harder on the Mac or MS-DOS.
1742  //# For DOS it is absolute if it starts with a slash or backslash (current
1743  //# volume), or if a pathname after the volume letter and colon / UNC
1744  // resource # starts with a slash or backslash.
1745  //
1746  // def isabs(s):
1747  // """Test whether a path is absolute"""
1748  // s = splitdrive(s)[1]
1749  // return s != '' and s[:1] in '/\\'
1750  std::string path = splitDrive(pathname).second;
1751  return path.size() > 0 && (path.substr(0, 1) == "/" || path.substr(0, 1) == "\\");
1752 }
1753 
1761 bool vpIoTools::isSamePathname(const std::string &pathname1, const std::string &pathname2)
1762 {
1763  // Normalize path
1764  std::string path1_normalize = vpIoTools::path(pathname1);
1765  std::string path2_normalize = vpIoTools::path(pathname2);
1766 
1767  // Get absolute path
1768  path1_normalize = vpIoTools::getAbsolutePathname(path1_normalize);
1769  path2_normalize = vpIoTools::getAbsolutePathname(path2_normalize);
1770 
1771  return (path1_normalize == path2_normalize);
1772 }
1773 
1781 std::pair<std::string, std::string> vpIoTools::splitDrive(const std::string &pathname)
1782 {
1783 //# Split a path in a drive specification (a drive letter followed by a
1784 //# colon) and the path specification.
1785 //# It is always true that drivespec + pathspec == p
1786 // def splitdrive(p):
1787 // """Split a pathname into drive/UNC sharepoint and relative path
1788 // specifiers. Returns a 2-tuple (drive_or_unc, path); either part may be
1789 // empty.
1790 //
1791 // If you assign
1792 // result = splitdrive(p)
1793 // It is always true that:
1794 // result[0] + result[1] == p
1795 //
1796 // If the path contained a drive letter, drive_or_unc will contain
1797 // everything up to and including the colon. e.g. splitdrive("c:/dir")
1798 // returns ("c:", "/dir")
1799 //
1800 // If the path contained a UNC path, the drive_or_unc will contain the host
1801 // name and share up to but not including the fourth directory separator
1802 // character. e.g. splitdrive("//host/computer/dir") returns
1803 // ("//host/computer", "/dir")
1804 //
1805 // Paths cannot contain both a drive letter and a UNC path.
1806 //
1807 // """
1808 // if len(p) > 1:
1809 // normp = p.replace(altsep, sep)
1810 // if (normp[0:2] == sep*2) and (normp[2] != sep):
1811 // # is a UNC path:
1812 // # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1813 // # \\machine\mountpoint\directory\etc\...
1814 // # directory ^^^^^^^^^^^^^^^
1815 // index = normp.find(sep, 2)
1816 // if index == -1:
1817 // return '', p
1818 // index2 = normp.find(sep, index + 1)
1819 // # a UNC path can't have two slashes in a row
1820 // # (after the initial two)
1821 // if index2 == index + 1:
1822 // return '', p
1823 // if index2 == -1:
1824 // index2 = len(p)
1825 // return p[:index2], p[index2:]
1826 // if normp[1] == ':':
1827 // return p[:2], p[2:]
1828 // return '', p
1829 
1830 // On Unix, the drive is always empty.
1831 // On the Mac, the drive is always empty (don't use the volume name -- it
1832 // doesn't have the same syntactic and semantic oddities as DOS drive
1833 // letters, such as there being a separate current directory per drive).
1834 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
1835  return std::pair<std::string, std::string>("", pathname);
1836 #else
1837  const std::string sep = "\\";
1838  const std::string sepsep = "\\\\";
1839  const std::string altsep = "/";
1840 
1841  if (pathname.size() > 1) {
1842  std::string normPathname = pathname;
1843  std::replace(normPathname.begin(), normPathname.end(), *altsep.c_str(), *sep.c_str());
1844 
1845  if (normPathname.substr(0, 2) == sepsep && normPathname.substr(2, 1) != sep) {
1846  // is a UNC path:
1847  // vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
1848  // \\machine\mountpoint\directory\etc\...
1849  // directory ^^^^^^^^^^^^^^^
1850  size_t index = normPathname.find(sep, 2);
1851  if (index == std::string::npos) {
1852  return std::pair<std::string, std::string>("", pathname);
1853  }
1854 
1855  size_t index2 = normPathname.find(sep, index + 1);
1856  //# a UNC path can't have two slashes in a row
1857  //# (after the initial two)
1858  if (index2 == index + 1) {
1859  return std::pair<std::string, std::string>("", pathname);
1860  }
1861 
1862  if (index2 == std::string::npos) {
1863  index2 = pathname.size();
1864  }
1865 
1866  return std::pair<std::string, std::string>(pathname.substr(0, index2), pathname.substr(index2));
1867  }
1868 
1869  if (normPathname[1] == ':') {
1870  return std::pair<std::string, std::string>(pathname.substr(0, 2), pathname.substr(2));
1871  }
1872  }
1873 
1874  return std::pair<std::string, std::string>("", pathname);
1875 #endif
1876 }
1877 
1926 std::vector<std::string> vpIoTools::splitChain(const std::string &chain, const std::string &sep)
1927 {
1928  size_t startIndex = 0;
1929 
1930  std::string chainToSplit = chain;
1931  std::vector<std::string> subChain;
1932  size_t sepIndex = chainToSplit.find(sep);
1933 
1934  while (sepIndex != std::string::npos) {
1935  std::string sub = chainToSplit.substr(startIndex, sepIndex);
1936  if (!sub.empty())
1937  subChain.push_back(sub);
1938  chainToSplit = chainToSplit.substr(sepIndex + 1, chain.size() - 1);
1939 
1940  sepIndex = chainToSplit.find(sep);
1941  }
1942  if (!chainToSplit.empty())
1943  subChain.push_back(chainToSplit);
1944 
1945  return subChain;
1946 }
1947 
1955 std::vector<std::string> vpIoTools::getDirFiles(const std::string &pathname)
1956 {
1957 
1958  if (!checkDirectory(pathname)) {
1959  throw(vpIoException(vpException::fatalError, "Directory %s doesn't exist'", pathname.c_str()));
1960  }
1961  std::string dirName = path(pathname);
1962 
1963 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
1964 
1965  std::vector<std::string> files;
1966  struct dirent **list = NULL;
1967  int filesCount = scandir(dirName.c_str(), &list, NULL, NULL);
1968  if (filesCount == -1) {
1969  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1970  }
1971  for (int i = 0; i < filesCount; i++) {
1972  std::string fileName = list[i]->d_name;
1973  if (fileName != "." && fileName != "..") {
1974  files.push_back(fileName);
1975  }
1976  free(list[i]);
1977  }
1978  free(list);
1979  std::sort(files.begin(), files.end());
1980  return files;
1981 
1982 #elif defined(_WIN32)
1983 #if (!defined(WINRT))
1984 
1985  std::vector<std::string> files;
1986  std::string fileMask = dirName;
1987  fileMask.append("\\*");
1988  WIN32_FIND_DATA FindFileData;
1989  HANDLE hFind = FindFirstFile(fileMask.c_str(), &FindFileData);
1990  // Directory is empty
1991  if (HandleToLong(&hFind) == ERROR_FILE_NOT_FOUND) {
1992  return files;
1993  }
1994  if (hFind == INVALID_HANDLE_VALUE) {
1995  throw(vpIoException(vpException::fatalError, "Cannot read files of directory %s", dirName.c_str()));
1996  }
1997  do {
1998  std::string fileName = FindFileData.cFileName;
1999  if (fileName != "." && fileName != "..") {
2000  files.push_back(fileName);
2001  }
2002  } while (FindNextFile(hFind, &FindFileData));
2003  FindClose(hFind);
2004  std::sort(files.begin(), files.end());
2005  return files;
2006 
2007 #else
2009  "Cannot read files of directory %s: not implemented on "
2010  "Universal Windows Platform",
2011  dirName.c_str()));
2012 #endif
2013 #endif
2014 }
2015 
2019 void vpIoTools::readBinaryValueLE(std::ifstream &file, int16_t &short_value)
2020 {
2021  file.read((char *)(&short_value), sizeof(short_value));
2022 
2023 #ifdef VISP_BIG_ENDIAN
2024  // Swap bytes order from little endian to big endian
2025  short_value = vpEndian::swap16bits((uint16_t)short_value);
2026 #endif
2027 }
2028 
2032 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint16_t &ushort_value)
2033 {
2034  file.read((char *)(&ushort_value), sizeof(ushort_value));
2035 
2036 #ifdef VISP_BIG_ENDIAN
2037  // Swap bytes order from little endian to big endian
2038  ushort_value = vpEndian::swap16bits(ushort_value);
2039 #endif
2040 }
2041 
2045 void vpIoTools::readBinaryValueLE(std::ifstream &file, int32_t &int_value)
2046 {
2047  file.read((char *)(&int_value), sizeof(int_value));
2048 
2049 #ifdef VISP_BIG_ENDIAN
2050  // Swap bytes order from little endian to big endian
2051  int_value = vpEndian::swap32bits((uint32_t)int_value);
2052 #endif
2053 }
2054 
2058 void vpIoTools::readBinaryValueLE(std::ifstream &file, uint32_t &uint_value)
2059 {
2060  file.read((char *)(&uint_value), sizeof(uint_value));
2061 
2062 #ifdef VISP_BIG_ENDIAN
2063  // Swap bytes order from little endian to big endian
2064  uint_value = vpEndian::swap32bits(uint_value);
2065 #endif
2066 }
2067 
2071 void vpIoTools::readBinaryValueLE(std::ifstream &file, float &float_value)
2072 {
2073  file.read((char *)(&float_value), sizeof(float_value));
2074 
2075 #ifdef VISP_BIG_ENDIAN
2076  // Swap bytes order from little endian to big endian
2077  float_value = vpEndian::swapFloat(float_value);
2078 #endif
2079 }
2080 
2084 void vpIoTools::readBinaryValueLE(std::ifstream &file, double &double_value)
2085 {
2086  file.read((char *)(&double_value), sizeof(double_value));
2087 
2088 #ifdef VISP_BIG_ENDIAN
2089  // Swap bytes order from little endian to big endian
2090  double_value = vpEndian::swapDouble(double_value);
2091 #endif
2092 }
2093 
2097 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int16_t short_value)
2098 {
2099 #ifdef VISP_BIG_ENDIAN
2100  // Swap bytes order to little endian
2101  uint16_t swap_short = vpEndian::swap16bits((uint16_t)short_value);
2102  file.write((char *)(&swap_short), sizeof(swap_short));
2103 #else
2104  file.write((char *)(&short_value), sizeof(short_value));
2105 #endif
2106 }
2107 
2111 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint16_t ushort_value)
2112 {
2113 #ifdef VISP_BIG_ENDIAN
2114  // Swap bytes order to little endian
2115  uint16_t swap_ushort = vpEndian::swap16bits(ushort_value);
2116  file.write((char *)(&swap_ushort), sizeof(swap_ushort));
2117 #else
2118  file.write((char *)(&ushort_value), sizeof(ushort_value));
2119 #endif
2120 }
2121 
2125 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const int32_t int_value)
2126 {
2127 #ifdef VISP_BIG_ENDIAN
2128  // Swap bytes order to little endian
2129  uint32_t swap_int = vpEndian::swap32bits((uint32_t)int_value);
2130  file.write((char *)(&swap_int), sizeof(swap_int));
2131 #else
2132  file.write((char *)(&int_value), sizeof(int_value));
2133 #endif
2134 }
2135 
2139 void vpIoTools::writeBinaryValueLE(std::ofstream &file, const uint32_t uint_value)
2140 {
2141 #ifdef VISP_BIG_ENDIAN
2142  // Swap bytes order to little endian
2143  uint32_t swap_int = vpEndian::swap32bits(uint_value);
2144  file.write((char *)(&swap_int), sizeof(swap_int));
2145 #else
2146  file.write((char *)(&uint_value), sizeof(uint_value));
2147 #endif
2148 }
2149 
2153 void vpIoTools::writeBinaryValueLE(std::ofstream &file, float float_value)
2154 {
2155 #ifdef VISP_BIG_ENDIAN
2156  // Swap bytes order to little endian
2157  float swap_float = vpEndian::swapFloat(float_value);
2158  file.write((char *)(&swap_float), sizeof(swap_float));
2159 #else
2160  file.write((char *)(&float_value), sizeof(float_value));
2161 #endif
2162 }
2163 
2167 void vpIoTools::writeBinaryValueLE(std::ofstream &file, double double_value)
2168 {
2169 #ifdef VISP_BIG_ENDIAN
2170  // Swap bytes order to little endian
2171  double swap_double = vpEndian::swapDouble(double_value);
2172  file.write((char *)(&swap_double), sizeof(swap_double));
2173 #else
2174  file.write((char *)(&double_value), sizeof(double_value));
2175 #endif
2176 }
2177 
2178 bool vpIoTools::parseBoolean(std::string input)
2179 {
2180  std::transform(input.begin(), input.end(), input.begin(), ::tolower);
2181  std::istringstream is(input);
2182  bool b;
2183  // Parse string to boolean either in the textual representation
2184  // (True/False) or in numeric representation (1/0)
2185  is >> (input.size() > 1 ? std::boolalpha : std::noboolalpha) >> b;
2186  return b;
2187 }
2188 
2192 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:391
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1378
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1926
static std::vector< std::string > configVars
Definition: vpIoTools.h:256
static std::string path(const std::string &pathname)
Definition: vpIoTools.cpp:1016
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1654
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:810
static bool readConfigVar(const std::string &var, float &value)
Definition: vpIoTools.cpp:1105
static void setBaseName(const std::string &s)
Definition: vpIoTools.cpp:245
static std::pair< std::string, std::string > splitDrive(const std::string &pathname)
Definition: vpIoTools.cpp:1781
static bool isSamePathname(const std::string &pathname1, const std::string &pathname2)
Definition: vpIoTools.cpp:1761
static std::string getTempPath()
Definition: vpIoTools.cpp:207
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1737
static void setBaseDir(const std::string &dir)
Definition: vpIoTools.cpp:252
static std::string baseDir
Definition: vpIoTools.h:254
static bool loadConfigFile(const std::string &confFile)
Definition: vpIoTools.cpp:1056
static bool copy(const std::string &src, const std::string &dst)
Definition: vpIoTools.cpp:852
static std::string trim(std::string s)
Definition: vpIoTools.cpp:2192
static void readBinaryValueLE(std::ifstream &file, int16_t &short_value)
Definition: vpIoTools.cpp:2019
static void saveConfigFile(const bool &actuallySave=true)
Definition: vpIoTools.cpp:1356
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:431
static bool rename(const std::string &oldfilename, const std::string &newfilename)
Definition: vpIoTools.cpp:998
static bool parseBoolean(std::string input)
Definition: vpIoTools.cpp:2178
static long getIndex(const std::string &filename, const std::string &format)
Definition: vpIoTools.cpp:1587
static std::string getUserName()
Definition: vpIoTools.cpp:327
static std::string getFullName()
Definition: vpIoTools.cpp:266
static void addNameElement(const std::string &strTrue, const bool &cond=true, const std::string &strFalse="")
Definition: vpIoTools.cpp:1302
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1696
static std::string getenv(const std::string &env)
Definition: vpIoTools.cpp:364
static const std::string & getBuildInformation()
Definition: vpIoTools.cpp:148
static std::string getBaseName()
Definition: vpIoTools.cpp:259
static std::string getFileExtension(const std::string &pathname, bool checkFile=false)
Definition: vpIoTools.cpp:1443
static std::string baseName
Definition: vpIoTools.h:253
static void createBaseNamePath(const bool &empty=false)
Definition: vpIoTools.cpp:1337
static std::vector< std::string > getDirFiles(const std::string &dirname)
Definition: vpIoTools.cpp:1955
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:581
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:2097
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:939
static std::string getNameWE(const std::string &pathname)
Definition: vpIoTools.cpp:1546
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:734
static bool checkFifo(const std::string &filename)
Definition: vpIoTools.cpp:491
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1630
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1524
static const char separator
Definition: vpIoTools.h:186
static void makeFifo(const std::string &dirname)
Definition: vpIoTools.cpp:632
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