[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