[Scummvm-cvs-logs] SF.net SVN: scummvm:[48953] scummvm/trunk

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Wed May 5 19:52:59 CEST 2010


Revision: 48953
          http://scummvm.svn.sourceforge.net/scummvm/?rev=48953&view=rev
Author:   lordhoto
Date:     2010-05-05 17:52:59 +0000 (Wed, 05 May 2010)

Log Message:
-----------
Add a custom implementation of OpenBSD's strlcat and strlcpy.

This includes both an implementation and some basic unit tests for
the above mentioned functions.

Modified Paths:
--------------
    scummvm/trunk/common/str.cpp
    scummvm/trunk/common/str.h
    scummvm/trunk/test/common/str.h

Modified: scummvm/trunk/common/str.cpp
===================================================================
--- scummvm/trunk/common/str.cpp	2010-05-05 12:16:51 UTC (rev 48952)
+++ scummvm/trunk/common/str.cpp	2010-05-05 17:52:59 UTC (rev 48953)
@@ -739,4 +739,84 @@
 	return Common::String(str);
 }
 
+size_t strlcpy(char *dst, const char *src, size_t size) {
+	// Our backup of the source's start, we need this
+	// to calculate the source's length.
+	const char * const srcStart = src;
+
+	// In case a non-empty size was specified we
+	// copy over (size - 1) bytes at max.
+	if (size != 0) {
+		// Copy over (size - 1) bytes at max.
+		while (--size != 0) {
+			if ((*dst++ = *src) == 0)
+				break;
+			++src;
+		}
+
+		// In case the source string was longer than the
+		// destination, we need to add a terminating
+		// zero.
+		if (size == 0)
+			*dst = 0;
+	}
+
+	// Move to the terminating zero of the source
+	// string, we need this to determin the length
+	// of the source string.
+	while (*src)
+		++src;
+
+	// Return the source string's length.
+	return src - srcStart;
+}
+
+size_t strlcat(char *dst, const char *src, size_t size) {
+	// In case the destination buffer does not contain
+	// space for at least 1 character, we will just
+	// return the source string's length.
+	if (size == 0)
+		return strlen(src);
+
+	// Our backup of the source's start, we need this
+	// to calculate the source's length.
+	const char * const srcStart = src;
+
+	// Our backup of the destination's start, we need
+	// this to calculate the destination's length.
+	const char * const dstStart = dst;
+
+	// Search the end of the destination, but do not
+	// move past the terminating zero.
+	while (size-- != 0 && *dst != 0)
+		++dst;
+
+	// Calculate the destination's length;
+	const size_t dstLength = dst - dstStart;
+
+	// In case we reached the end of the destination
+	// buffer before we had a chance to append any
+	// characters we will just return the destination
+	// length plus the source string's length.
+	if (size == 0)
+		return dstLength + strlen(srcStart);
+
+	// Copy over all of the source that fits
+	// the destination buffer. We also need
+	// to take the terminating zero we will
+	// add into consideration.
+	while (size-- != 0 && *src != 0)
+		*dst++ = *src++;
+	*dst = 0;
+
+	// Move to the terminating zero of the source
+	// string, we need this to determin the length
+	// of the source string.
+	while (*src)
+		++src;
+
+	// Return the total length of the result string
+	return dstLength + (src - srcStart);
+}
+
 }	// End of namespace Common

