add last backwards-compatible version
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
#include "pfc.h"
|
||||
|
||||
static_assert(L'Ö' == 0xD6, "Compile as Unicode!!!");
|
||||
#include "pfc.h"
|
||||
|
||||
namespace pfc { namespace io { namespace path {
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define KPathSeparators "\\/|"
|
||||
static const string g_pathSeparators ("\\/|");
|
||||
#else
|
||||
#define KPathSeparators "/"
|
||||
static const string g_pathSeparators ("/");
|
||||
#endif
|
||||
|
||||
string getFileName(string path) {
|
||||
t_size split = path.lastIndexOfAnyChar(KPathSeparators);
|
||||
t_size split = path.lastIndexOfAnyChar(g_pathSeparators);
|
||||
if (split == ~0) return path;
|
||||
else return path.subString(split+1);
|
||||
}
|
||||
@@ -30,7 +28,7 @@ string getFileExtension(string path) {
|
||||
string getDirectory(string filePath) {return getParent(filePath);}
|
||||
|
||||
string getParent(string filePath) {
|
||||
t_size split = filePath.lastIndexOfAnyChar(KPathSeparators);
|
||||
t_size split = filePath.lastIndexOfAnyChar(g_pathSeparators);
|
||||
if (split == ~0) return "";
|
||||
#ifdef _WINDOWS
|
||||
if (split > 0 && getIllegalNameChars().contains(filePath[split-1])) {
|
||||
@@ -53,55 +51,27 @@ string combine(string basePath,string fileName) {
|
||||
}
|
||||
|
||||
bool isSeparator(char c) {
|
||||
return strchr(KPathSeparators, c) != nullptr;
|
||||
return g_pathSeparators.indexOf(c) != ~0;
|
||||
}
|
||||
string getSeparators() {
|
||||
return KPathSeparators;
|
||||
return g_pathSeparators;
|
||||
}
|
||||
|
||||
const char * charReplaceDefault(char c) {
|
||||
switch (c) {
|
||||
case '*':
|
||||
return "x";
|
||||
case '\"':
|
||||
return "\'\'";
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
return "-";
|
||||
case '?':
|
||||
return "";
|
||||
default:
|
||||
return "_";
|
||||
static string replaceIllegalChar(char c) {
|
||||
switch(c) {
|
||||
case '*':
|
||||
return "x";
|
||||
case '\"':
|
||||
return "\'\'";
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
return "-";
|
||||
default:
|
||||
return "_";
|
||||
}
|
||||
}
|
||||
|
||||
const char * charReplaceModern(char c) {
|
||||
switch (c) {
|
||||
case '*':
|
||||
return u8"∗";
|
||||
case '\"':
|
||||
return u8"''";
|
||||
case ':':
|
||||
return u8"∶";
|
||||
case '/':
|
||||
return u8"⁄";
|
||||
case '\\':
|
||||
return u8"⧵";
|
||||
case '?':
|
||||
return u8"?";
|
||||
case '<':
|
||||
return u8"˂";
|
||||
case '>':
|
||||
return u8"˃";
|
||||
case '|':
|
||||
return u8"∣";
|
||||
default:
|
||||
return "_";
|
||||
}
|
||||
}
|
||||
|
||||
string replaceIllegalPathChars(string fn, charReplace_t replaceIllegalChar) {
|
||||
string replaceIllegalPathChars(string fn) {
|
||||
string illegal = getIllegalNameChars();
|
||||
string separators = getSeparators();
|
||||
string_formatter output;
|
||||
@@ -120,7 +90,7 @@ string replaceIllegalPathChars(string fn, charReplace_t replaceIllegalChar) {
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
string replaceIllegalNameChars(string fn, bool allowWC, charReplace_t replaceIllegalChar) {
|
||||
string replaceIllegalNameChars(string fn, bool allowWC) {
|
||||
const string illegal = getIllegalNameChars(allowWC);
|
||||
string_formatter output;
|
||||
for(t_size walk = 0; walk < fn.length(); ++walk) {
|
||||
@@ -159,36 +129,37 @@ char getDefaultSeparator() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static const string g_illegalNameChars(g_pathSeparators
|
||||
#ifdef _WINDOWS
|
||||
#define KIllegalNameCharsEx ":<>\""
|
||||
+ ":<>*?\""
|
||||
#else
|
||||
// Mac OS allows : in filenames but does funny things presenting them in Finder, so don't use it
|
||||
#define KIllegalNameCharsEx ":"
|
||||
+ "*?"
|
||||
#endif
|
||||
|
||||
#define KWildcardChars "*?"
|
||||
|
||||
#define KIllegalNameChars KPathSeparators KIllegalNameCharsEx KWildcardChars
|
||||
#define KIllegalNameChars_noWC KPathSeparators KIllegalNameCharsEx
|
||||
|
||||
static string g_illegalNameChars ( KIllegalNameChars );
|
||||
static string g_illegalNameChars_noWC ( KIllegalNameChars_noWC );
|
||||
|
||||
);
|
||||
|
||||
static const string g_illegalNameChars_noWC(g_pathSeparators
|
||||
#ifdef _WINDOWS
|
||||
+ ":<>?\""
|
||||
#endif
|
||||
);
|
||||
string getIllegalNameChars(bool allowWC) {
|
||||
return allowWC ? g_illegalNameChars_noWC : g_illegalNameChars;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
static bool isIllegalTrailingChar(char c) {
|
||||
return c == ' ' || c == '.';
|
||||
}
|
||||
static const char * const specialIllegalNames[] = {
|
||||
"con", "aux", "lst", "prn", "nul", "eof", "inp", "out"
|
||||
};
|
||||
|
||||
enum { maxPathComponent = 255 };
|
||||
static size_t safeTruncat( const char * str, size_t maxLen ) {
|
||||
size_t i = 0;
|
||||
size_t ret = 0;
|
||||
static unsigned safeTruncat( const char * str, unsigned maxLen ) {
|
||||
unsigned i = 0;
|
||||
unsigned ret = 0;
|
||||
for( ; i < maxLen; ++ i ) {
|
||||
auto d = pfc::utf8_char_len( str + ret );
|
||||
unsigned d = pfc::utf8_char_len( str + ret );
|
||||
if ( d == 0 ) break;
|
||||
ret += d;
|
||||
}
|
||||
@@ -198,7 +169,7 @@ static size_t safeTruncat( const char * str, size_t maxLen ) {
|
||||
static size_t utf8_length( const char * str ) {
|
||||
size_t ret = 0;
|
||||
for (; ++ret;) {
|
||||
size_t d = pfc::utf8_char_len( str );
|
||||
unsigned d = pfc::utf8_char_len( str );
|
||||
if ( d == 0 ) break;
|
||||
str += d;
|
||||
}
|
||||
@@ -222,64 +193,42 @@ static string truncatePathComponent( string name, bool preserveExt ) {
|
||||
}
|
||||
}
|
||||
|
||||
size_t truncat = safeTruncat( name.c_str(), maxPathComponent );
|
||||
unsigned truncat = safeTruncat( name.c_str(), maxPathComponent );
|
||||
return name.subString(0, truncat);
|
||||
}
|
||||
#endif // _WINDOWS
|
||||
|
||||
static string trailingSanity(string name, bool preserveExt, const char * lstIllegal) {
|
||||
#endif
|
||||
|
||||
const auto isIllegalTrailingChar = [lstIllegal](char c) {
|
||||
return strchr(lstIllegal, c) != nullptr;
|
||||
};
|
||||
|
||||
t_size end = name.length();
|
||||
if (preserveExt) {
|
||||
size_t offset = pfc::string_find_last(name.c_str(), '.');
|
||||
if (offset < end) end = offset;
|
||||
}
|
||||
const size_t endEx = end;
|
||||
while (end > 0) {
|
||||
if (!isIllegalTrailingChar(name[end - 1])) break;
|
||||
--end;
|
||||
}
|
||||
t_size begin = 0;
|
||||
while (begin < end) {
|
||||
if (!isIllegalTrailingChar(name[begin])) break;
|
||||
++begin;
|
||||
}
|
||||
if (end < endEx || begin > 0) {
|
||||
name = name.subString(begin, end - begin) + name.subString(endEx);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
string validateFileName(string name, bool allowWC, bool preserveExt, charReplace_t replaceIllegalChar) {
|
||||
if (!allowWC) { // special fix for filenames that consist only of question marks
|
||||
size_t end = name.length();
|
||||
if (preserveExt) {
|
||||
size_t offset = pfc::string_find_last(name.c_str(), '.');
|
||||
if (offset < end) end = offset;
|
||||
}
|
||||
bool unnamed = true;
|
||||
for (size_t walk = 0; walk < end; ++walk) {
|
||||
if (name[walk] != '?') unnamed = false;
|
||||
}
|
||||
if (unnamed) {
|
||||
name = string("[unnamed]") + name.subString(end);
|
||||
string validateFileName(string name, bool allowWC, bool preserveExt) {
|
||||
for(t_size walk = 0; name[walk];) {
|
||||
if (name[walk] == '?') {
|
||||
t_size end = walk;
|
||||
do { ++end; } while(name[end] == '?');
|
||||
if ( walk == 0 && name[end] == '.' ) {
|
||||
name = string("[unnamed]") + name.subString(end);
|
||||
} else {
|
||||
name = name.subString(0, walk) + name.subString(end);
|
||||
}
|
||||
} else {
|
||||
++walk;
|
||||
}
|
||||
}
|
||||
|
||||
// Trailing sanity AFTER replaceIllegalNameChars
|
||||
// replaceIllegalNameChars may remove chars exposing illegal prefix/suffix chars
|
||||
name = replaceIllegalNameChars(name, allowWC, replaceIllegalChar);
|
||||
if (name.length() > 0 && !allowWC) {
|
||||
pfc::string8 lstIllegal = " ";
|
||||
if (!preserveExt) lstIllegal += ".";
|
||||
|
||||
name = trailingSanity(name, preserveExt, lstIllegal);
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
name = replaceIllegalNameChars(name, allowWC);
|
||||
if (name.length() > 0) {
|
||||
t_size end = name.length();
|
||||
while(end > 0) {
|
||||
if (!isIllegalTrailingChar(name[end-1])) break;
|
||||
--end;
|
||||
}
|
||||
t_size begin = 0;
|
||||
while(begin < end) {
|
||||
if (!isIllegalTrailingChar(name[begin])) break;
|
||||
++begin;
|
||||
}
|
||||
if (end < name.length() || begin > 0) name = name.subString(begin,end - begin);
|
||||
}
|
||||
|
||||
name = truncatePathComponent(name, preserveExt);
|
||||
|
||||
for( unsigned w = 0; w < _countof(specialIllegalNames); ++w ) {
|
||||
@@ -288,10 +237,12 @@ string validateFileName(string name, bool allowWC, bool preserveExt, charReplace
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name.isEmpty()) name = "_";
|
||||
return name;
|
||||
#else
|
||||
return replaceIllegalNameChars(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
}}}
|
||||
|
||||
Reference in New Issue
Block a user