[Scummvm-cvs-logs] SF.net SVN: scummvm:[33256] residual/trunk/common
aquadran at users.sourceforge.net
aquadran at users.sourceforge.net
Wed Jul 23 23:48:28 CEST 2008
Revision: 33256
http://scummvm.svn.sourceforge.net/scummvm/?rev=33256&view=rev
Author: aquadran
Date: 2008-07-23 21:48:28 +0000 (Wed, 23 Jul 2008)
Log Message:
-----------
sync with scummvm
Modified Paths:
--------------
residual/trunk/common/file.cpp
residual/trunk/common/hashmap.h
residual/trunk/common/str.cpp
residual/trunk/common/str.h
residual/trunk/common/stream.cpp
residual/trunk/common/stream.h
Modified: residual/trunk/common/file.cpp
===================================================================
--- residual/trunk/common/file.cpp 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/file.cpp 2008-07-23 21:48:28 UTC (rev 33256)
@@ -29,7 +29,6 @@
#include "common/util.h"
#include "common/debug.h"
#include "common/hash-str.h"
-
#include <errno.h>
#if defined(MACOSX) || defined(IPHONE)
@@ -454,10 +453,12 @@
}
bool File::ioFailed() const {
+ // TODO/FIXME: Just use ferror() here?
return _ioFailed != 0;
}
void File::clearIOFailed() {
+ // TODO/FIXME: Just use clearerr() here?
_ioFailed = false;
}
Modified: residual/trunk/common/hashmap.h
===================================================================
--- residual/trunk/common/hashmap.h 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/hashmap.h 2008-07-23 21:48:28 UTC (rev 33256)
@@ -58,7 +58,13 @@
#include "common/str.h"
#include "common/util.h"
+// FIXME: Since this define is very system dependant,
+// it should be moved to the appropriate H file instead.
+// Portdefs might be a good location for example
+#if !defined(__SYMBIAN32__)
#define USE_HASHMAP_MEMORY_POOL
+#endif
+
#ifdef USE_HASHMAP_MEMORY_POOL
#include "common/memorypool.h"
// FIXME: we sadly can't assume standard C++ to be present
Modified: residual/trunk/common/str.cpp
===================================================================
--- residual/trunk/common/str.cpp 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/str.cpp 2008-07-23 21:48:28 UTC (rev 33256)
@@ -43,32 +43,43 @@
return ((len + 32 - 1) & ~0x1F) - 1;
}
-String::String(const char *str, uint32 len)
-: _len(0), _str(_storage) {
+String::String(const char *str) : _len(0), _str(_storage) {
+ if (str == 0) {
+ _storage[0] = 0;
+ _len = 0;
+ } else
+ initWithCStr(str, strlen(str));
+}
+String::String(const char *str, uint32 len) : _len(0), _str(_storage) {
+ initWithCStr(str, len);
+}
+
+String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) {
+ assert(endP >= beginP);
+ initWithCStr(beginP, endP - beginP);
+}
+
+void String::initWithCStr(const char *str, uint32 len) {
+ assert(str);
+
// Init _storage member explicitly (ie. without calling its constructor)
// for GCC 2.95.x compatibility (see also tracker item #1602879).
_storage[0] = 0;
- if (str && *str) {
- const uint32 tmp = strlen(str);
- assert(len <= tmp);
- if (len <= 0)
- len = tmp;
- _len = len;
+ _len = len;
- if (len >= _builtinCapacity) {
- // Not enough internal storage, so allocate more
- _extern._capacity = computeCapacity(len);
- _extern._refCount = 0;
- _str = (char *)malloc(_extern._capacity+1);
- assert(_str != 0);
- }
+ if (len >= _builtinCapacity) {
+ // Not enough internal storage, so allocate more
+ _extern._capacity = computeCapacity(len);
+ _extern._refCount = 0;
+ _str = (char *)malloc(_extern._capacity+1);
+ assert(_str != 0);
+ }
- // Copy the string into the storage area
- memcpy(_str, str, len);
- _str[len] = 0;
- }
+ // Copy the string into the storage area
+ memmove(_str, str, len);
+ _str[len] = 0;
}
String::String(const String &str)
@@ -91,6 +102,8 @@
_storage[0] = c;
_storage[1] = 0;
+ // TODO/FIXME: There is no reason for the following check -- we *do*
+ // allow strings to contain 0 bytes!
_len = (c == 0) ? 0 : 1;
}
@@ -98,6 +111,74 @@
decRefCount(_extern._refCount);
}
+void String::makeUnique() {
+ ensureCapacity(_len, true);
+}
+
+/**
+ * Ensure that enough storage is available to store at least new_len
+ * characters plus a null byte. In addition, if we currently share
+ * the storage with another string, unshare it, so that we can safely
+ * write to the storage.
+ */
+void String::ensureCapacity(uint32 new_len, bool keep_old) {
+ bool isShared;
+ uint32 curCapacity, newCapacity;
+ char *newStorage;
+ int *oldRefCount = _extern._refCount;
+
+ if (isStorageIntern()) {
+ isShared = false;
+ curCapacity = _builtinCapacity - 1;
+ } else {
+ isShared = (oldRefCount && *oldRefCount > 1);
+ curCapacity = _extern._capacity;
+ }
+
+ // Special case: If there is enough space, and we do not share
+ // the storage, then there is nothing to do.
+ if (!isShared && new_len <= curCapacity)
+ return;
+
+ if (isShared && new_len <= _builtinCapacity - 1) {
+ // We share the storage, but there is enough internal storage: Use that.
+ newStorage = _storage;
+ newCapacity = _builtinCapacity - 1;
+ } else {
+ // We need to allocate storage on the heap!
+
+ // Compute a suitable new capacity limit
+ newCapacity = computeCapacity(new_len);
+
+ // Allocate new storage
+ newStorage = (char *)malloc(newCapacity+1);
+ assert(newStorage);
+ }
+
+ // Copy old data if needed, elsewise reset the new storage.
+ if (keep_old) {
+ assert(_len <= newCapacity);
+ memcpy(newStorage, _str, _len + 1);
+ } else {
+ _len = 0;
+ newStorage[0] = 0;
+ }
+
+ // Release hold on the old storage ...
+ decRefCount(oldRefCount);
+
+ // ... in favor of the new storage
+ _str = newStorage;
+
+ if (!isStorageIntern()) {
+ // Set the ref count & capacity if we use an external storage.
+ // It is important to do this *after* copying any old content,
+ // else we would override data that has not yet been copied!
+ _extern._refCount = 0;
+ _extern._capacity = newCapacity;
+ }
+}
+
void String::incRefCount() const {
assert(!isStorageIntern());
if (_extern._refCount == 0) {
@@ -130,11 +211,14 @@
uint32 len = strlen(str);
ensureCapacity(len, false);
_len = len;
- memcpy(_str, str, len + 1);
+ memmove(_str, str, len + 1);
return *this;
}
String &String::operator =(const String &str) {
+ if (&str == this)
+ return *this;
+
if (str.isStorageIntern()) {
decRefCount(_extern._refCount);
_len = str._len;
@@ -154,7 +238,8 @@
}
String& String::operator =(char c) {
- ensureCapacity(1, false);
+ decRefCount(_extern._refCount);
+ _str = _storage;
_len = 1;
_str[0] = c;
_str[1] = 0;
@@ -237,10 +322,7 @@
void String::deleteChar(uint32 p) {
assert(p < _len);
- // Call ensureCapacity to make sure we actually *own* the storage
- // to which _str points to -- we wouldn't want to modify a storage
- // which other string objects are sharing, after all.
- ensureCapacity(_len, true);
+ makeUnique();
while (p++ < _len)
_str[p-1] = _str[p];
_len--;
@@ -257,7 +339,7 @@
void String::setChar(char c, uint32 p) {
assert(p <= _len);
- ensureCapacity(_len, true);
+ makeUnique();
_str[p] = c;
}
@@ -272,79 +354,37 @@
}
void String::toLowercase() {
- ensureCapacity(_len, true);
+ makeUnique();
for (uint32 i = 0; i < _len; ++i)
_str[i] = tolower(_str[i]);
}
void String::toUppercase() {
- ensureCapacity(_len, true);
+ makeUnique();
for (uint32 i = 0; i < _len; ++i)
_str[i] = toupper(_str[i]);
}
-/**
- * Ensure that enough storage is available to store at least new_len
- * characters plus a null byte. In addition, if we currently share
- * the storage with another string, unshare it, so that we can safely
- * write to the storage.
- */
-void String::ensureCapacity(uint32 new_len, bool keep_old) {
- bool isShared;
- uint32 curCapacity, newCapacity;
- char *newStorage;
- int *oldRefCount = _extern._refCount;
-
- if (isStorageIntern()) {
- isShared = false;
- curCapacity = _builtinCapacity - 1;
- } else {
- isShared = (oldRefCount && *oldRefCount > 1);
- curCapacity = _extern._capacity;
- }
-
- // Special case: If there is enough space, and we do not share
- // the storage, then there is nothing to do.
- if (!isShared && new_len <= curCapacity)
+void String::trim() {
+ if (_len == 0)
return;
- if (isShared && new_len <= _builtinCapacity - 1) {
- // We share the storage, but there is enough internal storage: Use that.
- newStorage = _storage;
- newCapacity = _builtinCapacity - 1;
- } else {
- // We need to allocate storage on the heap!
+ makeUnique();
- // Compute a suitable new capacity limit
- newCapacity = computeCapacity(new_len);
+ // Trim trailing whitespace
+ while (_len >= 1 && isspace(_str[_len-1]))
+ _len--;
+ _str[_len] = 0;
- // Allocate new storage
- newStorage = (char *)malloc(newCapacity+1);
- assert(newStorage);
- }
+ // Trim leading whitespace
+ char *t = _str;
+ while (isspace(*t))
+ t++;
- // Copy old data if needed, elsewise reset the new storage.
- if (keep_old) {
- assert(_len <= newCapacity);
- memcpy(newStorage, _str, _len + 1);
- } else {
- _len = 0;
- newStorage[0] = 0;
+ if (t != _str) {
+ _len -= t - _str;
+ memmove(_str, t, _len + 1);
}
-
- // Release hold on the old storage ...
- decRefCount(oldRefCount);
-
- // ... in favor of the new storage
- _str = newStorage;
-
- if (!isStorageIntern()) {
- // Set the ref count & capacity if we use an external storage.
- // It is important to do this *after* copying any old content,
- // else we would override data that has not yet been copied!
- _extern._refCount = 0;
- _extern._capacity = newCapacity;
- }
}
uint String::hash() const {
Modified: residual/trunk/common/str.h
===================================================================
--- residual/trunk/common/str.h 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/str.h 2008-07-23 21:48:28 UTC (rev 33256)
@@ -96,10 +96,24 @@
static const char *emptyString;
#endif
+ /** Construct a new empty string. */
String() : _len(0), _str(_storage) { _storage[0] = 0; }
- String(const char *str, uint32 len = 0);
+
+ /** Construct a new string from the given NULL-terminated C string. */
+ String(const char *str);
+
+ /** Construct a new string containing exactly len characters read from address str. */
+ String(const char *str, uint32 len);
+
+ /** Construct a new string containing the characters between beginP (including) and endP (excluding). */
+ String(const char *beginP, const char *endP);
+
+ /** Construct a copy of the given string. */
String(const String &str);
+
+ /** Construct a string consisting of the given character. */
String(char c);
+
~String();
String &operator =(const char *str);
@@ -162,6 +176,8 @@
void toLowercase();
void toUppercase();
+
+ void trim();
uint hash() const;
@@ -186,9 +202,11 @@
}
protected:
+ void makeUnique();
void ensureCapacity(uint32 new_len, bool keep_old);
void incRefCount() const;
void decRefCount(int *oldRefCount);
+ void initWithCStr(const char *str, uint32 len);
};
// Append two strings to form a new (temp) string
Modified: residual/trunk/common/stream.cpp
===================================================================
--- residual/trunk/common/stream.cpp 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/stream.cpp 2008-07-23 21:48:28 UTC (rev 33256)
@@ -148,6 +148,61 @@
return buf;
}
+char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
+ assert(buf != 0 && bufSize > 1);
+ char *p = buf;
+ size_t len = 0;
+ char c = 0;
+
+ // If end-of-file occurs before any characters are read, return NULL
+ // and the buffer contents remain unchanged.
+ if (eos() || ioFailed()) {
+ return 0;
+ }
+
+ // Loop as long as the stream has not ended, there is still free
+ // space in the buffer, and the line has not ended
+ while (!eos() && len + 1 < bufSize && c != LF) {
+ c = readByte();
+
+ // If end-of-file occurs before any characters are read, return
+ // NULL and the buffer contents remain unchanged. If an error
+ /// occurs, return NULL and the buffer contents are indeterminate.
+ if (ioFailed() || (len == 0 && eos()))
+ return 0;
+
+ // Check for CR or CR/LF
+ // * DOS and Windows use CRLF line breaks
+ // * Unix and OS X use LF line breaks
+ // * Macintosh before OS X used CR line breaks
+ if (c == CR) {
+ // Look at the next char -- is it LF? If not, seek back
+ c = readByte();
+ if (c != LF && !eos())
+ seek(-1, SEEK_CUR);
+ // Treat CR & CR/LF as plain LF
+ c = LF;
+ }
+
+ *p++ = c;
+ len++;
+ }
+
+ // FIXME:
+ // This should fix a bug while using readLine with Common::File
+ // it seems that it sets the eos flag after an invalid read
+ // and at the same time the ioFailed flag
+ // the config file parser fails out of that reason for the new themes
+ if (eos()) {
+ clearIOFailed();
+ }
+
+ // We always terminate the buffer if no error occured
+ *p = 0;
+ return buf;
+}
+
+
uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
dataSize = MIN(dataSize, _end - _pos);
Modified: residual/trunk/common/stream.h
===================================================================
--- residual/trunk/common/stream.h 2008-07-23 20:47:42 UTC (rev 33255)
+++ residual/trunk/common/stream.h 2008-07-23 21:48:28 UTC (rev 33256)
@@ -304,13 +304,40 @@
* Read one line of text from a CR or CR/LF terminated plain text file.
* This method is a rough analog of the (f)gets function.
*
+ * @bug A main difference (and flaw) in this function is that there is no
+ * way to detect that a line exceeeds the length of the buffer.
+ * Code which needs this should use the new readLine_NEW() method instead.
+ *
* @param buf the buffer to store into
* @param bufSize the size of the buffer
* @return a pointer to the read string, or NULL if an error occurred
+ *
* @note The line terminator (CR or CR/LF) is stripped and not inserted
* into the buffer.
*/
virtual char *readLine(char *buf, size_t bufSize);
+
+ /**
+ * Reads at most one less than the number of characters specified
+ * by bufSize from the and stores them in the string buf. Reading
+ * stops when the end of a line is reached (CR, CR/LF or LF), at
+ * end-of-file or error. The newline, if any, is retained (CR and
+ * CR/LF are translated to LF = 0xA = '\n'). If any characters are
+ * read and there is no error, a `\0' character is appended to end
+ * the string.
+ *
+ * Upon successful completion, return a pointer to the string. If
+ * end-of-file occurs before any characters are read, returns NULL
+ * and the buffer contents remain unchanged. If an error occurs,
+ * returns NULL and the buffer contents are indeterminate.
+ * This method does not distinguish between end-of-file and error;
+ * callers muse use ioFailed() or eos() to determine which occurred.
+ *
+ * @param buf the buffer to store into
+ * @param bufSize the size of the buffer
+ * @return a pointer to the read string, or NULL if an error occurred
+ */
+ virtual char *readLine_NEW(char *s, size_t bufSize);
};
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list