Bug 1360803 - switch nsMsgSearchValue to using nsCString and fix CTOR of nsMsgSearchValueImpl. r=mkmelin
authorJorg K <jorgk@jorgk.com>
Wed, 26 Sep 2018 10:27:43 +0200
changeset 33232 9cbdc6469caf6126896fcee4803f920a316a8172
parent 33231 34eaca00ed364f73e4b43c1240e1d8a900655bce
child 33233 3bc0fb310b8a55a282da9addf885f9beba0c8bac
push id387
push userclokep@gmail.com
push dateMon, 10 Dec 2018 21:30:47 +0000
reviewersmkmelin
bugs1360803
Bug 1360803 - switch nsMsgSearchValue to using nsCString and fix CTOR of nsMsgSearchValueImpl. r=mkmelin
mailnews/base/search/public/nsMsgSearchCore.idl
mailnews/base/search/src/nsMsgSearchTerm.cpp
mailnews/base/search/src/nsMsgSearchValue.cpp
--- a/mailnews/base/search/public/nsMsgSearchCore.idl
+++ b/mailnews/base/search/public/nsMsgSearchCore.idl
@@ -163,34 +163,34 @@ interface nsMsgSearchBooleanOp {
 };
 
 /* Use this to specify the value of a search term */
 
 [ptr] native nsMsgSearchValue(nsMsgSearchValue);
 
 %{C++
 #include "nsString.h"
-
 typedef struct nsMsgSearchValue
 {
     nsMsgSearchAttribValue attribute;
     union
     {
       nsMsgPriorityValue priority;
       PRTime date;
       uint32_t msgStatus; /* see MSG_FLAG in msgcom.h */
       uint32_t size;
       nsMsgKey key;
       int32_t age; /* in days */
       nsIMsgFolder *folder;
       nsMsgLabelValue label;
       uint32_t junkStatus;
       uint32_t junkPercent;
     } u;
-    char *string;
+    // We keep two versions of the string to avoid conversion at "search time".
+    nsCString utf8String;
     nsString utf16String;
 } nsMsgSearchValue;
 %}
 
 [ptr] native nsMsgSearchTerm(nsMsgSearchTerm);
 
 // Please note the ! at the start of this macro, which means the macro
 // needs to enumerate the non-string attributes.
