Bug 295088: Filter/Search term evaluator is extremely sub-optimal; p=Howard Chu <hyc@symas.com>, r=bienvenu, sr=dmose

This commit is contained in:
mnyromyr%tprac.de 2005-10-20 19:37:58 +00:00
Родитель 10de8e659f
Коммит dbf07011fd
8 изменённых файлов: 141 добавлений и 140 удалений

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -52,12 +53,10 @@
expression tree. Each node in the tree consists of either
(1) a boolean operator and two nsMsgSearchBoolExpressions or
(2) if the node is a leaf node then it contains a search term.
With each search term that is part of the expression we also keep
track of either an evaluation value (XP_BOOL) or a character string.
Evaluation values are used for offline searching. The character
With each search term that is part of the expression we may also keep
a character string. The character
string is used to store the IMAP/NNTP encoding of the search term. This
makes evaluating the expression (for offline) or generating a search
encoding (for online) easier.
makes generating a search encoding (for online) easier.
For IMAP/NNTP: nsMsgSearchBoolExpression has/assumes knowledge about how
AND and OR search terms are combined according to IMAP4 and NNTP protocol.
@ -76,9 +75,7 @@ public:
// create a leaf node expression
nsMsgSearchBoolExpression(nsIMsgSearchTerm * aNewTerm,
PRBool aEvaluationValue = PR_TRUE,
char * aEncodingString = NULL);
nsMsgSearchBoolExpression(nsIMsgSearchTerm * aNewTerm, char * aEncodingString);
// create a non-leaf node expression containing 2 expressions
// and a boolean operator
@ -90,18 +87,19 @@ public:
~nsMsgSearchBoolExpression(); // recursively destroys all sub
// expressions as well
// accesors
// accessors
// Offline
static nsMsgSearchBoolExpression * AddSearchTerm (nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, PRBool aEvaluationValue);
static nsMsgSearchBoolExpression * AddSearchTermWithEncoding (nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, char * aEncodingStr); // IMAP/NNTP
static nsMsgSearchBoolExpression * AddSearchTerm (nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, char * aEncodingStr); // IMAP/NNTP
static nsMsgSearchBoolExpression * AddExpressionTree(nsMsgSearchBoolExpression * aOrigExpr, nsMsgSearchBoolExpression * aExpression, PRBool aBoolOp);
// parses the expression tree and all
// expressions underneath this node using
// each EvaluationValue at each leaf to
// expressions underneath this node to
// determine if the end result is PR_TRUE or PR_FALSE.
PRBool OfflineEvaluate();
PRBool OfflineEvaluate(nsIMsgDBHdr *msgToMatch,
const char *defaultCharset, nsIMsgSearchScopeTerm *scope,
nsIMsgDatabase *db, const char *headers, PRUint32 headerSize,
PRBool Filtering);
// assuming the expression is for online
// searches, determine the length of the
@ -112,15 +110,6 @@ public:
// memory in buffer with
// the IMAP/NNTP encoding for the expression
void GenerateEncodeStr(nsCString * buffer);
protected:
// if we are a leaf node, all we have is a search term
// and a Evaluation value for that search term
nsIMsgSearchTerm * m_term;
PRBool m_evalValue;
// store IMAP/NNTP encoding for the search term if applicable
nsCString m_encodingStr;
// if we are not a leaf node, then we have two other expressions
// and a boolean operator
@ -128,6 +117,13 @@ protected:
nsMsgSearchBoolExpression * m_rightChild;
nsMsgSearchBooleanOperator m_boolOp;
protected:
// if we are a leaf node, all we have is a search term
nsIMsgSearchTerm * m_term;
// store IMAP/NNTP encoding for the search term if applicable
nsCString m_encodingStr;
// internal methods
@ -138,7 +134,6 @@ protected:
// that by calling leftToRightAddTerm. If future forms of evaluation
// need to be supported, add new methods here for proper tree construction.
nsMsgSearchBoolExpression * leftToRightAddTerm(nsIMsgSearchTerm * newTerm,
PRBool EvaluationValue,
char * encodingStr);
};

Просмотреть файл

