From 990b5091111d54c8ac26c81899f1a713e2771b4c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 20 Feb 2023 14:46:24 -0500 Subject: [PATCH] Added GetRelativePath --- BeefySysLib/Common.cpp | 176 +++++++++++++++++++++++++++++++---------- BeefySysLib/Common.h | 1 + 2 files changed, 135 insertions(+), 42 deletions(-) diff --git a/BeefySysLib/Common.cpp b/BeefySysLib/Common.cpp index 28f0e7e9..abedc863 100644 --- a/BeefySysLib/Common.cpp +++ b/BeefySysLib/Common.cpp @@ -2,7 +2,7 @@ #include "util/BumpAllocator.h" #include "util/UTF8.h" #include "util/String.h" -//#include "farts.z" +//#include "farts.z" #include #include "platform/PlatformHelper.h" @@ -48,11 +48,11 @@ UTF16String Beefy::ToWString(const StringImpl& theString) // String Beefy::ToString(const UTF16String& theString) // { -// String newString; +// String newString; // newString.Reserve((intptr)theString.length()); // for (int i = 0; i < (int)theString.length(); ++i) // { -// const unsigned int c = (unsigned int)theString[i]; +// const unsigned int c = (unsigned int)theString[i]; // newString.Append(char(c & 0xFF)); // } // return newString; @@ -67,9 +67,9 @@ String Beefy::ToUpper(const StringImpl& theString) } void Beefy::MakeUpper(StringImpl& theString) -{ +{ for (int i = 0; i < (int)theString.length(); ++i) - theString[i] = toupper(theString[i]); + theString[i] = toupper(theString[i]); } UTF16String Beefy::ToUpper(const UTF16String& theString) @@ -101,14 +101,14 @@ String Beefy::ToLower(const StringImpl& theString) // int left = 0; // while ((left < (int) theString.length() - 1) && (iswspace(theString[left]))) // left++; -// +// // int right = (int)theString.length() - 1; // while ((right >= left) && (iswspace(theString[right]))) // right--; -// +// // if ((left == 0) && (right == theString.length() - 1)) // return theString; -// +// // return theString.substr(left, right - left + 1); // } @@ -124,7 +124,7 @@ String Beefy::Trim(const StringImpl& theString) if ((left == 0) && (right == theString.length() - 1)) return theString; - + return theString.Substring(left, right - left + 1); } @@ -155,7 +155,7 @@ String Beefy::SlashString(const StringImpl& str, bool utf8decode, bool utf8encod { bool prevEndedInSlashedNum = false; String outStr; - + bool noNextHex = false; bool lastWasVisibleChar = false; @@ -217,7 +217,7 @@ String Beefy::SlashString(const StringImpl& str, bool utf8decode, bool utf8encod // Need to break string to allow proper evaluation of slashed string if (prevEndedInSlashedNum) outStr += "\" \""; - } + } // May be UTF8 byte. Make sure it's valid before we add it, otherwise write the bytes in direct "\x" style if (((uint8)c >= 0x80) && (utf8decode)) @@ -295,7 +295,7 @@ String Beefy::SlashString(const StringImpl& str, bool utf8decode, bool utf8encod } if (((uint8)c >= 0x80) && (utf8encode)) - { + { outStr += (char)(0xC0 | (((uint8)c & 0xFF) >> 6)); outStr += (char)(0x80 | ((uint8)c & 0x3F)); isVisibleChar = true; @@ -330,7 +330,7 @@ String Beefy::SlashString(const StringImpl& str, bool utf8decode, bool utf8encod UTF16String Beefy::UTF8Decode(const StringImpl& theString) { UTF16String strOut; - + int strLen = 0; char* cPtr = (char*)theString.c_str(); int lenLeft = (int)theString.length(); @@ -345,7 +345,7 @@ UTF16String Beefy::UTF8Decode(const StringImpl& theString) cPtr += seqLen; lenLeft -= seqLen; } - + strOut.ResizeRaw(strLen + 1); strOut[strLen] = 0; @@ -360,12 +360,12 @@ UTF16String Beefy::UTF8Decode(const StringImpl& theString) if ((c32 >= 0x10000) && (sizeof(wchar_t) == 2)) { *(wcPtr++) = (wchar_t)(((c32 - 0x10000) >> 10) + 0xD800); - *(wcPtr++) = (wchar_t)(((c32 - 0x10000) & 0x3FF) + 0xDC00); + *(wcPtr++) = (wchar_t)(((c32 - 0x10000) & 0x3FF) + 0xDC00); wcLenLeft -= 2; } else { - *(wcPtr++) = (wchar_t)c32; + *(wcPtr++) = (wchar_t)c32; wcLenLeft -= 1; } cPtr += seqLen; @@ -382,7 +382,7 @@ String Beefy::UTF8Encode(const uint16* theString, int length) String strOut; int utf8Len = 0; - uint16 utf16hi = 0; + uint16 utf16hi = 0; for (int i = 0; i < length; i++) { uint16 c = theString[i]; @@ -406,7 +406,7 @@ String Beefy::UTF8Encode(const uint16* theString, int length) for (int i = 0; i < length; i++) { uint16 c = theString[i]; - uint32 c32 = c; + uint32 c32 = c; if ((c >= 0xD800) && (c < 0xDC00)) { utf16hi = (uint16)c; @@ -452,7 +452,7 @@ UTF16String Beefy::UTF16Decode(const uint16* theString) for (int pos = 0; pos < len; pos++) str[pos] = (wchar_t)theString[pos]; return str; - } + } } static const char gHexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -466,13 +466,13 @@ String Beefy::FileNameToURI(const StringImpl& fileName) for (int i = 0; i < (int)fileName.length(); i++) { char c = out[i]; - - bool isValid = + + bool isValid = ((c >= '@' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '&' && c < 0x3b) || (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~')); - + if ((((unsigned char)c) >= 0x80) || (!isValid)) { out += '%'; @@ -515,14 +515,14 @@ static const char c64bToChar[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '_'}; void Beefy::EncodeULEB32(uint64 value, StringImpl& buffer) { - do + do { uint8 byteVal = value & 0x1f; value >>= 5; if (value != 0) byteVal |= 0x20; // Mark this byte to show that more bytes will follow buffer.Append(c64bToChar[byteVal]); - } + } while (value != 0); } @@ -601,7 +601,7 @@ void Beefy::ExactMinimalDoubleToStr(double d, char* str) { char c = cPtrLast[1]; if ((c == 0) || (c == 'e')) - break; + break; cPtrLast++; } char* cStrEnd = cPtrLast + 1; @@ -622,10 +622,10 @@ void Beefy::ExactMinimalDoubleToStr(double d, char* str) else { return; // Not a 'transitional' representation - } + } do - { + { *cPtrLast = 0; cPtrLast--; } @@ -637,7 +637,7 @@ void Beefy::ExactMinimalDoubleToStr(double d, char* str) // Verify that our pretty representation is equivalent double checkD = 0; - sscanf(str, "%lf", &checkD); + sscanf(str, "%lf", &checkD); if (d == checkD) return; @@ -823,7 +823,7 @@ String Beefy::vformat(const char* fmt, va_list argPtr) } #endif -String Beefy::StrFormat(const char* fmt ...) +String Beefy::StrFormat(const char* fmt ...) { va_list argList; va_start(argList, fmt); @@ -899,7 +899,7 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size) { //UTF16 LE - int dataLen = fileSize - 2; + int dataLen = fileSize - 2; char* data = new char[dataLen + 2]; data[0] = (char)charHeader[2]; data[dataLen] = 0; @@ -910,7 +910,7 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size) // UTF16 UTF16String str; - str.Set((wchar_t*)data); + str.Set((wchar_t*)data); delete [] data; String utf8Str = UTF8Encode(str); @@ -923,18 +923,18 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size) return utf8Data; } else if ((charHeader[0] == 0xEF) && (charHeader[1] == 0xBB) && (charHeader[2] == 0xBF)) - { + { strLen = fileSize - 3; - char* data = new char[strLen + 1]; + char* data = new char[strLen + 1]; data[strLen] = 0; if (size != NULL) *size = strLen; int readSize = (int)fread(data, 1, strLen, fP); (void)readSize; - fclose(fP); + fclose(fP); return data; } - + if (size != NULL) *size = strLen; char* data = new char[strLen + 1]; @@ -957,7 +957,7 @@ bool Beefy::LoadTextData(const StringImpl& path, StringImpl& str) if (data == NULL) return false; if ((str.mAllocSizeAndFlags & StringImpl::DynAllocFlag) != 0) - str.Release(); + str.Release(); str.mPtr = data; str.mAllocSizeAndFlags = size | StringImpl::DynAllocFlag | StringImpl::StrPtrFlag; str.mLength = size; @@ -1044,6 +1044,98 @@ String Beefy::GetFileExtension(const StringImpl& path) return path.Substring(dotPos); } +static String GetDriveStringTo(String path) +{ + if ((path.length() >= 2) && (path[1] == ':')) + return String(path, 0, 2); + return ""; +} + +String Beefy::GetRelativePath(const StringImpl& fullPath, const StringImpl& curDir) +{ + String curPath1 = String(curDir); + String curPath2 = String(fullPath); + + for (int i = 0; i < (int)curPath1.length(); i++) + if (curPath1[i] == DIR_SEP_CHAR_ALT) + curPath1[i] = DIR_SEP_CHAR; + + for (int i = 0; i < (int)curPath2.length(); i++) + if (curPath2[i] == DIR_SEP_CHAR_ALT) + curPath2[i] = DIR_SEP_CHAR; + + String driveString1 = GetDriveStringTo(curPath1); + String driveString2 = GetDriveStringTo(curPath2); + +#ifdef _WIN32 + StringImpl::CompareKind compareType = StringImpl::CompareKind_OrdinalIgnoreCase; +#else + StringImpl::CompareKind compareType = StringImpl::CompareKind_Ordinal; +#endif + + // On separate drives? + if (!driveString1.Equals(driveString2, compareType)) + { + return fullPath; + } + + if (driveString1.mLength > 0) + curPath1.Remove(0, BF_MIN(driveString1.mLength + 1, curPath1.mLength)); + if (driveString2.mLength > 0) + curPath2.Remove(0, BF_MIN(driveString2.mLength + 1, curPath2.mLength)); + + while ((curPath1.mLength > 0) && (curPath2.mLength > 0)) + { + int slashPos1 = (int)curPath1.IndexOf(DIR_SEP_CHAR); + if (slashPos1 == -1) + slashPos1 = curPath1.mLength; + int slashPos2 = (int)curPath2.IndexOf(DIR_SEP_CHAR); + if (slashPos2 == -1) + slashPos2 = curPath2.mLength; + + String section1; + section1.Append(StringView(curPath1, 0, slashPos1)); + String section2; + section2.Append(StringView(curPath2, 0, slashPos2)); + + if (!section1.Equals(section2, compareType)) + { + // a/b/c + // d/e/f + + while (curPath1.mLength > 0) + { + slashPos1 = (int)curPath1.IndexOf(DIR_SEP_CHAR); + if (slashPos1 == -1) + slashPos1 = curPath1.mLength; + + if (slashPos1 + 1 >= curPath1.mLength) + curPath1.Clear(); + else + curPath1.Remove(0, slashPos1 + 1); + if (DIR_SEP_CHAR == '\\') + curPath2.Insert(0, "..\\"); + else + curPath2.Insert(0, "../"); + } + } + else + { + if (slashPos1 + 1 >= curPath1.mLength) + curPath1.Clear(); + else + curPath1.Remove(0, slashPos1 + 1); + + if (slashPos2 + 2 >= curPath2.mLength) + curPath1 = ""; + else + curPath2.Remove(0, slashPos2 + 1); + } + } + + return curPath2; +} + String Beefy::GetAbsPath(const StringImpl& relPathIn, const StringImpl& dir) { String relPath = relPathIn; @@ -1119,7 +1211,7 @@ String Beefy::GetAbsPath(const StringImpl& relPathIn, const StringImpl& dir) } else if (chDir != ".") { - newPath += chDir + slashChar; + newPath += chDir + slashChar; break; } } @@ -1129,7 +1221,7 @@ String Beefy::GetAbsPath(const StringImpl& relPathIn, const StringImpl& dir) newPath += relPath.Substring(relIdx); return newPath; -} +} String Beefy::FixPath(const StringImpl& pathIn) { @@ -1144,7 +1236,7 @@ String Beefy::FixPath(const StringImpl& pathIn) for (int checkIdx = i - 3; checkIdx >= 0; checkIdx--) { if ((path[checkIdx] == '\\') || (path[checkIdx] == '/')) - { + { path = path.Substring(0, checkIdx) + path.Substring(i + 1); i = checkIdx; break; @@ -1189,10 +1281,10 @@ String Beefy::RemoveTrailingSlash(const StringImpl& str) bool Beefy::FileNameEquals(const StringImpl& filePathA, const StringImpl& filePathB) { -#ifdef _WIN32 +#ifdef _WIN32 if (filePathA.length() != filePathB.length()) return false; - + const char* aPtr = filePathA.c_str(); const char* bPtr = filePathB.c_str(); while (true) @@ -1250,7 +1342,7 @@ bool Beefy::RecursiveDeleteDirectory(const StringImpl& dirPath) BfpFileResult result; BfpFindFileData* findFileData = BfpFindFileData_FindFirstFile(findSpec.c_str(), (BfpFindFileFlags)(BfpFindFileFlag_Directories | BfpFindFileFlag_Files), &result); if (result == BfpFileResult_Ok) - { + { while (true) { Beefy::String fileName; diff --git a/BeefySysLib/Common.h b/BeefySysLib/Common.h index e2a61beb..fa164320 100644 --- a/BeefySysLib/Common.h +++ b/BeefySysLib/Common.h @@ -226,6 +226,7 @@ int64 GetFileTimeWrite(const StringImpl& path); String GetFileDir(const StringImpl& path); String GetFileName(const StringImpl& path); String GetFileExtension(const StringImpl& path); +String GetRelativePath(const StringImpl& fullPath, const StringImpl& curDir); String GetAbsPath(const StringImpl& relPath, const StringImpl& dir); String FixPath(const StringImpl& path); String FixPathAndCase(const StringImpl& path);