diff options
Diffstat (limited to 'common/str.cpp')
-rw-r--r-- | common/str.cpp | 74 |
1 files changed, 46 insertions, 28 deletions
diff --git a/common/str.cpp b/common/str.cpp index 740e7b6a06..a2cd4a0193 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -19,13 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "common/str.h" #include "common/hash-str.h" -#include "common/util.h" - +#include "common/list.h" #include "common/memorypool.h" - -#include <stdarg.h> +#include "common/str.h" +#include "common/util.h" namespace Common { @@ -256,7 +254,7 @@ String &String::operator=(char c) { String &String::operator+=(const char *str) { if (_str <= str && str <= _str + _size) - return operator+=(Common::String(str)); + return operator+=(String(str)); int len = strlen(str); if (len > 0) { @@ -270,7 +268,7 @@ String &String::operator+=(const char *str) { String &String::operator+=(const String &str) { if (&str == this) - return operator+=(Common::String(str)); + return operator+=(String(str)); int len = str._size; if (len > 0) { @@ -429,10 +427,22 @@ uint String::hash() const { // static String String::format(const char *fmt, ...) { String output; - assert(output.isStorageIntern()); va_list va; va_start(va, fmt); + output = String::vformat(fmt, va); + va_end(va); + + return output; +} + +// static +String String::vformat(const char *fmt, va_list args) { + String output; + assert(output.isStorageIntern()); + + va_list va; + scumm_va_copy(va, args); int len = vsnprintf(output._str, _builtinCapacity, fmt, va); va_end(va); @@ -457,7 +467,7 @@ String String::format(const char *fmt, ...) { assert(!output.isStorageIntern()); size = output._extern._capacity; - va_start(va, fmt); + scumm_va_copy(va, args); len = vsnprintf(output._str, size, fmt, va); va_end(va); } while (len == -1 || len >= size - 1); @@ -468,7 +478,7 @@ String String::format(const char *fmt, ...) { } else { // vsnprintf didn't have enough space, so grow buffer output.ensureCapacity(len, false); - va_start(va, fmt); + scumm_va_copy(va, args); int len2 = vsnprintf(output._str, len+1, fmt, va); va_end(va); assert(len == len2); @@ -612,7 +622,7 @@ char *trim(char *t) { return rtrim(ltrim(t)); } -Common::String lastPathComponent(const Common::String &path, const char sep) { +String lastPathComponent(const String &path, const char sep) { const char *str = path.c_str(); const char *last = str + path.size(); @@ -622,7 +632,7 @@ Common::String lastPathComponent(const Common::String &path, const char sep) { // Path consisted of only slashes -> return empty string if (last == str) - return Common::String(); + return String(); // Now scan the whole component const char *first = last - 1; @@ -632,24 +642,26 @@ Common::String lastPathComponent(const Common::String &path, const char sep) { if (*first == sep) first++; - return Common::String(first, last); + return String(first, last); } -Common::String normalizePath(const Common::String &path, const char sep) { +String normalizePath(const String &path, const char sep) { if (path.empty()) return path; const char *cur = path.c_str(); - Common::String result; + String result; // If there is a leading slash, preserve that: if (*cur == sep) { result += sep; + // Skip over multiple leading slashes, so "//" equals "/" while (*cur == sep) ++cur; } - // Scan till the end of the String + // Scan for path components till the end of the String + List<String> comps; while (*cur != 0) { const char *start = cur; @@ -657,18 +669,16 @@ Common::String normalizePath(const Common::String &path, const char sep) { while (*cur != sep && *cur != 0) cur++; - const Common::String component(start, cur); - - // Skip empty components and dot components, add all others - if (!component.empty() && component != ".") { - // Add a separator before the component, unless the result - // string already ends with one (which happens only if the - // path *starts* with a separator). - if (!result.empty() && result.lastChar() != sep) - result += sep; + const String component(start, cur); - // Add the component - result += component; + if (component.empty() || component == ".") { + // Skip empty components and dot components + } else if (!comps.empty() && component == ".." && comps.back() != "..") { + // If stack is non-empty and top is not "..", remove top + comps.pop_back(); + } else { + // Add the component to the stack + comps.push_back(component); } // Skip over separator chars @@ -676,6 +686,14 @@ Common::String normalizePath(const Common::String &path, const char sep) { cur++; } + // Finally, assemble all components back into a path + while (!comps.empty()) { + result += comps.front(); + comps.pop_front(); + if (!comps.empty()) + result += sep; + } + return result; } @@ -749,7 +767,7 @@ String tag2string(uint32 tag) { if (!isprint((unsigned char)str[i])) str[i] = '.'; } - return Common::String(str); + return String(str); } size_t strlcpy(char *dst, const char *src, size_t size) { |