--- a/mailnews/base/search/src/nsMsgSearchTerm.cpp
+++ b/mailnews/base/search/src/nsMsgSearchTerm.cpp
@@ -353,17 +353,16 @@ int32_t NS_MsgGetStatusValueFromName(cha
   return 0;
 }
 
 
 // Needed for DeStream method.
 nsMsgSearchTerm::nsMsgSearchTerm()
 {
     // initialize this to zero
-    m_value.string=nullptr;
     m_value.attribute=0;
     m_value.u.priority=0;
     m_attribute = nsMsgSearchAttrib::Default;
     m_operator = nsMsgSearchOp::Contains;
     mBeginsGrouping = false;
     mEndsGrouping = false;
     m_matchAll = false;
 
@@ -394,18 +393,16 @@ nsMsgSearchTerm::nsMsgSearchTerm (nsMsgS
   nsMsgResultElement::AssignValues (val, &m_value);
   m_matchAll = false;
 }
 
 
 
 nsMsgSearchTerm::~nsMsgSearchTerm ()
 {
-  if (IS_STRING_ATTRIBUTE (m_attribute) && m_value.string)
-    free(m_value.string);
 }
 
 NS_IMPL_ISUPPORTS(nsMsgSearchTerm, nsIMsgSearchTerm)
 
 
 // Perhaps we could find a better place for this?
 // Caller needs to free.
 /* static */char *nsMsgSearchTerm::EscapeQuotesInStr(const char *str)
@@ -428,41 +425,41 @@ NS_IMPL_ISUPPORTS(nsMsgSearchTerm, nsIMs
     *destPtr = '\0';
   }
   return escapedStr;
 }
 
 
 nsresult nsMsgSearchTerm::OutputValue(nsCString &outputStr)
 {
-  if (IS_STRING_ATTRIBUTE(m_attribute) && m_value.string)
+  if (IS_STRING_ATTRIBUTE(m_attribute) && !m_value.utf8String.IsEmpty())
   {
     bool    quoteVal = false;
     // need to quote strings with ')' and strings starting with '"' or ' '
     // filter code will escape quotes
-    if (PL_strchr(m_value.string, ')') ||
-        (m_value.string[0] == ' ') ||
-        (m_value.string[0] == '"'))
+    if (m_value.utf8String.FindChar(')') != kNotFound ||
+        (m_value.utf8String.First() == ' ') ||
+        (m_value.utf8String.First() == '"'))
     {
       quoteVal = true;
       outputStr += "\"";
     }
-    if (PL_strchr(m_value.string, '"'))
+    if (m_value.utf8String.FindChar('"') != kNotFound)
     {
-      char *escapedString = nsMsgSearchTerm::EscapeQuotesInStr(m_value.string);
+      char *escapedString = nsMsgSearchTerm::EscapeQuotesInStr(m_value.utf8String.get());
       if (escapedString)
       {
         outputStr += escapedString;
         PR_Free(escapedString);
       }
 
     }
     else
     {
-      outputStr += m_value.string;
+      outputStr += m_value.utf8String;
     }
     if (quoteVal)
       outputStr += "\"";
   }
   else
   {
     switch (m_attribute)
     {
@@ -598,20 +595,18 @@ nsresult nsMsgSearchTerm::ParseValue(cha
     {
       quoteVal = true;
       inStream++;
     }
     int valueLen = PL_strlen(inStream);
     if (quoteVal && inStream[valueLen - 1] == '"')
       valueLen--;
 
-    m_value.string = (char *) PR_Malloc(valueLen + 1);
-    PL_strncpy(m_value.string, inStream, valueLen + 1);
-    m_value.string[valueLen] = '\0';
-    CopyUTF8toUTF16(mozilla::MakeSpan(m_value.string, valueLen), m_value.utf16String);
+    m_value.utf8String.Assign(inStream, valueLen);
+    CopyUTF8toUTF16(mozilla::MakeSpan(inStream, valueLen), m_value.utf16String);
   }
   else
   {
     switch (m_attribute)
     {
     case nsMsgSearchAttrib::Date:
       PR_ParseTimeString (inStream, false, &m_value.u.date);
       break;
@@ -727,18 +722,18 @@ nsresult nsMsgSearchTerm::DeStreamNew (c
   // convert label filters and saved searches to keyword equivalents
   if (secondCommaSep)
     ParseValue(secondCommaSep + 1);
   if (m_attribute == nsMsgSearchAttrib::Label)
   {
     nsAutoCString keyword("$label");
     m_value.attribute = m_attribute = nsMsgSearchAttrib::Keywords;
     keyword.Append('0' + m_value.u.label);
-    m_value.string = PL_strdup(keyword.get());
-    CopyUTF8toUTF16(mozilla::MakeStringSpan(m_value.string), m_value.utf16String);
+    m_value.utf8String = keyword;
+    CopyUTF8toUTF16(keyword, m_value.utf16String);
   }
   return NS_OK;
 }
 
 
 // Looks in the MessageDB for the user specified arbitrary header, if it finds the header, it then looks for a match against
 // the value for the header.
 nsresult nsMsgSearchTerm::MatchArbitraryHeader(nsIMsgSearchScopeTerm *scope,
@@ -928,17 +923,17 @@ nsresult nsMsgSearchTerm::MatchBody(nsIM
   nsresult rv = NS_OK;
 
   bool result = false;
   *pResult = false;
 
   // Small hack so we don't look all through a message when someone has
   // specified "BODY IS foo". ### Since length is in lines, this is not quite right.
   if ((length > 0) && (m_operator == nsMsgSearchOp::Is || m_operator == nsMsgSearchOp::Isnt))
-    length = PL_strlen (m_value.string);
+    length = m_value.utf8String.Length();
 
   nsMsgBodyHandler * bodyHan  = new nsMsgBodyHandler (scope, length, msg, db);
   if (!bodyHan)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsAutoCString buf;
   bool endOfFile = false;  // if retValue == 0, we've hit the end of the file
   uint32_t lines = 0;
@@ -953,17 +948,17 @@ nsresult nsMsgSearchTerm::MatchBody(nsIM
   // quoted printable decoding. Otherwise we assume everything is
   // quoted printable. Obviously everything isn't quoted printable, but
   // since we don't have a MIME parser handy, and we want to err on the
   // side of too many hits rather than not enough, we'll assume in that
   // general direction. Blech. ### FIX ME
   // bug fix #314637: for stateful charsets like ISO-2022-JP, we don't
   // want to decode quoted printable since it contains '='.
   bool isQuotedPrintable = !nsMsgI18Nstateful_charset(folderCharset) &&
-    (PL_strchr (m_value.string, '=') == nullptr);
+    (m_value.utf8String.FindChar('=') == kNotFound);
 
   nsCString compare;
   nsCString charset;
   while (!endOfFile && result == boolContinueLoop)
   {
     if (bodyHan->GetNextLine(buf, charset) >= 0)
     {
       bool softLineBreak = false;
@@ -1013,26 +1008,26 @@ nsresult nsMsgSearchTerm::InitializeAddr
   nsresult rv = NS_OK;
 
   if (mDirectory)
   {
     nsCString uri;
     rv = mDirectory->GetURI(uri);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!uri.Equals(m_value.string))
+    if (!uri.Equals(m_value.utf8String))
       // clear out the directory....we are no longer pointing to the right one
       mDirectory = nullptr;
   }
   if (!mDirectory)
   {
     nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = abManager->GetDirectory(nsDependentCString(m_value.string), getter_AddRefs(mDirectory));
+    rv = abManager->GetDirectory(m_value.utf8String, getter_AddRefs(mDirectory));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult nsMsgSearchTerm::MatchInAddressBook(const nsAString &aAddress,
                                              bool *pResult)
@@ -1441,20 +1436,20 @@ nsresult nsMsgSearchTerm::MatchJunkScore
   NS_ENSURE_ARG_POINTER(pResult);
 
   bool matches = false;
   nsresult rv = NS_OK;
 
   switch (m_operator)
   {
   case nsMsgSearchOp::Is:
-    matches = aJunkScoreOrigin && !strcmp(aJunkScoreOrigin, m_value.string);
+    matches = aJunkScoreOrigin && m_value.utf8String.Equals(aJunkScoreOrigin);
     break;
   case nsMsgSearchOp::Isnt:
-    matches = !aJunkScoreOrigin || strcmp(aJunkScoreOrigin, m_value.string);
+    matches = !aJunkScoreOrigin || !m_value.utf8String.Equals(aJunkScoreOrigin);
     break;
   default:
     rv = NS_ERROR_FAILURE;
     NS_ERROR("invalid compare op for junk score origin");
   }
 
   *pResult = matches;
   return rv;
@@ -1567,32 +1562,32 @@ nsresult nsMsgSearchTerm::MatchKeyword(c
     return NS_OK;
   }
 
   // check if we can skip expensive valid keywordList test
   if (m_operator == nsMsgSearchOp::DoesntContain ||
       m_operator == nsMsgSearchOp::Contains)
   {
     nsCString keywordString(keywordList);
-    const uint32_t kKeywordLen = PL_strlen(m_value.string);
-    const char* matchStart = PL_strstr(keywordString.get(), m_value.string);
+    const uint32_t kKeywordLen = m_value.utf8String.Length();
+    const char* matchStart = PL_strstr(keywordString.get(), m_value.utf8String.get());
     while (matchStart)
     {
       // For a real match, matchStart must be the start of the keywordList or
       // preceded by a space and matchEnd must point to a \0 or space.
       const char* matchEnd = matchStart + kKeywordLen;
       if ((matchStart == keywordString.get() || matchStart[-1] == ' ') &&
           (!*matchEnd || *matchEnd == ' '))
       {
         // found the keyword
         *pResult = m_operator == nsMsgSearchOp::Contains;
         return NS_OK;
       }
       // no match yet, so search on
-      matchStart = PL_strstr(matchEnd, m_value.string);
+      matchStart = PL_strstr(matchEnd, m_value.utf8String.get());
     }
     // keyword not found
     *pResult = m_operator == nsMsgSearchOp::DoesntContain;
     return NS_OK;
   }
 
   // Only accept valid keys in tokens.
   nsresult rv = NS_OK;
@@ -1622,17 +1617,17 @@ nsresult nsMsgSearchTerm::MatchKeyword(c
       // IsntEmpty succeeds on any valid token
       if (m_operator == nsMsgSearchOp::IsntEmpty)
       {
         *pResult = true;
         return rv;
       }
 
       // Does this valid tag key match our search term?
-      matches = keywordArray[i].Equals(m_value.string);
+      matches = keywordArray[i].Equals(m_value.utf8String);
 
       // Is or Isn't partly determined on a single unmatched token
       if (!matches)
       {
         if (m_operator == nsMsgSearchOp::Is)
         {
           *pResult = false;
           return rv;
@@ -1726,17 +1721,17 @@ NS_IMETHODIMP nsMsgSearchTerm::MatchCust
       do_GetService(NS_MSGFILTERSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgSearchCustomTerm> customTerm;
   rv = filterService->GetCustomTerm(m_customId, getter_AddRefs(customTerm));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (customTerm)
-    return customTerm->Match(aHdr, nsDependentCString(m_value.string),
+    return customTerm->Match(aHdr, m_value.utf8String,
                              m_operator, pResult);
   *pResult = false;     // default to no match if term is missing
   return NS_ERROR_FAILURE; // missing custom term
 }
 
 // set the id of a custom search term
 NS_IMETHODIMP nsMsgSearchTerm::SetCustomId(const nsACString &aId)
 {
@@ -2037,17 +2032,17 @@ nsresult nsMsgResultElement::AssignValue
     rv = src->GetSize(&dst->u.size);
     break;
   default:
     if (dst->attribute < nsMsgSearchAttrib::kNumMsgSearchAttributes)
     {
       NS_ASSERTION(IS_STRING_ATTRIBUTE(dst->attribute), "assigning non-string result");
       nsString unicodeString;
       rv = src->GetStr(unicodeString);
-      dst->string = ToNewUTF8String(unicodeString);
+      CopyUTF16toUTF8(unicodeString, dst->utf8String);
       dst->utf16String = unicodeString;
     }
     else
       rv = NS_ERROR_INVALID_ARG;
   }
   return rv;
 }
 
--- a/mailnews/base/search/src/nsMsgSearchValue.cpp
+++ b/mailnews/base/search/src/nsMsgSearchValue.cpp
@@ -6,30 +6,21 @@
 #include "MailNewsTypes.h"
 #include "nsMsgSearchValue.h"
 #include "nsIMsgFolder.h"
 #include "nsMsgUtils.h"
 #include "nsString.h"
 
 nsMsgSearchValueImpl::nsMsgSearchValueImpl(nsMsgSearchValue *aInitialValue)
 {
-    mValue = *aInitialValue;
-    if (IS_STRING_ATTRIBUTE(aInitialValue->attribute) && aInitialValue->string)
-    {
-        mValue.string = NS_xstrdup(aInitialValue->string);
-        CopyUTF8toUTF16(mozilla::MakeStringSpan(mValue.string), mValue.utf16String);
-    }
-    else
-        mValue.string = 0;
+  mValue = *aInitialValue;
 }
 
 nsMsgSearchValueImpl::~nsMsgSearchValueImpl()
 {
-  if (IS_STRING_ATTRIBUTE(mValue.attribute))
-    free(mValue.string);
 }
 
 NS_IMPL_ISUPPORTS(nsMsgSearchValueImpl, nsIMsgSearchValue)
 
 NS_IMPL_GETSET(nsMsgSearchValueImpl, Priority, nsMsgPriorityValue, mValue.u.priority)
 NS_IMPL_GETSET(nsMsgSearchValueImpl, Status, uint32_t, mValue.u.msgStatus)
 NS_IMPL_GETSET(nsMsgSearchValueImpl, Size, uint32_t, mValue.u.size)
 NS_IMPL_GETSET(nsMsgSearchValueImpl, MsgKey, nsMsgKey, mValue.u.key)
@@ -64,19 +55,17 @@ nsMsgSearchValueImpl::GetStr(nsAString &
     aResult = mValue.utf16String;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgSearchValueImpl::SetStr(const nsAString &aValue)
 {
     NS_ENSURE_TRUE(IS_STRING_ATTRIBUTE(mValue.attribute), NS_ERROR_ILLEGAL_VALUE);
-    if (mValue.string)
-        free(mValue.string);
-    mValue.string = ToNewUTF8String(aValue);
+    CopyUTF16toUTF8(aValue, mValue.utf8String);
     mValue.utf16String = aValue;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgSearchValueImpl::ToString(nsAString &aResult)
 {
     aResult.AssignLiteral("[nsIMsgSearchValue: ");