From Sukender, "1. Made code a bit more readable/cleaner.

2. Removed unecessary code. Also made sure the images names are not truncated in the middle of an UTF8 character. You'll find there a function called utf8TruncateBytes(), which may be moved in core OSG (osgDB/ConvertUTF I guess). Feel free to do it if you feel it that way.
"
This commit is contained in:
Robert Osfield
2011-03-09 14:44:14 +00:00
parent d3d0859b4c
commit 7640e9535d
2 changed files with 45 additions and 60 deletions

View File

@@ -91,6 +91,7 @@ std::string getFileName(const std::string & path)
/// Checks if a filename (\b not path) is 8.3 (an empty name is never 8.3, and a path is never 8.3).
/// Please note the '8' and '3' limitations are in \b bytes, not in characters (which is different when using UTF8).
bool is83(const std::string & s)
{
// 012345678901
@@ -441,49 +442,6 @@ WriterNodeVisitor::Material::Material(WriterNodeVisitor & writerNodeVisitor, osg
}
// If 'to' is in a subdirectory of 'from' then this function returns the
// subpath. Otherwise it just returns the file name.
// (Same as in FBX plugin)
std::string getPathRelative(const std::string& from/*directory*/,
const std::string& to/*file path*/)
{
std::string::size_type slash = to.find_last_of('/');
std::string::size_type backslash = to.find_last_of('\\');
if (slash == std::string::npos)
{
if (backslash == std::string::npos) return to;
slash = backslash;
}
else if (backslash != std::string::npos && backslash > slash)
{
slash = backslash;
}
if (from.empty() || from.length() > to.length())
return osgDB::getSimpleFileName(to);
std::string::const_iterator itTo = to.begin();
for (std::string::const_iterator itFrom = from.begin();
itFrom != from.end(); ++itFrom, ++itTo)
{
char a = tolower(*itFrom), b = tolower(*itTo);
if (a == '\\') a = '/';
if (b == '\\') b = '/';
if (a != b || itTo == to.begin() + slash + 1)
{
return osgDB::getSimpleFileName(to);
}
}
while (itTo != to.end() && (*itTo == '\\' || *itTo == '/'))
{
++itTo;
}
return std::string(itTo, to.end());
}
/// Converts an extension to a 3-letters long one equivalent.
std::string convertExt(const std::string & path, bool extendedFilePaths)
{
@@ -562,7 +520,7 @@ void WriterNodeVisitor::writeMaterials()
}
else
{
path = getPathRelative(_srcDirectory, mat.image->getFileName());
path = osgDB::getPathRelative(_srcDirectory, mat.image->getFileName());
}
path = convertExt(path, _extendedFilePaths);
@@ -597,6 +555,31 @@ void WriterNodeVisitor::writeMaterials()
}
}
/// Truncates an UTF8 string so that it does not takes more than a given \b bytes amount (\b excluding the potential NULL end character).
/// The function assumes the UTF8 string is valid.
///\return A valid UTF8 string which size is less or equal to \c byteLimit.
// May be moved in osgDB/ConvertUTF?
std::string utf8TruncateBytes(const std::string & s, std::string::size_type byteLimit) {
// Untruncated strings
if (s.size() <= byteLimit) return s;
// Truncated strings
std::string::const_iterator it=s.begin(), itEnd=s.begin()+byteLimit;
std::string::const_iterator itStop=it;
// Note: itEnd is < s.end(), so that we can always write "it+1"
for(; it!=itEnd; ++it) {
unsigned char c = static_cast<unsigned char>(*it);
if ((c & 0x80) == 0) itStop=it+1; // 7 bits ANSI. itStop must then point after that character.
else if ((c & 0x40) != 0) itStop=it; // UTF8 sequence start: this is also past-the-end for the previous character (ANSI or UTF8)
}
return std::string(s.begin(), itStop);
}
#ifdef OSG_USE_UTF8_FILENAME
# define truncateFilenameBytes(str, size) utf8TruncateBytes(str, size)
#else
# define truncateFilenameBytes(str, size) std::string(str, 0, size)
#endif
std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, const std::string & _defaultPrefix, bool nameIsPath)
{
@@ -615,7 +598,8 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c
// Handling of paths is not well done yet. Defaulting to something very simple.
// We should actually ensure each component is 8 chars long, and final filename is 8.3, and total is <64 chars, or simply ensure total length for extended 3DS paths.
std::string defaultValue(nameIsPath ? osgDB::getSimpleFileName(_defaultValue) : _defaultValue);
std::string ext(nameIsPath ? osgDB::getFileExtensionIncludingDot(_defaultValue).substr(0, std::min<unsigned int>(_defaultValue.size(), 4)) : ""); // 4 chars = dot + 3 chars
std::string ext(nameIsPath ? osgDB::getFileExtensionIncludingDot(_defaultValue) : "");
ext = truncateFilenameBytes(ext, std::min<unsigned int>(_defaultValue.size(), 4)); // 4 chars = dot + 3 chars
if (ext == ".") ext = "";
std::string defaultPrefix(_defaultPrefix.empty() ? "_" : _defaultPrefix);
@@ -626,12 +610,12 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c
{
if (defaultValue[i] == '.')
{
truncDefaultValue = defaultValue.substr(0, i);
truncDefaultValue = truncateFilenameBytes(defaultValue, i);
break;
}
}
if (truncDefaultValue.empty())
truncDefaultValue = defaultValue.substr(0, std::min<unsigned int>(defaultValue.size(), MAX_PREFIX_LEGNTH));
truncDefaultValue = truncateFilenameBytes(defaultValue, std::min<unsigned int>(defaultValue.size(), MAX_PREFIX_LEGNTH));
assert(truncDefaultValue.size() <= MAX_PREFIX_LEGNTH);
std::map<std::string, unsigned int>::iterator pairPrefix;
@@ -680,7 +664,7 @@ std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, c
// Failed finding a name
// Try with a shorter prefix if possible
if (defaultPrefix.length()>1) return getUniqueName(_defaultValue, defaultPrefix.substr(0, defaultPrefix.length()-1), nameIsPath);
if (defaultPrefix.length()>1) return getUniqueName(_defaultValue, truncateFilenameBytes(defaultPrefix, defaultPrefix.length()-1), nameIsPath);
// Try with default prefix if not arleady done
if (defaultPrefix != std::string("_")) return getUniqueName(_defaultValue, "_", nameIsPath);