From b43891b82ed916c07eef072459d801becbd073f4 Mon Sep 17 00:00:00 2001 From: "benjamin%smedbergs.us" Date: Thu, 4 May 2006 18:34:45 +0000 Subject: [PATCH] Bug 335248 - Add StringBeginsWith and several other functions to the frozen CRTGlue/stringapi, r=darin --- xpcom/glue/nsCRTGlue.cpp | 35 +++++++++++ xpcom/glue/nsCRTGlue.h | 19 ++++++ xpcom/glue/nsStringAPI.cpp | 124 +++++++++++++++++++++++++++++++++++++ xpcom/glue/nsStringAPI.h | 121 +++++++++++++++++++----------------- 4 files changed, 241 insertions(+), 58 deletions(-) diff --git a/xpcom/glue/nsCRTGlue.cpp b/xpcom/glue/nsCRTGlue.cpp index c09371ce132d..de1a02d0206f 100644 --- a/xpcom/glue/nsCRTGlue.cpp +++ b/xpcom/glue/nsCRTGlue.cpp @@ -39,6 +39,8 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCRTGlue.h" +#include "nsXPCOM.h" +#include const char* NS_strspnp(const char *delims, const char *str) @@ -97,6 +99,39 @@ NS_strlen(const PRUnichar *aString) return end - aString; } +int +NS_strcmp(const PRUnichar *a, const PRUnichar *b) +{ + while (*b) { + int r = *a - *b; + if (r) + return r; + + ++a; + ++b; + } + + return *a != '\0'; +} + +PRUnichar* +NS_strdup(const PRUnichar *aString) +{ + PRUint32 len = NS_strlen(aString); + return NS_strndup(aString, len); +} + +PRUnichar* +NS_strndup(const PRUnichar *aString, PRUint32 aLen) +{ + PRUnichar *newBuf = (PRUnichar*) NS_Alloc((aLen + 1) * sizeof(PRUnichar)); + if (newBuf) { + memcpy(newBuf, aString, aLen * sizeof(PRUnichar)); + newBuf[aLen] = '\0'; + } + return newBuf; +} + // This table maps uppercase characters to lower case characters; // characters that are neither upper nor lower case are unaffected. static const unsigned char kUpper2Lower[256] = { diff --git a/xpcom/glue/nsCRTGlue.h b/xpcom/glue/nsCRTGlue.h index 86915b4e07c8..5ae833bc75ce 100644 --- a/xpcom/glue/nsCRTGlue.h +++ b/xpcom/glue/nsCRTGlue.h @@ -77,6 +77,25 @@ NS_strtok(const char *delims, char **str); NS_COM_GLUE PRUint32 NS_strlen(const PRUnichar *aString); +/** + * "strcmp" for PRUnichar strings + */ +NS_COM_GLUE int +NS_strcmp(const PRUnichar *a, const PRUnichar *b); + +/** + * "strdup" for PRUnichar strings, uses the NS_Alloc allocator. + */ +NS_COM_GLUE PRUnichar* +NS_strdup(const PRUnichar *aString); + +/** + * strndup for PRUnichar strings... this function will ensure that the + * new string is null-terminated. Uses the NS_Alloc allocator. + */ +NS_COM_GLUE PRUnichar* +NS_strndup(const PRUnichar *aString, PRUint32 aLen); + // The following case-conversion methods only deal in the ascii repertoire // A-Z and a-z diff --git a/xpcom/glue/nsStringAPI.cpp b/xpcom/glue/nsStringAPI.cpp index 612a4e4a8423..0327562f3286 100644 --- a/xpcom/glue/nsStringAPI.cpp +++ b/xpcom/glue/nsStringAPI.cpp @@ -37,6 +37,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nscore.h" +#include "nsCRTGlue.h" #ifdef MOZILLA_INTERNAL_API #undef nsAString @@ -127,6 +128,19 @@ nsAString::DefaultComparator(const char_type *a, const char_type *b, return 0; } +PRBool +nsAString::Equals(const char_type *other, ComparatorFunc c) const +{ + const char_type *cself; + PRUint32 selflen = NS_StringGetData(*this, &cself); + PRUint32 otherlen = NS_strlen(other); + + if (selflen != otherlen) + return PR_FALSE; + + return c(cself, other, selflen) == 0; +} + PRBool nsAString::Equals(const self_type &other, ComparatorFunc c) const { @@ -141,6 +155,23 @@ nsAString::Equals(const self_type &other, ComparatorFunc c) const return c(cself, cother, selflen) == 0; } +PRInt32 +nsAString::RFindChar(char_type aChar) const +{ + const PRUnichar *start, *end; + BeginReading(&start, &end); + + do { + --end; + + if (*end == aChar) + return end - start; + + } while (end >= start); + + return -1; +} + // nsACString PRUint32 @@ -210,6 +241,19 @@ nsACString::DefaultComparator(const char_type *a, const char_type *b, return memcmp(a, b, len); } +PRBool +nsACString::Equals(const char_type *other, ComparatorFunc c) const +{ + const char_type *cself; + PRUint32 selflen = NS_CStringGetData(*this, &cself); + PRUint32 otherlen = strlen(other); + + if (selflen != otherlen) + return PR_FALSE; + + return c(cself, other, selflen) == 0; +} + PRBool nsACString::Equals(const self_type &other, ComparatorFunc c) const { @@ -224,6 +268,86 @@ nsACString::Equals(const self_type &other, ComparatorFunc c) const return c(cself, cother, selflen) == 0; } +PRInt32 +nsACString::RFindChar(char_type aChar) const +{ + const char *start, *end; + BeginReading(&start, &end); + + for (; end >= start; --end) { + if (*end == aChar) + return end - start; + } + + return -1; +} + +// Substrings + +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, + PRUint32 aStartPos) +{ + const PRUnichar* data; + PRUint32 len = NS_StringGetData(aStr, &data); + + if (aStartPos > len) + aStartPos = len; + + NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos, + NS_STRING_CONTAINER_INIT_DEPEND | + NS_STRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr, + PRUint32 aStartPos, + PRUint32 aLength) +{ + const PRUnichar* data; + PRUint32 len = NS_StringGetData(aStr, &data); + + if (aStartPos > len) + aStartPos = len; + + if (aStartPos + aLength > len) + aLength = len - aStartPos; + + NS_StringContainerInit2(*this, data + aStartPos, aLength, + NS_STRING_CONTAINER_INIT_DEPEND | + NS_STRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, + PRUint32 aStartPos) +{ + const char* data; + PRUint32 len = NS_CStringGetData(aStr, &data); + + if (aStartPos > len) + aStartPos = len; + + NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos, + NS_CSTRING_CONTAINER_INIT_DEPEND | + NS_CSTRING_CONTAINER_INIT_SUBSTRING); +} + +nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr, + PRUint32 aStartPos, + PRUint32 aLength) +{ + const char* data; + PRUint32 len = NS_CStringGetData(aStr, &data); + + if (aStartPos > len) + aStartPos = len; + + if (aStartPos + aLength > len) + aLength = len - aStartPos; + + NS_CStringContainerInit2(*this, data + aStartPos, aLength, + NS_CSTRING_CONTAINER_INIT_DEPEND | + NS_CSTRING_CONTAINER_INIT_SUBSTRING); +} + // Utils char* diff --git a/xpcom/glue/nsStringAPI.h b/xpcom/glue/nsStringAPI.h index 9c384bd6f2fe..66096f7603c3 100644 --- a/xpcom/glue/nsStringAPI.h +++ b/xpcom/glue/nsStringAPI.h @@ -154,9 +154,21 @@ public: const char_type *b, PRUint32 length); + PRBool Equals( const char_type *other, + ComparatorFunc c = DefaultComparator ) const; + PRBool Equals( const self_type &other, ComparatorFunc c = DefaultComparator ) const; + /** + * Search for the offset of the last occurrence of a character in a + * string. + * + * @return The offset of the character from the beginning of the string, + * or -1 if not found. + */ + PRInt32 RFindChar(char_type aChar) const; + protected: // Prevent people from allocating a nsAString directly. ~nsAString() {} @@ -266,9 +278,21 @@ public: const char_type *b, PRUint32 length); + PRBool Equals( const char_type *other, + ComparatorFunc c = DefaultComparator ) const; + PRBool Equals( const self_type &other, ComparatorFunc c = DefaultComparator ) const; + /** + * Search for the offset of the last occurrence of a character in a + * string. + * + * @return The offset of the character from the beginning of the string, + * or -1 if not found. + */ + PRInt32 RFindChar(char_type aChar) const; + protected: // Prevent people from allocating a nsAString directly. ~nsACString() {} @@ -733,7 +757,7 @@ getter_Copies(nsCString& aString) * substrings */ -class nsDependentSubstring : public nsStringContainer +class NS_COM_GLUE nsDependentSubstring : public nsStringContainer { public: typedef nsDependentSubstring self_type; @@ -757,35 +781,9 @@ public: } nsDependentSubstring(const abstract_string_type& aStr, - PRUint32 aStartPos) - { - const PRUnichar* data; - PRUint32 len = NS_StringGetData(aStr, &data); - - if (aStartPos > len) - aStartPos = len; - - NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos, - NS_STRING_CONTAINER_INIT_DEPEND | - NS_STRING_CONTAINER_INIT_SUBSTRING); - } - + PRUint32 aStartPos); nsDependentSubstring(const abstract_string_type& aStr, - PRUint32 aStartPos, PRUint32 aLength) - { - const PRUnichar* data; - PRUint32 len = NS_StringGetData(aStr, &data); - - if (aStartPos > len) - aStartPos = len; - - if (aStartPos + aLength > len) - aLength = len - aStartPos; - - NS_StringContainerInit2(*this, data + aStartPos, aLength, - NS_STRING_CONTAINER_INIT_DEPEND | - NS_STRING_CONTAINER_INIT_SUBSTRING); - } + PRUint32 aStartPos, PRUint32 aLength); void Rebind(const char_type *aStart, PRUint32 aLength) { @@ -799,7 +797,7 @@ private: self_type& operator=(const self_type& aString); // NOT IMPLEMENTED }; -class nsDependentCSubstring : public nsCStringContainer +class NS_COM_GLUE nsDependentCSubstring : public nsCStringContainer { public: typedef nsDependentCSubstring self_type; @@ -823,35 +821,9 @@ public: } nsDependentCSubstring(const abstract_string_type& aStr, - PRUint32 aStartPos) - { - const char* data; - PRUint32 len = NS_CStringGetData(aStr, &data); - - if (aStartPos > len) - aStartPos = len; - - NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos, - NS_CSTRING_CONTAINER_INIT_DEPEND | - NS_CSTRING_CONTAINER_INIT_SUBSTRING); - } - + PRUint32 aStartPos); nsDependentCSubstring(const abstract_string_type& aStr, - PRUint32 aStartPos, PRUint32 aLength) - { - const char* data; - PRUint32 len = NS_CStringGetData(aStr, &data); - - if (aStartPos > len) - aStartPos = len; - - if (aStartPos + aLength > len) - aLength = len - aStartPos; - - NS_CStringContainerInit2(*this, data + aStartPos, aLength, - NS_CSTRING_CONTAINER_INIT_DEPEND | - NS_CSTRING_CONTAINER_INIT_SUBSTRING); - } + PRUint32 aStartPos, PRUint32 aLength); void Rebind(const char_type *aStart, PRUint32 aLength) { @@ -946,6 +918,39 @@ StringTail( const nsACString& str, PRUint32 count ) return nsDependentCSubstring(str, str.Length() - count, count); } + +inline PRBool +StringBeginsWith(const nsAString& aSource, const nsAString& aSubstring, + nsAString::ComparatorFunc aComparator = nsAString::DefaultComparator) +{ + return StringHead(aSource, aSubstring.Length()). + Equals(aSubstring, aComparator); +} + +inline PRBool +StringEndsWith(const nsAString& aSource, const nsAString& aSubstring, + nsAString::ComparatorFunc aComparator = nsAString::DefaultComparator) +{ + return StringTail(aSource, aSubstring.Length()). + Equals(aSubstring, aComparator); +} + +inline PRBool +StringBeginsWith(const nsACString& aSource, const nsACString& aSubstring, + nsACString::ComparatorFunc aComparator = nsACString::DefaultComparator) +{ + return StringHead(aSource, aSubstring.Length()). + Equals(aSubstring, aComparator); +} + +inline PRBool +StringEndsWith(const nsACString& aSource, const nsACString& aSubstring, + nsACString::ComparatorFunc aComparator = nsACString::DefaultComparator) +{ + return StringTail(aSource, aSubstring.Length()). + Equals(aSubstring, aComparator); +} + #define EmptyCString() nsCString() #define EmptyString() nsString()