Modified: scummvm/trunk/common/str.h
===================================================================
--- scummvm/trunk/common/str.h	2010-05-05 12:16:51 UTC (rev 48952)
+++ scummvm/trunk/common/str.h	2010-05-05 17:52:59 UTC (rev 48953)
@@ -326,6 +326,43 @@
 String tag2string(uint32 tag);
 
 /**
+ * Copy up to size - 1 characters from src to dst and also zero terminate the
+ * result. Note that src must be a zero terminated string.
+ *
+ * In case size is zero this function just returns the length of the source
+ * string.
+ *
+ * @note This is modeled after OpenBSD's strlcpy. See the manpage here:
+ *       http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy
+ *
+ * @param dst The destination buffer.
+ * @param src The source string.
+ * @param size The size of the destination buffer.
+ * @return The length of the (non-truncated) result, i.e. strlen(src).
+ */
+size_t strlcpy(char *dst, const char *src, size_t size);
+
+/**
+ * Append the string src to the string dst. Note that both src and dst must be
+ * zero terminated. The result will be zero terminated. At most
+ * "size - strlen(dst) - 1" bytes will be appended.
+ *
+ * In case the dst string does not contain a zero within the first "size" bytes
+ * the dst string will not be changed and size + strlen(src) is returned.
+ *
+ * @note This is modeled after OpenBSD's strlcat. See the manpage here:
+ *       http://www.openbsd.org/cgi-bin/man.cgi?query=strlcat
+ *
+ * @param dst The string the source string should be appended to.
+ * @param src The source string.
+ * @param size The (total) size of the destination buffer.
+ * @return The length of the (non-truncated) result. That is
+ *         strlen(dst) + strlen(src). In case strlen(dst) > size
+ *         size + strlen(src) is returned.
+ */
+size_t strlcat(char *dst, const char *src, size_t size);
+
+/**
  * Convenience wrapper for tag2string which "returns" a C string.
  * Note: It is *NOT* safe to do anything with the return value other than directly
  * copying or printing it.

Modified: scummvm/trunk/test/common/str.h
===================================================================
--- scummvm/trunk/test/common/str.h	2010-05-05 12:16:51 UTC (rev 48952)
+++ scummvm/trunk/test/common/str.h	2010-05-05 17:52:59 UTC (rev 48953)
@@ -295,6 +295,58 @@
 		Common::String s = Common::String::printf("%s%X", "test", 1234);
 		TS_ASSERT(s == "test4D2");
 		TS_ASSERT(s.size() == 7);
+	}
 
+	void test_strlcpy() {
+		static const char * const testString = "1234567890";
+
+		char test1[4];
+		TS_ASSERT_EQUALS(Common::strlcpy(test1, testString, 4), strlen(testString));
+		TS_ASSERT_EQUALS(strcmp(test1, "123"), 0);
+
+		char test2[12];
+		test2[11] = 'X';
+		TS_ASSERT_EQUALS(Common::strlcpy(test2, testString, 11), strlen(testString));
+		TS_ASSERT_EQUALS(strcmp(test2, testString), 0);
+		TS_ASSERT_EQUALS(test2[11], 'X');
+
+		char test3[1] = { 'X' };
+		TS_ASSERT_EQUALS(Common::strlcpy(test3, testString, 0), strlen(testString));
+		TS_ASSERT_EQUALS(test3[0], 'X');
+
+		char test4[12];
+		TS_ASSERT_EQUALS(Common::strlcpy(test4, testString, 12), strlen(testString));
+		TS_ASSERT_EQUALS(strcmp(test4, testString), 0);
 	}
+
+	void test_strncat() {
+		static const char * const initialString = "123";
+		static const char * const appendString = "4567890";
+		static const char * const resultString = "1234567890";
+
+		char test1[4];
+		TS_ASSERT_EQUALS(Common::strlcpy(test1, initialString, 4), strlen(initialString));
+		TS_ASSERT_EQUALS(strcmp(test1, initialString), 0);
+		TS_ASSERT_EQUALS(Common::strlcat(test1, appendString, 4), strlen(resultString));
+		TS_ASSERT_EQUALS(strcmp(test1, initialString), 0);
+
+		char test2[12];
+		test2[11] = 'X';
+		TS_ASSERT_EQUALS(Common::strlcpy(test2, initialString, 11), strlen(initialString));
+		TS_ASSERT_EQUALS(strcmp(test2, initialString), 0);
+		TS_ASSERT_EQUALS(Common::strlcat(test2, appendString, 11), strlen(resultString));
+		TS_ASSERT_EQUALS(strcmp(test2, resultString), 0);
+		TS_ASSERT_EQUALS(test2[11], 'X');
+
+		char test3[1];
+		test3[0] = 'X';
+		TS_ASSERT_EQUALS(Common::strlcat(test3, appendString, 0), strlen(appendString));
+		TS_ASSERT_EQUALS(test3[0], 'X');
+
+		char test4[11];
+		TS_ASSERT_EQUALS(Common::strlcpy(test4, initialString, 11), strlen(initialString));
+		TS_ASSERT_EQUALS(strcmp(test4, initialString), 0);
+		TS_ASSERT_EQUALS(Common::strlcat(test4, appendString, 11), strlen(resultString));
+		TS_ASSERT_EQUALS(strcmp(test4, resultString), 0);
+	}
 };


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