@ -22,6 +22,7 @@
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Seth Spitzer <sspitzer@netscape.com>
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -170,7 +171,8 @@ nsMsgRuleAction::GetStrValue(char **aStrValue)
nsMsgFilter::nsMsgFilter():
m_temporary(PR_FALSE),
m_unparseable(PR_FALSE),
m_filterList(nsnull)
m_filterList(nsnull),
m_expressionTree(nsnull)
{
NS_NewISupportsArray(getter_AddRefs(m_termList));
NS_NewISupportsArray(getter_AddRefs(m_actionList));
@ -180,6 +182,7 @@ nsMsgFilter::nsMsgFilter():
nsMsgFilter::~nsMsgFilter()
{
delete m_expressionTree;
}
NS_IMPL_ISUPPORTS1(nsMsgFilter, nsIMsgFilter)
@ -243,7 +246,8 @@ NS_IMETHODIMP nsMsgFilter::AddTerm(
NS_IMETHODIMP nsMsgFilter::AppendTerm(nsIMsgSearchTerm * aTerm)
{
NS_ENSURE_TRUE(aTerm, NS_ERROR_NULL_POINTER);
// invalidate expression tree if we're changing the terms
delete m_expressionTree;
return m_termList->AppendElement(NS_STATIC_CAST(nsISupports*,aTerm));
}
@ -391,6 +395,7 @@ NS_IMETHODIMP nsMsgFilter::GetSearchTerms(nsISupportsArray **aResult)
NS_IMETHODIMP nsMsgFilter::SetSearchTerms(nsISupportsArray *aSearchList)
{
delete m_expressionTree;
m_termList = aSearchList;
return NS_OK;
}
@ -511,7 +516,7 @@ NS_IMETHODIMP nsMsgFilter::MatchHdr(nsIMsgDBHdr *msgHdr, nsIMsgFolder *folder, n
nsXPIDLCString folderCharset;
folder->GetCharset(getter_Copies(folderCharset));
nsresult rv = nsMsgSearchOfflineMail::MatchTermsForFilter(msgHdr, m_termList,
folderCharset.get(), scope, db, headers, headersSize, pResult);
folderCharset.get(), scope, db, headers, headersSize, &m_expressionTree, pResult);
delete scope;
return rv;
}

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* David Bienvenu (bienvenu@nventure.com)
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -44,6 +45,7 @@
#include "nsIMsgFilter.h"
#include "nsMsgSearchArray.h"
#include "nsIMsgSearchScopeTerm.h"
#include "nsMsgSearchBoolExpression.h"
class nsMsgRuleAction : public nsIMsgRuleAction
{
@ -120,6 +122,7 @@ protected:
nsCOMPtr<nsIMsgSearchScopeTerm> m_scope; /* default for mail rules is inbox, but news rules could
have a newsgroup - LDAP would be invalid */
nsCOMPtr<nsISupportsArray> m_actionList;
nsMsgSearchBoolExpression *m_expressionTree;
};
#endif

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -67,19 +68,11 @@ extern "C"
//----------------------------------------------------------------------------
nsMsgSearchBoolExpression * nsMsgSearchBoolExpression::AddSearchTermWithEncoding(nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, char * aEncodingStr)
nsMsgSearchBoolExpression * nsMsgSearchBoolExpression::AddSearchTerm(nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, char * aEncodingStr)
// appropriately add the search term to the current expression and return a pointer to the
// new expression. The encodingStr is the IMAP/NNTP encoding string for newTerm.
{
return aOrigExpr->leftToRightAddTerm(aNewTerm, PR_FALSE, aEncodingStr);
}
nsMsgSearchBoolExpression * nsMsgSearchBoolExpression::AddSearchTerm(nsMsgSearchBoolExpression * aOrigExpr, nsIMsgSearchTerm * aNewTerm, PRBool aEvalValue)
// appropriately add the search term to the current expression
// Returns: a pointer to the new expression which includes this new search term
{
return aOrigExpr->leftToRightAddTerm(aNewTerm, aEvalValue, nsnull); // currently we build our expressions to
// evaluate left to right.
return aOrigExpr->leftToRightAddTerm(aNewTerm, aEncodingStr);
}
nsMsgSearchBoolExpression * nsMsgSearchBoolExpression::AddExpressionTree(nsMsgSearchBoolExpression * aOrigExpr, nsMsgSearchBoolExpression * aExpression, PRBool aBoolOp)
@ -100,19 +93,17 @@ nsMsgSearchBoolExpression::nsMsgSearchBoolExpression()
{
m_term = nsnull;
m_boolOp = nsMsgSearchBooleanOp::BooleanAND;
m_evalValue = PR_FALSE;
m_leftChild = nsnull;
m_rightChild = nsnull;
}
nsMsgSearchBoolExpression::nsMsgSearchBoolExpression (nsIMsgSearchTerm * newTerm, PRBool evalValue, char * encodingStr)
nsMsgSearchBoolExpression::nsMsgSearchBoolExpression (nsIMsgSearchTerm * newTerm, char * encodingStr)
// we are creating an expression which contains a single search term (newTerm)
// and the search term's IMAP or NNTP encoding value for online search expressions AND
// a boolean evaluation value which is used for offline search expressions.
{
m_term = newTerm;
m_encodingStr = encodingStr;
m_evalValue = evalValue;
m_boolOp = nsMsgSearchBooleanOp::BooleanAND;
// this expression does not contain sub expressions
@ -130,7 +121,6 @@ nsMsgSearchBoolExpression::nsMsgSearchBoolExpression (nsMsgSearchBoolExpression
m_boolOp = boolOp;
m_term = nsnull;
m_evalValue = PR_FALSE;
}
nsMsgSearchBoolExpression::~nsMsgSearchBoolExpression()
@ -143,18 +133,17 @@ nsMsgSearchBoolExpression::~nsMsgSearchBoolExpression()
}
nsMsgSearchBoolExpression *
nsMsgSearchBoolExpression::leftToRightAddTerm(nsIMsgSearchTerm * newTerm, PRBool evalValue, char * encodingStr)
nsMsgSearchBoolExpression::leftToRightAddTerm(nsIMsgSearchTerm * newTerm, char * encodingStr)
{
// we have a base case where this is the first term being added to the expression:
if (!m_term && !m_leftChild && !m_rightChild)
{
m_term = newTerm;
m_evalValue = evalValue;
m_encodingStr = encodingStr;
return this;
}
nsMsgSearchBoolExpression * tempExpr = new nsMsgSearchBoolExpression (newTerm,evalValue,encodingStr);
nsMsgSearchBoolExpression * tempExpr = new nsMsgSearchBoolExpression (newTerm,encodingStr);
if (tempExpr) // make sure creation succeeded
{
PRBool booleanAnd;
@ -169,36 +158,42 @@ nsMsgSearchBoolExpression::leftToRightAddTerm(nsIMsgSearchTerm * newTerm, PRBool
}
PRBool nsMsgSearchBoolExpression::OfflineEvaluate()
// returns PR_TRUE or PR_FALSE depending on what the current expression evaluates to. Since this is
// offline, when we created the expression we stored an evaluation value for each search term in
// the expression. These are the values we use to determine if the expression is PR_TRUE or PR_FALSE.
// returns PR_TRUE or PR_FALSE depending on what the current expression evaluates to.
PRBool nsMsgSearchBoolExpression::OfflineEvaluate(nsIMsgDBHdr *msgToMatch, const char *defaultCharset,
nsIMsgSearchScopeTerm *scope, nsIMsgDatabase *db, const char *headers,
PRUint32 headerSize, PRBool Filtering)
{
PRBool result = PR_TRUE; // always default to false positives
PRBool isAnd;
if (m_term) // do we contain just a search term?
return m_evalValue;
{
nsMsgSearchOfflineMail::ProcessSearchTerm(msgToMatch, m_term,
defaultCharset, scope, db, headers, headerSize, Filtering, &result);
return result;
}
// otherwise we must recursively determine the value of our sub expressions
PRBool result1 = PR_TRUE; // always default to false positives
PRBool result2 = PR_TRUE;
isAnd = (m_boolOp == nsMsgSearchBooleanOp::BooleanAND);
if (m_leftChild)
{
result1 = m_leftChild->OfflineEvaluate();
if (m_boolOp == nsMsgSearchBooleanOp::BooleanOR && result1 ||
(m_boolOp == nsMsgSearchBooleanOp::BooleanAND && !result1))
return result1;
result = m_leftChild->OfflineEvaluate(msgToMatch, defaultCharset,
scope, db, headers, headerSize, Filtering);
// If (TRUE and OR) or (FALSE and AND) return result
if (result ^ isAnd)
return result;
}
// If we got this far, either there was no leftChild (which is impossible)
// or we got (FALSE and OR) or (TRUE and AND) from the first result. That
// means the outcome depends entirely on the rightChild.
if (m_rightChild)
result2 = m_rightChild->OfflineEvaluate();
result = m_rightChild->OfflineEvaluate(msgToMatch, defaultCharset,
scope, db, headers, headerSize, Filtering);
if (m_boolOp == nsMsgSearchBooleanOp::BooleanOR)
return (result1 || result2) ? PR_TRUE : PR_FALSE;
if (m_boolOp == nsMsgSearchBooleanOp::BooleanAND && result1 && result2)
return PR_TRUE;
return PR_FALSE;
return result;
}
// ### Maybe we can get rid of these because of our use of nsString???
@ -350,9 +345,10 @@ nsMsgSearchOfflineMail::MatchTermsForFilter(nsIMsgDBHdr *msgToMatch,
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult)
{
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, headers, headerSize, PR_TRUE, pResult);
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, headers, headerSize, PR_TRUE, aExpressionTree, pResult);
}
// static method which matches a header against a list of search terms.
@ -362,46 +358,28 @@ nsMsgSearchOfflineMail::MatchTermsForSearch(nsIMsgDBHdr *msgToMatch,
const char *defaultCharset,
nsIMsgSearchScopeTerm *scope,
nsIMsgDatabase *db,
PRBool *pResult)
{
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, nsnull, 0, PR_FALSE, pResult);
}
nsresult nsMsgSearchOfflineMail::ConstructExpressionTree(nsIMsgDBHdr *msgToMatch,
nsISupportsArray * termList,
PRUint32 &aStartPosInList,
const char *defaultCharset,
nsIMsgSearchScopeTerm * scope,
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
PRBool Filtering,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult)
{
PRBool result;
NS_ENSURE_ARG_POINTER(pResult);
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, nsnull, 0, PR_FALSE, aExpressionTree, pResult);
}
*pResult = PR_FALSE;
nsresult nsMsgSearchOfflineMail::ConstructExpressionTree(nsISupportsArray * termList,
PRUint32 termCount,
PRUint32 &aStartPosInList,
nsMsgSearchBoolExpression ** aExpressionTree)
{
nsMsgSearchBoolExpression * finalExpression = *aExpressionTree;
// Don't even bother to look at expunged messages awaiting compression
PRUint32 msgFlags;
msgToMatch->GetFlags(&msgFlags);
if (msgFlags & MSG_FLAG_EXPUNGED)
result = PR_FALSE;
if (!finalExpression)
finalExpression = new nsMsgSearchBoolExpression();
PRUint32 count;
termList->Count(&count);
nsMsgSearchBoolExpression * finalExpression = new nsMsgSearchBoolExpression();
while (aStartPosInList < count)
while (aStartPosInList < termCount)
{
nsCOMPtr<nsIMsgSearchTerm> pTerm;
termList->QueryElementAt(aStartPosInList, NS_GET_IID(nsIMsgSearchTerm), (void **)getter_AddRefs(pTerm));
NS_ASSERTION (msgToMatch, "couldn't get term to match");
NS_ASSERTION (pTerm, "couldn't get term to match");
PRBool beginsGrouping;
PRBool endsGrouping;
@ -412,12 +390,8 @@ nsresult nsMsgSearchOfflineMail::ConstructExpressionTree(nsIMsgDBHdr *msgToMatch
{
//temporarily turn off the grouping for our recursive call
pTerm->SetBeginsGrouping(PR_FALSE);
// recursively process this inner expression
nsMsgSearchBoolExpression * innerExpression = new nsMsgSearchBoolExpression();
ConstructExpressionTree(msgToMatch, termList, aStartPosInList, defaultCharset, scope, db, headers,
headerSize, Filtering, &innerExpression, &result);
// the first search term in the grouping is the one that holds the operator for how this search term
// should be joined with the expressions to it's left.
PRBool booleanAnd;
@ -426,29 +400,25 @@ nsresult nsMsgSearchOfflineMail::ConstructExpressionTree(nsIMsgDBHdr *msgToMatch
// now add this expression tree to our overall expression tree...
finalExpression = nsMsgSearchBoolExpression::AddExpressionTree(finalExpression, innerExpression, booleanAnd);
// recursively process this inner expression
ConstructExpressionTree(termList, termCount, aStartPosInList,
&finalExpression->m_rightChild);
// undo our damage
pTerm->SetBeginsGrouping(PR_TRUE);
}
else
{
ProcessSearchTerm(msgToMatch, pTerm, defaultCharset, scope, db, headers, headerSize, Filtering, &result);
finalExpression = nsMsgSearchBoolExpression::AddSearchTerm(finalExpression, pTerm, result); // added the term and its value to the expression tree
finalExpression = nsMsgSearchBoolExpression::AddSearchTerm(finalExpression, pTerm, nsnull); // add the term to the expression tree
if (endsGrouping)
{
// okay, this term marks the end of a grouping...kick out of this function.
*pResult = result;
*aExpressionTree = finalExpression;
return NS_OK;
}
break;
}
aStartPosInList++;
} // while we still have terms to process in this group
*pResult = PR_TRUE;
*aExpressionTree = finalExpression;
return NS_OK;
@ -619,17 +589,35 @@ nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch,
const char * headers,
PRUint32 headerSize,
PRBool Filtering,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult)
{
nsMsgSearchBoolExpression * expressionTree = nsnull;
NS_ENSURE_ARG(aExpressionTree);
nsresult err;
// Don't even bother to look at expunged messages awaiting compression
PRUint32 msgFlags;
msgToMatch->GetFlags(&msgFlags);
if (msgFlags & MSG_FLAG_EXPUNGED)
{
*pResult = PR_FALSE;
return NS_OK;
}
if (!*aExpressionTree)
{
PRUint32 initialPos = 0;
nsresult err = ConstructExpressionTree(msgToMatch, termList, initialPos, defaultCharset, scope, db, headers, headerSize,
Filtering, &expressionTree, pResult);
PRUint32 count;
termList->Count(&count);
err = ConstructExpressionTree(termList, count, initialPos, aExpressionTree);
if (NS_FAILED(err))
return err;
}
// evaluate the expression tree and return the result
if (NS_SUCCEEDED(err) && expressionTree)
*pResult = expressionTree->OfflineEvaluate();
delete expressionTree;
if (NS_SUCCEEDED(err) && *aExpressionTree)
*pResult = (*aExpressionTree)->OfflineEvaluate(msgToMatch,
defaultCharset, scope, db, headers, headerSize, Filtering);
return err;
}
@ -642,6 +630,7 @@ nsresult nsMsgSearchOfflineMail::Search (PRBool *aDone)
NS_ENSURE_ARG(aDone);
nsresult dbErr = NS_OK;
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
nsMsgSearchBoolExpression *expressionTree = nsnull;
const PRUint32 kTimeSliceInMS = 200;
@ -678,7 +667,7 @@ nsresult nsMsgSearchOfflineMail::Search (PRBool *aDone)
GetSearchCharsets(getter_Copies(nullCharset), getter_Copies(folderCharset));
NS_ConvertUCS2toUTF8 charset(folderCharset);
// Is this message a hit?
err = MatchTermsForSearch (msgDBHdr, m_searchTerms, charset.get(), m_scope, m_db, &match);
err = MatchTermsForSearch (msgDBHdr, m_searchTerms, charset.get(), m_scope, m_db, &expressionTree, &match);
// Add search hits to the results list
if (NS_SUCCEEDED(err) && match)
{
@ -696,6 +685,8 @@ nsresult nsMsgSearchOfflineMail::Search (PRBool *aDone)
else
*aDone = PR_TRUE; // we couldn't open up the DB. This is an unrecoverable error so mark the scope as done.
delete expressionTree;
// in the past an error here would cause an "infinite" search because the url would continue to run...
// i.e. if we couldn't open the database, it returns an error code but the caller of this function says, oh,
// we did not finish so continue...what we really want is to treat this current scope as done

Просмотреть файл

@ -73,39 +73,19 @@ public:
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult);
static nsresult MatchTermsForSearch(nsIMsgDBHdr * msgTomatch,
nsISupportsArray * termList,
const char *defaultCharset,
nsIMsgSearchScopeTerm *scope,
nsIMsgDatabase *db, PRBool *pResult);
virtual nsresult OpenSummaryFile ();
protected:
static nsresult MatchTerms(nsIMsgDBHdr *msgToMatch,
nsISupportsArray *termList,
const char *defaultCharset,
nsIMsgSearchScopeTerm *scope,
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
PRBool ForFilters,
PRBool *pResult);
static nsresult ConstructExpressionTree(nsIMsgDBHdr *msgToMatch,
nsISupportsArray * termList,
PRUint32 &aStartPosInList,
const char *defaultCharset,
nsIMsgSearchScopeTerm * scope,
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
PRBool Filtering,
nsIMsgDatabase *db,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult);
virtual nsresult OpenSummaryFile ();
static nsresult ProcessSearchTerm(nsIMsgDBHdr *msgToMatch,
nsIMsgSearchTerm * aTerm,
const char *defaultCharset,
@ -115,6 +95,23 @@ protected:
PRUint32 headerSize,
PRBool Filtering,
PRBool *pResult);
protected:
static nsresult MatchTerms(nsIMsgDBHdr *msgToMatch,
nsISupportsArray *termList,
const char *defaultCharset,
nsIMsgSearchScopeTerm *scope,
nsIMsgDatabase * db,
const char * headers,
PRUint32 headerSize,
PRBool ForFilters,
nsMsgSearchBoolExpression ** aExpressionTree,
PRBool *pResult);
static nsresult ConstructExpressionTree(nsISupportsArray * termList,
PRUint32 termCount,
PRUint32 &aStartPosInList,
nsMsgSearchBoolExpression ** aExpressionTree);
nsCOMPtr <nsIMsgDatabase> m_db;
nsCOMPtr<nsISimpleEnumerator> m_listContext;
void CleanUpScope();

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -786,7 +787,7 @@ nsresult nsMsgSearchAdapter::EncodeImap (char **ppOutEncoding, nsISupportsArray
err = EncodeImapTerm (pTerm, reallyDredd, srcCharset, destCharset, &termEncoding);
if (NS_SUCCEEDED(err) && nsnull != termEncoding)
{
expression = nsMsgSearchBoolExpression::AddSearchTermWithEncoding(expression, pTerm, termEncoding);
expression = nsMsgSearchBoolExpression::AddSearchTerm(expression, pTerm, termEncoding);
delete [] termEncoding;
}
}

Просмотреть файл

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Howard Chu <hyc@symas.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -59,6 +60,7 @@ nsMsgSearchSession::nsMsgSearchSession()
m_idxRunningScope = 0;
m_urlQueueIndex = 0;
m_handlingError = PR_FALSE;
m_expressionTree = nsnull;
m_searchPaused = PR_FALSE;
NS_NewISupportsArray(getter_AddRefs(m_termList));
}
@ -66,6 +68,7 @@ nsMsgSearchSession::nsMsgSearchSession()
nsMsgSearchSession::~nsMsgSearchSession()
{
InterruptSearch();
delete m_expressionTree;
DestroyResultList ();
DestroyScopeList ();
DestroyTermList ();
@ -90,6 +93,8 @@ nsMsgSearchSession::AddSearchTerm(nsMsgSearchAttribValue attrib,
if (nsnull == pTerm)
return NS_ERROR_OUT_OF_MEMORY;
m_termList->AppendElement (pTerm);
// force the expression tree to rebuild whenever we change the terms
delete m_expressionTree;
return NS_OK;
}
@ -98,6 +103,7 @@ nsMsgSearchSession::AppendTerm(nsIMsgSearchTerm *aTerm)
{
NS_ENSURE_ARG_POINTER(aTerm);
NS_ENSURE_TRUE(m_termList, NS_ERROR_NOT_INITIALIZED);
delete m_expressionTree;
return m_termList->AppendElement(aTerm);
}
@ -641,6 +647,7 @@ void nsMsgSearchSession::DestroyScopeList()
void nsMsgSearchSession::DestroyTermList ()
{
delete m_expressionTree;
m_termList->Clear();
}
@ -746,7 +753,7 @@ nsMsgSearchSession::MatchHdr(nsIMsgDBHdr *aMsgHdr, nsIMsgDatabase *aDatabase, PR
nsXPIDLString nullCharset, folderCharset;
scope->m_adapter->GetSearchCharsets(getter_Copies(nullCharset), getter_Copies(folderCharset));
NS_ConvertUCS2toUTF8 charset(folderCharset.get());
nsMsgSearchOfflineMail::MatchTermsForSearch(aMsgHdr, m_termList, charset.get(), scope, aDatabase, aResult);
nsMsgSearchOfflineMail::MatchTermsForSearch(aMsgHdr, m_termList, charset.get(), scope, aDatabase, &m_expressionTree, aResult);
}
}
return NS_OK;

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsWeakReference.h"
class nsMsgSearchAdapter;
class nsMsgSearchBoolExpression;
class nsMsgSearchSession : public nsIMsgSearchSession, public nsIUrlListener, public nsSupportsWeakReference
{
@ -103,6 +104,7 @@ protected:
nsCStringArray m_urlQueue;
nsCOMPtr <nsITimer> m_backgroundTimer;
PRBool m_searchPaused;
nsMsgSearchBoolExpression *m_expressionTree;
};
#endif