aboutsummaryrefslogtreecommitdiff
path: root/common/str.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/str.cpp')
-rw-r--r--common/str.cpp74
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) {