3232#include < unistd.h>
3333#else
3434#include < direct.h>
35+ #include < stdexcept>
3536#endif
3637#if defined(__CYGWIN__)
3738#include < strings.h>
3839#endif
3940
4041#include < simplecpp.h>
4142
43+ #if defined(_WIN32) && !defined(__MINGW32__)
44+ static const char SEP_NATIVE = ' \\ ' ;
45+ #else
46+ static const char SEP_NATIVE = ' /' ;
47+ #endif
48+
4249/* * Is the filesystem case insensitive? */
4350static bool caseInsensitiveFilesystem ()
4451{
@@ -54,20 +61,16 @@ std::string Path::toNativeSeparators(std::string path)
5461{
5562#if defined(_WIN32)
5663 const char separ = ' /' ;
57- const char native = ' \\ ' ;
5864#else
5965 const char separ = ' \\ ' ;
60- const char native = ' /' ;
6166#endif
62- std::replace (path.begin (), path.end (), separ, native );
67+ std::replace (path.begin (), path.end (), separ, SEP_NATIVE );
6368 return path;
6469}
6570
6671std::string Path::fromNativeSeparators (std::string path)
6772{
68- const char nonnative = ' \\ ' ;
69- const char newsepar = ' /' ;
70- std::replace (path.begin (), path.end (), nonnative, newsepar);
73+ std::replace (path.begin (), path.end (), ' \\ ' , ' /' );
7174 return path;
7275}
7376
@@ -211,9 +214,13 @@ std::string Path::getAbsoluteFilePath(const std::string& filePath)
211214 if (_fullpath (absolute, filePath.c_str (), _MAX_PATH))
212215 absolute_path = absolute;
213216#elif defined(__linux__) || defined(__sun) || defined(__hpux) || defined(__GNUC__) || defined(__CPPCHECK__)
217+ // realpath() only works with files that actually exist
214218 char * absolute = realpath (filePath.c_str (), nullptr );
215- if (absolute)
216- absolute_path = absolute;
219+ if (!absolute) {
220+ const int err = errno;
221+ throw std::runtime_error (" realpath() failed with " + std::to_string (err));
222+ }
223+ absolute_path = absolute;
217224 free (absolute);
218225#else
219226#error Platform absolute path function needed
@@ -223,13 +230,7 @@ std::string Path::getAbsoluteFilePath(const std::string& filePath)
223230
224231std::string Path::stripDirectoryPart (const std::string &file)
225232{
226- #if defined(_WIN32) && !defined(__MINGW32__)
227- const char native = ' \\ ' ;
228- #else
229- const char native = ' /' ;
230- #endif
231-
232- const std::string::size_type p = file.rfind (native);
233+ const std::string::size_type p = file.rfind (SEP_NATIVE);
233234 if (p != std::string::npos) {
234235 return file.substr (p + 1 );
235236 }
@@ -243,6 +244,8 @@ bool Path::fileExists(const std::string &file)
243244}
244245
245246std::string Path::join (std::string path1, std::string path2) {
247+ path1 = fromNativeSeparators (std::move (path1));
248+ path2 = fromNativeSeparators (std::move (path2));
246249 if (path1.empty () || path2.empty ())
247250 return path1 + path2;
248251 if (path2.front () == ' /' )
0 commit comments