From eff6e0fd5e996921347a7378496e3c6a844dc6c3 Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Sat, 20 Nov 1999 04:22:26 +0000 Subject: [PATCH] Added nsStr (nsString, nsString2) code for counting strings that have been seen. r=rickg git-svn-id: svn://10.0.0.236/trunk@54036 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/string/obsolete/nsStr.cpp | 162 +++++++++++++++++++++++- mozilla/string/obsolete/nsStr.h | 38 +++++- mozilla/xpcom/ds/nsHashtable.cpp | 24 +--- mozilla/xpcom/ds/nsStr.cpp | 162 +++++++++++++++++++++++- mozilla/xpcom/ds/nsStr.h | 38 +++++- mozilla/xpcom/string/obsolete/nsStr.cpp | 162 +++++++++++++++++++++++- mozilla/xpcom/string/obsolete/nsStr.h | 38 +++++- 7 files changed, 595 insertions(+), 29 deletions(-) diff --git a/mozilla/string/obsolete/nsStr.cpp b/mozilla/string/obsolete/nsStr.cpp index c0f78afc224..8d106d0f921 100644 --- a/mozilla/string/obsolete/nsStr.cpp +++ b/mozilla/string/obsolete/nsStr.cpp @@ -173,6 +173,9 @@ void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a aDest.mLength+=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } } } @@ -241,7 +244,9 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin //finally, make sure to update the string length... aDest.mLength+=theLength; AddNullTerminator(aDest); - +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif }//if //else nothing to do! } @@ -272,6 +277,9 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){ (*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength); aDest.mLength-=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } else Truncate(aDest,aDestOffset); }//if @@ -287,6 +295,9 @@ void nsStr::Truncate(nsStr& aDest,PRUint32 aDestOffset){ if(aDestOffset> 28) ^ (h << 4) ^ *c; + } + else { /* Sample a la java.lang.String.hash(). */ + for(m = n / 8; n >= m; c += m, n -= m) + h = (h >> 28) ^ (h << 4) ^ *c; + } + return h; + } + return (PRUint32)PL_HashString((const void*) aDest.mStr); +} +#ifdef DEBUG + +#include + +void +nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate) +{ + PRInt32 printLen = (PRInt32)aDest.mLength; + + if (aDest.mCharSize == eOneByte) { + const char* chars = aDest.mStr; + while (printLen-- && (!truncate || *chars != '\n')) { + fputc(*chars++, out); + } + } + else { + const PRUnichar* chars = aDest.mUStr; + while (printLen-- && (!truncate || *chars != '\n')) { + if (isascii(*chars)) + fputc((char)(*chars++), out); + else + fputc('-', out); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// String Usage Statistics Routines + +static PLHashTable* gStringInfo = nsnull; +PRLock* gStringInfoLock = nsnull; +PRBool gNoStringInfo = PR_FALSE; + +nsStringInfo::nsStringInfo(nsStr& str) + : mCount(0) +{ + nsStr::Initialize(mStr, str.mCharSize); + nsStr::Assign(mStr, str, 0, -1); +// nsStr::Print(mStr, stdout); +// fputc('\n', stdout); +} + +PR_EXTERN(PRHashNumber) +nsStr_Hash(const void* key) +{ + nsStr* str = (nsStr*)key; + return nsStr::HashCode(*str); +} + +PR_EXTERN(PRIntn) +nsStr_Compare(const void *v1, const void *v2) +{ + nsStr* str1 = (nsStr*)v1; + nsStr* str2 = (nsStr*)v2; + return nsStr::Compare(*str1, *str2, -1, PR_FALSE) == 0; +} + +nsStringInfo* +nsStringInfo::GetInfo(nsStr& str) +{ + if (gStringInfo == nsnull) { + gStringInfo = PL_NewHashTable(1024, + nsStr_Hash, + nsStr_Compare, + PL_CompareValues, + NULL, NULL); + gStringInfoLock = PR_NewLock(); + } + PR_Lock(gStringInfoLock); + nsStringInfo* info = + (nsStringInfo*)PL_HashTableLookup(gStringInfo, &str); + if (info == NULL) { + gNoStringInfo = PR_TRUE; + info = new nsStringInfo(str); + if (info) { + PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info); + if (e == NULL) { + delete info; + info = NULL; + } + } + gNoStringInfo = PR_FALSE; + } + PR_Unlock(gStringInfoLock); + return info; +} + +void +nsStringInfo::Seen(nsStr& str) +{ + if (!gNoStringInfo) { + nsStringInfo* info = GetInfo(str); + info->mCount++; + } +} + +void +nsStringInfo::Report(FILE* out) +{ + if (gStringInfo) { + fprintf(out, "\n== String Stats\n"); + PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out); + } +} + +PRIntn +nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg) +{ + nsStringInfo* entry = (nsStringInfo*)he->value; + FILE* out = (FILE*)arg; + + fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength); + nsStr::Print(entry->mStr, out, PR_TRUE); + fputc('\n', out); + return HT_ENUMERATE_NEXT; +} + +#endif // DEBUG + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/string/obsolete/nsStr.h b/mozilla/string/obsolete/nsStr.h index b44eeb01358..6fede507c2f 100644 --- a/mozilla/string/obsolete/nsStr.h +++ b/mozilla/string/obsolete/nsStr.h @@ -186,6 +186,7 @@ #include "nscore.h" #include "nsIAllocator.h" #include +#include //---------------------------------------------------------------------------------------- @@ -410,6 +411,19 @@ struct NS_COM nsStr { static PRBool DidAcquireMemory(void); + /** + * Returns a hash code for the string for use in a PLHashTable. + */ + static PRUint32 HashCode(const nsStr& aDest); + +#ifdef DEBUG + /** + * Prints an nsStr. If truncate is true, the string is only printed up to + * the first newline. (Note: The current implementation doesn't handle + * non-ascii unicode characters.) + */ + static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE); +#endif PRUint32 mLength; PRUint32 mCapacity; @@ -468,6 +482,28 @@ inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ return 0; } +#ifdef DEBUG -#endif +#include "plhash.h" +class nsStringInfo { +public: + nsStringInfo(nsStr& str); + ~nsStringInfo() {} + + static nsStringInfo* GetInfo(nsStr& str); + + static void Seen(nsStr& str); + + static void Report(FILE* out = stdout); + + static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg); + +protected: + nsStr mStr; + PRUint32 mCount; +}; + +#endif // DEBUG + +#endif // _nsStr diff --git a/mozilla/xpcom/ds/nsHashtable.cpp b/mozilla/xpcom/ds/nsHashtable.cpp index 1f78ee299b7..78d81f4a013 100644 --- a/mozilla/xpcom/ds/nsHashtable.cpp +++ b/mozilla/xpcom/ds/nsHashtable.cpp @@ -269,29 +269,7 @@ nsStringKey::~nsStringKey(void) PRUint32 nsStringKey::HashValue(void) const { - if(mStr.IsUnicode()) - { - PRUint32 h; - PRUint32 n; - PRUint32 m; - const PRUnichar* c; - - h = 0; - n = mStr.Length(); - c = mStr.GetUnicode(); - if(n < 16) - { /* Hash every char in a short string. */ - for(; n; c++, n--) - h = (h >> 28) ^ (h << 4) ^ *c; - } - else - { /* Sample a la jave.lang.String.hash(). */ - for(m = n / 8; n >= m; c += m, n -= m) - h = (h >> 28) ^ (h << 4) ^ *c; - } - return h; - } - return (PRUint32)PL_HashString((const void*) mStr.GetBuffer()); + return nsStr::HashCode(mStr); } PRBool nsStringKey::Equals(const nsHashKey* aKey) const diff --git a/mozilla/xpcom/ds/nsStr.cpp b/mozilla/xpcom/ds/nsStr.cpp index c0f78afc224..8d106d0f921 100644 --- a/mozilla/xpcom/ds/nsStr.cpp +++ b/mozilla/xpcom/ds/nsStr.cpp @@ -173,6 +173,9 @@ void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a aDest.mLength+=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } } } @@ -241,7 +244,9 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin //finally, make sure to update the string length... aDest.mLength+=theLength; AddNullTerminator(aDest); - +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif }//if //else nothing to do! } @@ -272,6 +277,9 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){ (*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength); aDest.mLength-=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } else Truncate(aDest,aDestOffset); }//if @@ -287,6 +295,9 @@ void nsStr::Truncate(nsStr& aDest,PRUint32 aDestOffset){ if(aDestOffset> 28) ^ (h << 4) ^ *c; + } + else { /* Sample a la java.lang.String.hash(). */ + for(m = n / 8; n >= m; c += m, n -= m) + h = (h >> 28) ^ (h << 4) ^ *c; + } + return h; + } + return (PRUint32)PL_HashString((const void*) aDest.mStr); +} +#ifdef DEBUG + +#include + +void +nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate) +{ + PRInt32 printLen = (PRInt32)aDest.mLength; + + if (aDest.mCharSize == eOneByte) { + const char* chars = aDest.mStr; + while (printLen-- && (!truncate || *chars != '\n')) { + fputc(*chars++, out); + } + } + else { + const PRUnichar* chars = aDest.mUStr; + while (printLen-- && (!truncate || *chars != '\n')) { + if (isascii(*chars)) + fputc((char)(*chars++), out); + else + fputc('-', out); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// String Usage Statistics Routines + +static PLHashTable* gStringInfo = nsnull; +PRLock* gStringInfoLock = nsnull; +PRBool gNoStringInfo = PR_FALSE; + +nsStringInfo::nsStringInfo(nsStr& str) + : mCount(0) +{ + nsStr::Initialize(mStr, str.mCharSize); + nsStr::Assign(mStr, str, 0, -1); +// nsStr::Print(mStr, stdout); +// fputc('\n', stdout); +} + +PR_EXTERN(PRHashNumber) +nsStr_Hash(const void* key) +{ + nsStr* str = (nsStr*)key; + return nsStr::HashCode(*str); +} + +PR_EXTERN(PRIntn) +nsStr_Compare(const void *v1, const void *v2) +{ + nsStr* str1 = (nsStr*)v1; + nsStr* str2 = (nsStr*)v2; + return nsStr::Compare(*str1, *str2, -1, PR_FALSE) == 0; +} + +nsStringInfo* +nsStringInfo::GetInfo(nsStr& str) +{ + if (gStringInfo == nsnull) { + gStringInfo = PL_NewHashTable(1024, + nsStr_Hash, + nsStr_Compare, + PL_CompareValues, + NULL, NULL); + gStringInfoLock = PR_NewLock(); + } + PR_Lock(gStringInfoLock); + nsStringInfo* info = + (nsStringInfo*)PL_HashTableLookup(gStringInfo, &str); + if (info == NULL) { + gNoStringInfo = PR_TRUE; + info = new nsStringInfo(str); + if (info) { + PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info); + if (e == NULL) { + delete info; + info = NULL; + } + } + gNoStringInfo = PR_FALSE; + } + PR_Unlock(gStringInfoLock); + return info; +} + +void +nsStringInfo::Seen(nsStr& str) +{ + if (!gNoStringInfo) { + nsStringInfo* info = GetInfo(str); + info->mCount++; + } +} + +void +nsStringInfo::Report(FILE* out) +{ + if (gStringInfo) { + fprintf(out, "\n== String Stats\n"); + PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out); + } +} + +PRIntn +nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg) +{ + nsStringInfo* entry = (nsStringInfo*)he->value; + FILE* out = (FILE*)arg; + + fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength); + nsStr::Print(entry->mStr, out, PR_TRUE); + fputc('\n', out); + return HT_ENUMERATE_NEXT; +} + +#endif // DEBUG + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/ds/nsStr.h b/mozilla/xpcom/ds/nsStr.h index b44eeb01358..6fede507c2f 100644 --- a/mozilla/xpcom/ds/nsStr.h +++ b/mozilla/xpcom/ds/nsStr.h @@ -186,6 +186,7 @@ #include "nscore.h" #include "nsIAllocator.h" #include +#include //---------------------------------------------------------------------------------------- @@ -410,6 +411,19 @@ struct NS_COM nsStr { static PRBool DidAcquireMemory(void); + /** + * Returns a hash code for the string for use in a PLHashTable. + */ + static PRUint32 HashCode(const nsStr& aDest); + +#ifdef DEBUG + /** + * Prints an nsStr. If truncate is true, the string is only printed up to + * the first newline. (Note: The current implementation doesn't handle + * non-ascii unicode characters.) + */ + static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE); +#endif PRUint32 mLength; PRUint32 mCapacity; @@ -468,6 +482,28 @@ inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ return 0; } +#ifdef DEBUG -#endif +#include "plhash.h" +class nsStringInfo { +public: + nsStringInfo(nsStr& str); + ~nsStringInfo() {} + + static nsStringInfo* GetInfo(nsStr& str); + + static void Seen(nsStr& str); + + static void Report(FILE* out = stdout); + + static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg); + +protected: + nsStr mStr; + PRUint32 mCount; +}; + +#endif // DEBUG + +#endif // _nsStr diff --git a/mozilla/xpcom/string/obsolete/nsStr.cpp b/mozilla/xpcom/string/obsolete/nsStr.cpp index c0f78afc224..8d106d0f921 100644 --- a/mozilla/xpcom/string/obsolete/nsStr.cpp +++ b/mozilla/xpcom/string/obsolete/nsStr.cpp @@ -173,6 +173,9 @@ void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a aDest.mLength+=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } } } @@ -241,7 +244,9 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin //finally, make sure to update the string length... aDest.mLength+=theLength; AddNullTerminator(aDest); - +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif }//if //else nothing to do! } @@ -272,6 +277,9 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){ (*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength); aDest.mLength-=theLength; AddNullTerminator(aDest); +#ifdef DEBUG + nsStringInfo::Seen(aDest); +#endif } else Truncate(aDest,aDestOffset); }//if @@ -287,6 +295,9 @@ void nsStr::Truncate(nsStr& aDest,PRUint32 aDestOffset){ if(aDestOffset> 28) ^ (h << 4) ^ *c; + } + else { /* Sample a la java.lang.String.hash(). */ + for(m = n / 8; n >= m; c += m, n -= m) + h = (h >> 28) ^ (h << 4) ^ *c; + } + return h; + } + return (PRUint32)PL_HashString((const void*) aDest.mStr); +} +#ifdef DEBUG + +#include + +void +nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate) +{ + PRInt32 printLen = (PRInt32)aDest.mLength; + + if (aDest.mCharSize == eOneByte) { + const char* chars = aDest.mStr; + while (printLen-- && (!truncate || *chars != '\n')) { + fputc(*chars++, out); + } + } + else { + const PRUnichar* chars = aDest.mUStr; + while (printLen-- && (!truncate || *chars != '\n')) { + if (isascii(*chars)) + fputc((char)(*chars++), out); + else + fputc('-', out); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// String Usage Statistics Routines + +static PLHashTable* gStringInfo = nsnull; +PRLock* gStringInfoLock = nsnull; +PRBool gNoStringInfo = PR_FALSE; + +nsStringInfo::nsStringInfo(nsStr& str) + : mCount(0) +{ + nsStr::Initialize(mStr, str.mCharSize); + nsStr::Assign(mStr, str, 0, -1); +// nsStr::Print(mStr, stdout); +// fputc('\n', stdout); +} + +PR_EXTERN(PRHashNumber) +nsStr_Hash(const void* key) +{ + nsStr* str = (nsStr*)key; + return nsStr::HashCode(*str); +} + +PR_EXTERN(PRIntn) +nsStr_Compare(const void *v1, const void *v2) +{ + nsStr* str1 = (nsStr*)v1; + nsStr* str2 = (nsStr*)v2; + return nsStr::Compare(*str1, *str2, -1, PR_FALSE) == 0; +} + +nsStringInfo* +nsStringInfo::GetInfo(nsStr& str) +{ + if (gStringInfo == nsnull) { + gStringInfo = PL_NewHashTable(1024, + nsStr_Hash, + nsStr_Compare, + PL_CompareValues, + NULL, NULL); + gStringInfoLock = PR_NewLock(); + } + PR_Lock(gStringInfoLock); + nsStringInfo* info = + (nsStringInfo*)PL_HashTableLookup(gStringInfo, &str); + if (info == NULL) { + gNoStringInfo = PR_TRUE; + info = new nsStringInfo(str); + if (info) { + PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info); + if (e == NULL) { + delete info; + info = NULL; + } + } + gNoStringInfo = PR_FALSE; + } + PR_Unlock(gStringInfoLock); + return info; +} + +void +nsStringInfo::Seen(nsStr& str) +{ + if (!gNoStringInfo) { + nsStringInfo* info = GetInfo(str); + info->mCount++; + } +} + +void +nsStringInfo::Report(FILE* out) +{ + if (gStringInfo) { + fprintf(out, "\n== String Stats\n"); + PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out); + } +} + +PRIntn +nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg) +{ + nsStringInfo* entry = (nsStringInfo*)he->value; + FILE* out = (FILE*)arg; + + fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength); + nsStr::Print(entry->mStr, out, PR_TRUE); + fputc('\n', out); + return HT_ENUMERATE_NEXT; +} + +#endif // DEBUG + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/string/obsolete/nsStr.h b/mozilla/xpcom/string/obsolete/nsStr.h index b44eeb01358..6fede507c2f 100644 --- a/mozilla/xpcom/string/obsolete/nsStr.h +++ b/mozilla/xpcom/string/obsolete/nsStr.h @@ -186,6 +186,7 @@ #include "nscore.h" #include "nsIAllocator.h" #include +#include //---------------------------------------------------------------------------------------- @@ -410,6 +411,19 @@ struct NS_COM nsStr { static PRBool DidAcquireMemory(void); + /** + * Returns a hash code for the string for use in a PLHashTable. + */ + static PRUint32 HashCode(const nsStr& aDest); + +#ifdef DEBUG + /** + * Prints an nsStr. If truncate is true, the string is only printed up to + * the first newline. (Note: The current implementation doesn't handle + * non-ascii unicode characters.) + */ + static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE); +#endif PRUint32 mLength; PRUint32 mCapacity; @@ -468,6 +482,28 @@ inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ return 0; } +#ifdef DEBUG -#endif +#include "plhash.h" +class nsStringInfo { +public: + nsStringInfo(nsStr& str); + ~nsStringInfo() {} + + static nsStringInfo* GetInfo(nsStr& str); + + static void Seen(nsStr& str); + + static void Report(FILE* out = stdout); + + static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg); + +protected: + nsStr mStr; + PRUint32 mCount; +}; + +#endif // DEBUG + +#endif // _nsStr