00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include "fileutils.h"
00025
00026 #include <cstring>
00027 #include <string>
00028
00029 using namespace std;
00030
00031 #ifdef __WIN32__
00033 static bool
00034 has_drive(const string &path)
00035 {
00036 return (path.size() >= 2 && path[1] == ':');
00037 }
00038
00040 static bool
00041 uncw_path(const string & path)
00042 {
00043 return (path.size() >= 4 && memcmp(path.data(), "\\\\?\\", 4) == 0);
00044 }
00045
00046 inline bool slash(char ch)
00047 {
00048 return ch == '/' || ch == '\\';
00049 }
00050 #endif
00051
00052 void
00053 resolve_relative_path(string & path, const string & base)
00054 {
00055 #ifndef __WIN32__
00056 if (path.empty() || path[0] != '/') {
00057
00058 string::size_type last_slash = base.rfind('/');
00059 if (last_slash != string::npos)
00060 path.insert(0, base, 0, last_slash + 1);
00061 }
00062 #else
00063
00064
00065 bool drive = has_drive(path);
00066 string::size_type p = (drive ? 2 : 0);
00067 bool absolute = (p != path.size() && slash(path[p]));
00068
00069 if (absolute) {
00070
00071 if (drive)
00072 return;
00073
00074
00075 if (has_drive(base)) {
00076 path.insert(0, base, 0, 2);
00077 return;
00078 }
00079
00080
00081
00082 if (uncw_path(base)) {
00083 string::size_type sl = 0;
00084 if (base.size() >= 7 && memcmp(base.data() + 5, ":\\", 2) == 0) {
00085
00086 sl = 6;
00087 } else if (base.size() >= 8 &&
00088 memcmp(base.data() + 4, "UNC\\", 4) == 0) {
00089
00090 sl = base.find('\\', 8);
00091 if (sl != string::npos)
00092 sl = base.find('\\', sl + 1);
00093 }
00094 if (sl) {
00095
00096
00097 string::iterator i;
00098 for (i = path.begin(); i != path.end(); ++i) {
00099 if (*i == '/')
00100 *i = '\\';
00101 }
00102 path.insert(0, base, 0, sl);
00103 }
00104 } else if (base.size() >= 5 && slash(base[0]) && slash(base[1])) {
00105
00106 string::size_type sl = base.find_first_of("/\\", 2);
00107 if (sl != string::npos) {
00108 sl = base.find_first_of("/\\", sl + 1);
00109 path.insert(0, base, 0, sl);
00110 }
00111 }
00112 return;
00113 }
00114
00115
00116
00117 bool base_drive = has_drive(base);
00118 if (!drive || (base_drive && (path[0] | 32) == (base[0] | 32))) {
00119 string::size_type last_slash = base.find_last_of("/\\");
00120 if (last_slash == string::npos && !drive && base_drive)
00121 last_slash = 1;
00122 if (last_slash != string::npos) {
00123 string::size_type b = (drive && base_drive ? 2 : 0);
00124 if (uncw_path(base)) {
00125
00126
00127 string::iterator i;
00128 for (i = path.begin(); i != path.end(); ++i) {
00129 if (*i == '/')
00130 *i = '\\';
00131 }
00132 }
00133 path.insert(b, base, b, last_slash + 1 - b);
00134 }
00135 }
00136 #endif
00137 }