Back to index

lightning-sunbird  0.9+nobinonly
nsLoggingSink.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsIAtom.h"
00038 #include "nsLoggingSink.h"
00039 #include "nsHTMLTags.h"
00040 #include "nsString.h"
00041 #include "nsReadableUtils.h"
00042 #include "prprf.h"
00043 
00044 
00045 static NS_DEFINE_IID(kIContentSinkIID, NS_ICONTENT_SINK_IID);
00046 static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
00047 static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID);
00048 static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
00049 
00050 // list of tags that have skipped content
00051 static const char gSkippedContentTags[] = {
00052   eHTMLTag_style,
00053   eHTMLTag_script,
00054   eHTMLTag_server,
00055   eHTMLTag_title,
00056   0
00057 };
00058 
00059 
00060 nsresult
00061 NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
00062 {
00063   NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
00064   if (nsnull == aInstancePtrResult) {
00065     return NS_ERROR_NULL_POINTER;
00066   }
00067   nsLoggingSink* it = new nsLoggingSink();
00068   if (nsnull == it) {
00069     return NS_ERROR_OUT_OF_MEMORY;
00070   }
00071   return it->QueryInterface(kIContentSinkIID, (void**) aInstancePtrResult);
00072 }
00073 
00074 nsLoggingSink::nsLoggingSink() {
00075   mOutput = 0;
00076        mLevel=-1;
00077   mSink=0;
00078   mParser=0;
00079 }
00080 
00081 nsLoggingSink::~nsLoggingSink() { 
00082   mSink=0;
00083   if(mOutput && mAutoDeleteOutput) {
00084     delete mOutput;
00085   }
00086   mOutput=0;
00087 }
00088 
00089 NS_IMPL_ADDREF(nsLoggingSink)
00090 NS_IMPL_RELEASE(nsLoggingSink)
00091 
00092 nsresult
00093 nsLoggingSink::QueryInterface(const nsIID& aIID, void** aInstancePtr)
00094 {
00095   NS_PRECONDITION(nsnull != aInstancePtr, "null ptr");
00096   if (nsnull == aInstancePtr) {                                            
00097     return NS_ERROR_NULL_POINTER;                                        
00098   }                                                                      
00099   if (aIID.Equals(kISupportsIID)) {
00100     nsISupports* tmp = this;
00101     *aInstancePtr = (void*) tmp;
00102   }
00103   else if (aIID.Equals(kIContentSinkIID)) {
00104     nsIContentSink* tmp = this;
00105     *aInstancePtr = (void*) tmp;
00106   }
00107   else if (aIID.Equals(kIHTMLContentSinkIID)) {
00108     nsIHTMLContentSink* tmp = this;
00109     *aInstancePtr = (void*) tmp;
00110   }
00111   else if (aIID.Equals(kILoggingSinkIID)) {
00112     nsILoggingSink* tmp = this;
00113     *aInstancePtr = (void*) tmp;
00114   }
00115   else {
00116     *aInstancePtr = nsnull;
00117     return NS_NOINTERFACE;
00118   }
00119   NS_ADDREF(this);
00120   return NS_OK;
00121 }
00122 
00123 NS_IMETHODIMP
00124 nsLoggingSink::SetOutputStream(PRFileDesc *aStream,PRBool autoDeleteOutput) {
00125   mOutput = aStream;
00126   mAutoDeleteOutput=autoDeleteOutput;
00127   return NS_OK;
00128 }
00129 
00130 static
00131 void WriteTabs(PRFileDesc * out,int aTabCount) {
00132   int tabs;
00133   for(tabs=0;tabs<aTabCount;++tabs)
00134     PR_fprintf(out, "  ");
00135 }
00136 
00137 
00138 NS_IMETHODIMP
00139 nsLoggingSink::WillBuildModel() {
00140   
00141   WriteTabs(mOutput,++mLevel);
00142   PR_fprintf(mOutput, "<begin>\n");
00143   
00144   //proxy the call to the real sink if you have one.
00145   if(mSink) {
00146     mSink->WillBuildModel();
00147   }
00148 
00149   return NS_OK;
00150 }
00151 
00152 NS_IMETHODIMP
00153 nsLoggingSink::DidBuildModel() {
00154   
00155   WriteTabs(mOutput,--mLevel);
00156   PR_fprintf(mOutput, "</begin>\n");
00157 
00158   //proxy the call to the real sink if you have one.
00159   nsresult theResult=NS_OK;
00160   if(mSink) {
00161     theResult=mSink->DidBuildModel();
00162   }
00163 
00164   return theResult;
00165 }
00166 
00167 NS_IMETHODIMP
00168 nsLoggingSink::WillInterrupt() {
00169   nsresult theResult=NS_OK;
00170 
00171   //proxy the call to the real sink if you have one.
00172   if(mSink) {
00173     theResult=mSink->WillInterrupt();
00174   }
00175   
00176   return theResult;
00177 }
00178 
00179 NS_IMETHODIMP
00180 nsLoggingSink::WillResume() {
00181   nsresult theResult=NS_OK;
00182 
00183   //proxy the call to the real sink if you have one.
00184   if(mSink) {
00185     theResult=mSink->WillResume();
00186   }
00187   
00188   return theResult;
00189 }
00190 
00191 NS_IMETHODIMP
00192 nsLoggingSink::SetParser(nsIParser* aParser)  {
00193   nsresult theResult=NS_OK;
00194 
00195   //proxy the call to the real sink if you have one.
00196   if(mSink) {
00197     theResult=mSink->SetParser(aParser);
00198   }
00199   
00200   NS_IF_RELEASE(mParser);
00201   
00202   mParser = aParser;
00203   
00204   NS_IF_ADDREF(mParser);
00205 
00206   return theResult;
00207 }
00208 
00209 NS_IMETHODIMP
00210 nsLoggingSink::OpenContainer(const nsIParserNode& aNode) {
00211 
00212   OpenNode("container", aNode); //do the real logging work...
00213 
00214   nsresult theResult=NS_OK;
00215 
00216   //then proxy the call to the real sink if you have one.
00217   if(mSink) {
00218     theResult=mSink->OpenContainer(aNode);
00219   }
00220   
00221   return theResult;
00222 
00223 }
00224 
00225 NS_IMETHODIMP
00226 nsLoggingSink::CloseContainer(const nsHTMLTag aTag) {
00227 
00228   nsresult theResult=NS_OK;
00229 
00230   nsHTMLTag nodeType = nsHTMLTag(aTag);
00231   if ((nodeType >= eHTMLTag_unknown) &&
00232       (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
00233     const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
00234     theResult = CloseNode(NS_ConvertUCS2toUTF8(tag).get());
00235   }
00236   else theResult= CloseNode("???");
00237 
00238   //then proxy the call to the real sink if you have one.
00239   if(mSink) {
00240     theResult=mSink->CloseContainer(aTag);
00241   }
00242   
00243   return theResult;
00244 
00245 }
00246 
00247 NS_IMETHODIMP
00248 nsLoggingSink::AddHeadContent(const nsIParserNode& aNode) {
00249   eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
00250 
00251   if (type == eHTMLTag_title) {
00252     nsCOMPtr<nsIDTD> dtd;
00253     mParser->GetDTD(getter_AddRefs(dtd));
00254     NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
00255     
00256     nsString theString;
00257     PRInt32 lineNo = 0;
00258 
00259     dtd->CollectSkippedContent(type, theString, lineNo);
00260     SetTitle(theString);
00261   }
00262   else {
00263     LeafNode(aNode);
00264   }
00265 
00266   nsresult theResult=NS_OK;
00267 
00268   //then proxy the call to the real sink if you have one.
00269   if(mSink) {
00270     theResult=mSink->AddHeadContent(aNode);
00271   }
00272   
00273   return theResult;
00274 
00275 }
00276 
00277 NS_IMETHODIMP
00278 nsLoggingSink::AddLeaf(const nsIParserNode& aNode) {
00279   LeafNode(aNode);
00280 
00281   nsresult theResult=NS_OK;
00282 
00283   //then proxy the call to the real sink if you have one.
00284   if(mSink) {
00285     theResult=mSink->AddLeaf(aNode);
00286   }
00287   
00288   return theResult;
00289 
00290 } 
00291 
00301 NS_IMETHODIMP
00302 nsLoggingSink::AddProcessingInstruction(const nsIParserNode& aNode){
00303 
00304 #ifdef VERBOSE_DEBUG
00305   DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
00306 #endif
00307 
00308   nsresult theResult=NS_OK;
00309 
00310   //then proxy the call to the real sink if you have one.
00311   if(mSink) {
00312     theResult=mSink->AddProcessingInstruction(aNode);
00313   }
00314   
00315   return theResult;
00316 }
00317 
00323 NS_IMETHODIMP
00324 nsLoggingSink::AddDocTypeDecl(const nsIParserNode& aNode) {
00325 
00326 #ifdef VERBOSE_DEBUG
00327   DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
00328 #endif
00329 
00330   nsresult theResult=NS_OK;
00331 
00332   //then proxy the call to the real sink if you have one.
00333   if(mSink) {
00334     theResult=mSink->AddDocTypeDecl(aNode);
00335   }
00336   
00337   return theResult;
00338 
00339 }
00340 
00350 NS_IMETHODIMP
00351 nsLoggingSink::AddComment(const nsIParserNode& aNode){
00352 
00353 #ifdef VERBOSE_DEBUG
00354   DebugDump("<",aNode.GetText(),(mNodeStackPos)*2);
00355 #endif
00356 
00357   nsresult theResult=NS_OK;
00358 
00359   //then proxy the call to the real sink if you have one.
00360   if(mSink) {
00361     theResult=mSink->AddComment(aNode);
00362   }
00363   
00364   return theResult;
00365 
00366 }
00367 
00368 
00369 NS_IMETHODIMP
00370 nsLoggingSink::SetTitle(const nsString& aValue) {
00371    
00372   char* tmp = nsnull;
00373   GetNewCString(aValue, &tmp);
00374        WriteTabs(mOutput,++mLevel);
00375   if(tmp) {
00376     PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp);
00377     nsMemory::Free(tmp);
00378   }
00379   --mLevel;
00380   
00381   nsresult theResult=NS_OK;
00382 
00383   //then proxy the call to the real sink if you have one.
00384   if(mSink) {
00385     theResult=mSink->SetTitle(aValue);
00386   }
00387   
00388   return theResult;
00389 
00390 }
00391 
00392 
00393 NS_IMETHODIMP
00394 nsLoggingSink::OpenHTML(const nsIParserNode& aNode) {
00395   OpenNode("html", aNode);
00396 
00397   nsresult theResult=NS_OK;
00398 
00399   //then proxy the call to the real sink if you have one.
00400   if(mSink) {
00401     theResult=mSink->OpenHTML(aNode);
00402   }
00403   
00404   return theResult;
00405 
00406 }
00407 
00408 NS_IMETHODIMP
00409 nsLoggingSink::CloseHTML() {
00410   CloseNode("html");
00411 
00412   nsresult theResult=NS_OK;
00413 
00414   //then proxy the call to the real sink if you have one.
00415   if(mSink) {
00416     theResult=mSink->CloseHTML();
00417   }
00418   
00419   return theResult;
00420 
00421 }
00422 
00423 NS_IMETHODIMP
00424 nsLoggingSink::OpenHead(const nsIParserNode& aNode) {
00425   OpenNode("head", aNode);
00426 
00427   nsresult theResult=NS_OK;
00428 
00429   //then proxy the call to the real sink if you have one.
00430   if(mSink) {
00431     theResult=mSink->OpenHead(aNode);
00432   }
00433   
00434   return theResult;
00435 }
00436 
00437 NS_IMETHODIMP
00438 nsLoggingSink::CloseHead() {
00439   CloseNode("head");
00440 
00441   nsresult theResult=NS_OK;
00442 
00443   //then proxy the call to the real sink if you have one.
00444   if(mSink) {
00445     theResult=mSink->CloseHead();
00446   }
00447   
00448   return theResult;
00449 }
00450 
00451 NS_IMETHODIMP
00452 nsLoggingSink::OpenBody(const nsIParserNode& aNode) {
00453   OpenNode("body", aNode);
00454 
00455   nsresult theResult=NS_OK;
00456 
00457   //then proxy the call to the real sink if you have one.
00458   if(mSink) {
00459     theResult=mSink->OpenBody(aNode);
00460   }
00461   
00462   return theResult;
00463 }
00464 
00465 NS_IMETHODIMP
00466 nsLoggingSink::CloseBody() {
00467   CloseNode("body");
00468 
00469   nsresult theResult=NS_OK;
00470 
00471   //then proxy the call to the real sink if you have one.
00472   if(mSink) {
00473     theResult=mSink->CloseBody();
00474   }
00475   
00476   return theResult;
00477 }
00478 
00479 NS_IMETHODIMP
00480 nsLoggingSink::OpenForm(const nsIParserNode& aNode) {
00481   OpenNode("form", aNode);
00482 
00483   nsresult theResult=NS_OK;
00484 
00485   //then proxy the call to the real sink if you have one.
00486   if(mSink) {
00487     theResult=mSink->OpenForm(aNode);
00488   }
00489   
00490   return theResult;
00491 }
00492 
00493 NS_IMETHODIMP
00494 nsLoggingSink::CloseForm() {
00495   CloseNode("form");
00496 
00497   nsresult theResult=NS_OK;
00498 
00499   //then proxy the call to the real sink if you have one.
00500   if(mSink) {
00501     theResult=mSink->CloseForm();
00502   }
00503   
00504   return theResult;
00505 }
00506 
00507 NS_IMETHODIMP
00508 nsLoggingSink::OpenMap(const nsIParserNode& aNode) {
00509   OpenNode("map", aNode);
00510 
00511   nsresult theResult=NS_OK;
00512 
00513   //then proxy the call to the real sink if you have one.
00514   if(mSink) {
00515     theResult=mSink->OpenMap(aNode);
00516   }
00517   
00518   return theResult;
00519 }
00520 
00521 NS_IMETHODIMP
00522 nsLoggingSink::CloseMap() {
00523   CloseNode("map");
00524 
00525   nsresult theResult=NS_OK;
00526 
00527   //then proxy the call to the real sink if you have one.
00528   if(mSink) {
00529     theResult=mSink->CloseMap();
00530   }
00531   
00532   return theResult;
00533 }
00534 
00535 NS_IMETHODIMP
00536 nsLoggingSink::OpenFrameset(const nsIParserNode& aNode) {
00537   OpenNode("frameset", aNode);
00538 
00539   nsresult theResult=NS_OK;
00540 
00541   //then proxy the call to the real sink if you have one.
00542   if(mSink) {
00543     theResult=mSink->OpenFrameset(aNode);
00544   }
00545   
00546   return theResult;
00547 }
00548 
00549 NS_IMETHODIMP
00550 nsLoggingSink::CloseFrameset() {
00551   CloseNode("frameset");
00552 
00553   nsresult theResult=NS_OK;
00554 
00555   //then proxy the call to the real sink if you have one.
00556   if(mSink) {
00557     theResult=mSink->CloseFrameset();
00558   }
00559   
00560   return theResult;
00561 }
00562 
00563 
00564 nsresult
00565 nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) {
00566        WriteTabs(mOutput,++mLevel);
00567 
00568   PR_fprintf(mOutput,"<open container=");
00569 
00570   nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
00571   if ((nodeType >= eHTMLTag_unknown) &&
00572       (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
00573     const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
00574     PR_fprintf(mOutput, "\"%s\"", NS_ConvertUCS2toUTF8(tag).get());
00575   }
00576   else {
00577     char* text = nsnull;
00578     GetNewCString(aNode.GetText(), &text);
00579     if(text) {
00580       PR_fprintf(mOutput, "\"%s\"", text);
00581       nsMemory::Free(text);
00582     }
00583   }
00584 
00585   if (WillWriteAttributes(aNode)) {
00586     PR_fprintf(mOutput, ">\n");
00587     WriteAttributes(aNode);
00588     PR_fprintf(mOutput, "</open>\n");
00589   }
00590   else {
00591     PR_fprintf(mOutput, ">\n");
00592   }
00593 
00594   return NS_OK;
00595 }
00596 
00597 nsresult
00598 nsLoggingSink::CloseNode(const char* aKind) {
00599        WriteTabs(mOutput,mLevel--);
00600   PR_fprintf(mOutput, "<close container=\"%s\">\n", aKind);
00601   return NS_OK;
00602 }
00603 
00604 
00605 nsresult
00606 nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) {
00607 
00608   WriteTabs(mOutput,1+mLevel);
00609   nsAutoString tmp;
00610   PRInt32 ac = aNode.GetAttributeCount();
00611   for (PRInt32 i = 0; i < ac; ++i) {
00612     char* key=nsnull;
00613     char* value=nsnull;
00614     const nsAString& k = aNode.GetKeyAt(i);
00615     const nsAString& v = aNode.GetValueAt(i);
00616 
00617     GetNewCString(k, &key);
00618     if(key) {
00619       PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key);
00620       nsMemory::Free(key);
00621     }
00622  
00623     tmp.Truncate();
00624     tmp.Append(v);
00625     if(!tmp.IsEmpty()) {
00626       PRUnichar first = tmp.First();
00627       if ((first == '"') || (first == '\'')) {
00628         if (tmp.Last() == first) {
00629           tmp.Cut(0, 1);
00630           PRInt32 pos = tmp.Length() - 1;
00631           if (pos >= 0) {
00632             tmp.Cut(pos, 1);
00633           }
00634         } else {
00635           // Mismatched quotes - leave them in
00636         }
00637       }
00638       GetNewCString(tmp, &value);
00639 
00640       if(value) {
00641         PR_fprintf(mOutput, "%s\"/>\n", value);
00642         WriteTabs(mOutput,1+mLevel);
00643         nsMemory::Free(value);
00644       }
00645     }
00646   }
00647 
00648   if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
00649     nsCOMPtr<nsIDTD> dtd;
00650     mParser->GetDTD(getter_AddRefs(dtd));
00651     NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
00652     
00653     nsString theString;
00654     PRInt32 lineNo = 0;
00655 
00656     dtd->CollectSkippedContent(aNode.GetNodeType(), theString, lineNo);
00657     char* content = nsnull;
00658     GetNewCString(theString, &content);
00659     if(content) {
00660       PR_fprintf(mOutput, " <content value=\"");
00661       PR_fprintf(mOutput, "%s\"/>\n", content) ;
00662       nsMemory::Free(content);
00663     }
00664   }
00665   WriteTabs(mOutput,1+mLevel);
00666   return NS_OK;
00667 }
00668 
00669 PRBool
00670 nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode)
00671 {
00672   PRInt32 ac = aNode.GetAttributeCount();
00673   if (0 != ac) {
00674     return PR_TRUE;
00675   }
00676   if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
00677     nsCOMPtr<nsIDTD> dtd;
00678     mParser->GetDTD(getter_AddRefs(dtd));
00679     NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
00680     
00681     nsString content;
00682     PRInt32 lineNo = 0;
00683 
00684     dtd->CollectSkippedContent(aNode.GetNodeType(), content, lineNo);
00685     if (!content.IsEmpty()) {
00686       return PR_TRUE;
00687     }
00688   }
00689   return PR_FALSE;
00690 }
00691 
00692 nsresult
00693 nsLoggingSink::LeafNode(const nsIParserNode& aNode)
00694 {
00695        WriteTabs(mOutput,1+mLevel);
00696        nsHTMLTag                          nodeType  = nsHTMLTag(aNode.GetNodeType());
00697 
00698   if ((nodeType >= eHTMLTag_unknown) &&
00699       (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
00700     const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
00701 
00702               if(tag)
00703       PR_fprintf(mOutput, "<leaf tag=\"%s\"", NS_ConvertUCS2toUTF8(tag).get());
00704     else PR_fprintf(mOutput, "<leaf tag=\"???\"");
00705 
00706     if (WillWriteAttributes(aNode)) {
00707                      PR_fprintf(mOutput, ">\n");
00708       WriteAttributes(aNode);
00709                      PR_fprintf(mOutput, "</leaf>\n");
00710     }
00711     else {
00712                      PR_fprintf(mOutput, "/>\n");
00713     }
00714   }
00715   else {
00716     PRInt32 pos;
00717     nsAutoString tmp;
00718     char* str = nsnull;
00719     switch (nodeType) {
00720                      case eHTMLTag_whitespace:
00721                      case eHTMLTag_text:
00722         GetNewCString(aNode.GetText(), &str);
00723         if(str) {
00724           PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str);
00725           nsMemory::Free(str);
00726         }
00727                             break;
00728 
00729                      case eHTMLTag_newline:
00730                             PR_fprintf(mOutput, "<newline/>\n");
00731                             break;
00732 
00733                      case eHTMLTag_entity:
00734                             tmp.Append(aNode.GetText());
00735                             tmp.Cut(0, 1);
00736                             pos = tmp.Length() - 1;
00737                             if (pos >= 0) {
00738                                    tmp.Cut(pos, 1);
00739                             }
00740                             PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get());
00741                             break;
00742 
00743                      default:
00744                             NS_NOTREACHED("unsupported leaf node type");
00745               }//switch
00746   }
00747   return NS_OK;
00748 }
00749 
00750 nsresult 
00751 nsLoggingSink::QuoteText(const nsAString& aValue, nsString& aResult) {
00752   aResult.Truncate();
00753     /*
00754       if you're stepping through the string anyway, why not use iterators instead of forcing the string to copy?
00755      */
00756   const nsPromiseFlatString& flat = PromiseFlatString(aValue);
00757   const PRUnichar* cp = flat.get();
00758   const PRUnichar* end = cp + aValue.Length();
00759   while (cp < end) {
00760     PRUnichar ch = *cp++;
00761     if (ch == '"') {
00762       aResult.AppendLiteral("&quot;");
00763     }
00764     else if (ch == '&') {
00765       aResult.AppendLiteral("&amp;");
00766     }
00767     else if ((ch < 32) || (ch >= 127)) {
00768       aResult.AppendLiteral("&#");
00769       aResult.AppendInt(PRInt32(ch), 10);
00770       aResult.Append(PRUnichar(';'));
00771     }
00772     else {
00773       aResult.Append(ch);
00774     }
00775   }
00776   return NS_OK;
00777 }
00778 
00787 nsresult
00788 nsLoggingSink::GetNewCString(const nsAString& aValue, char** aResult)
00789 {
00790   nsresult result=NS_OK;
00791   nsAutoString temp;
00792   result=QuoteText(aValue,temp);
00793   if(NS_SUCCEEDED(result)) {
00794     *aResult = temp.IsEmpty() ? nsnull : ToNewCString(temp);
00795   }
00796   return result;
00797 }
00798 
00806 NS_IMETHODIMP
00807 nsLoggingSink::BeginContext(PRInt32 aPosition) 
00808 {
00809   return NS_OK;
00810 }
00811 
00819 NS_IMETHODIMP
00820 nsLoggingSink::EndContext(PRInt32 aPosition)
00821 {
00822   return NS_OK;
00823 }