LCOV - code coverage report
Current view: top level - dom/xslt/xslt - txXSLTPatterns.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 268 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 46 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/FloatingPoint.h"
       7             : 
       8             : #include "nsReadableUtils.h"
       9             : #include "txExecutionState.h"
      10             : #include "txXSLTPatterns.h"
      11             : #include "txNodeSetContext.h"
      12             : #include "txForwardContext.h"
      13             : #include "txXMLUtils.h"
      14             : #include "txXSLTFunctions.h"
      15             : #include "nsWhitespaceTokenizer.h"
      16             : #include "nsIContent.h"
      17             : 
      18             : /*
      19             :  * Returns the default priority of this Pattern.
      20             :  * UnionPatterns don't like this.
      21             :  * This should be called on the simple patterns.
      22             :  */
      23           0 : double txUnionPattern::getDefaultPriority()
      24             : {
      25           0 :     NS_ERROR("Don't call getDefaultPriority on txUnionPattern");
      26           0 :     return mozilla::UnspecifiedNaN<double>();
      27             : }
      28             : 
      29             : /*
      30             :  * Determines whether this Pattern matches the given node within
      31             :  * the given context
      32             :  * This should be called on the simple patterns for xsl:template,
      33             :  * but is fine for xsl:key and xsl:number
      34             :  */
      35             : nsresult
      36           0 : txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
      37             :                         bool& aMatched)
      38             : {
      39           0 :     uint32_t i, len = mLocPathPatterns.Length();
      40           0 :     for (i = 0; i < len; ++i) {
      41           0 :         nsresult rv = mLocPathPatterns[i]->matches(aNode, aContext, aMatched);
      42           0 :         NS_ENSURE_SUCCESS(rv, rv);
      43             : 
      44           0 :         if (aMatched) {
      45           0 :             aMatched = true;
      46             : 
      47           0 :             return NS_OK;
      48             :         }
      49             :     }
      50             : 
      51           0 :     aMatched = false;
      52             : 
      53           0 :     return NS_OK;
      54             : }
      55             : 
      56             : txPattern::Type
      57           0 : txUnionPattern::getType()
      58             : {
      59           0 :   return UNION_PATTERN;
      60             : }
      61             : 
      62           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(txUnionPattern)
      63             : txPattern*
      64           0 : txUnionPattern::getSubPatternAt(uint32_t aPos)
      65             : {
      66           0 :     return mLocPathPatterns.SafeElementAt(aPos);
      67             : }
      68             : 
      69             : void
      70           0 : txUnionPattern::setSubPatternAt(uint32_t aPos, txPattern* aPattern)
      71             : {
      72           0 :     NS_ASSERTION(aPos < mLocPathPatterns.Length(),
      73             :                  "setting bad subexpression index");
      74           0 :     mLocPathPatterns[aPos] = aPattern;
      75           0 : }
      76             : 
      77             : 
      78             : #ifdef TX_TO_STRING
      79             : void
      80           0 : txUnionPattern::toString(nsAString& aDest)
      81             : {
      82             : #ifdef DEBUG
      83           0 :     aDest.AppendLiteral("txUnionPattern{");
      84             : #endif
      85           0 :     for (uint32_t i = 0; i < mLocPathPatterns.Length(); ++i) {
      86           0 :         if (i != 0)
      87           0 :             aDest.AppendLiteral(" | ");
      88           0 :         mLocPathPatterns[i]->toString(aDest);
      89             :     }
      90             : #ifdef DEBUG
      91           0 :     aDest.Append(char16_t('}'));
      92             : #endif
      93           0 : }
      94             : #endif
      95             : 
      96             : 
      97             : /*
      98             :  * LocationPathPattern
      99             :  *
     100             :  * a list of step patterns, can start with id or key
     101             :  * (dealt with by the parser)
     102             :  */
     103             : 
     104           0 : nsresult txLocPathPattern::addStep(txPattern* aPattern, bool isChild)
     105             : {
     106           0 :     Step* step = mSteps.AppendElement();
     107           0 :     if (!step)
     108           0 :         return NS_ERROR_OUT_OF_MEMORY;
     109             : 
     110           0 :     step->pattern = aPattern;
     111           0 :     step->isChild = isChild;
     112             : 
     113           0 :     return NS_OK;
     114             : }
     115             : 
     116             : nsresult
     117           0 : txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
     118             :                           bool& aMatched)
     119             : {
     120           0 :     NS_ASSERTION(mSteps.Length() > 1, "Internal error");
     121             : 
     122             :     /*
     123             :      * The idea is to split up a path into blocks separated by descendant
     124             :      * operators. For example "foo/bar//baz/bop//ying/yang" is split up into
     125             :      * three blocks. The "ying/yang" block is handled by the first while-loop
     126             :      * and the "foo/bar" and "baz/bop" blocks are handled by the second
     127             :      * while-loop.
     128             :      * A block is considered matched when we find a list of ancestors that
     129             :      * match the block. If there are more than one list of ancestors that
     130             :      * match a block we only need to find the one furthermost down in the
     131             :      * tree.
     132             :      */
     133             : 
     134           0 :     uint32_t pos = mSteps.Length();
     135           0 :     Step* step = &mSteps[--pos];
     136           0 :     nsresult rv = step->pattern->matches(aNode, aContext, aMatched);
     137           0 :     NS_ENSURE_SUCCESS(rv, rv);
     138             : 
     139           0 :     if (!aMatched) {
     140           0 :         return NS_OK;
     141             :     }
     142             : 
     143           0 :     txXPathTreeWalker walker(aNode);
     144           0 :     bool hasParent = walker.moveToParent();
     145             : 
     146           0 :     while (step->isChild) {
     147           0 :         if (!pos) {
     148           0 :             aMatched = true;
     149             : 
     150           0 :             return NS_OK; // all steps matched
     151             :         }
     152             : 
     153           0 :         if (!hasParent) {
     154             :             // no more ancestors
     155           0 :             aMatched = false;
     156             : 
     157           0 :             return NS_OK;
     158             :         }
     159             : 
     160           0 :         step = &mSteps[--pos];
     161           0 :         rv = step->pattern->matches(walker.getCurrentPosition(), aContext,
     162           0 :                                     aMatched);
     163           0 :         NS_ENSURE_SUCCESS(rv, rv);
     164             : 
     165           0 :         if (!aMatched) {
     166             :             // no match
     167           0 :             return NS_OK;
     168             :         }
     169             : 
     170           0 :         hasParent = walker.moveToParent();
     171             :     }
     172             : 
     173             :     // We have at least one // path separator
     174           0 :     txXPathTreeWalker blockWalker(walker);
     175           0 :     uint32_t blockPos = pos;
     176             : 
     177           0 :     while (pos) {
     178           0 :         if (!hasParent) {
     179           0 :             aMatched = false; // There are more steps in the current block
     180             :                               // than ancestors of the tested node
     181           0 :             return NS_OK;
     182             :         }
     183             : 
     184           0 :         step = &mSteps[--pos];
     185             :         bool matched;
     186           0 :         rv = step->pattern->matches(walker.getCurrentPosition(), aContext,
     187           0 :                                     matched);
     188           0 :         NS_ENSURE_SUCCESS(rv, rv);
     189             : 
     190           0 :         if (!matched) {
     191             :             // Didn't match. We restart at beginning of block using a new
     192             :             // start node
     193           0 :             pos = blockPos;
     194           0 :             hasParent = blockWalker.moveToParent();
     195           0 :             walker.moveTo(blockWalker);
     196             :         }
     197             :         else {
     198           0 :             hasParent = walker.moveToParent();
     199           0 :             if (!step->isChild) {
     200             :                 // We've matched an entire block. Set new start pos and start node
     201           0 :                 blockPos = pos;
     202           0 :                 blockWalker.moveTo(walker);
     203             :             }
     204             :         }
     205             :     }
     206             : 
     207           0 :     aMatched = true;
     208             : 
     209           0 :     return NS_OK;
     210             : } // txLocPathPattern::matches
     211             : 
     212           0 : double txLocPathPattern::getDefaultPriority()
     213             : {
     214           0 :     NS_ASSERTION(mSteps.Length() > 1, "Internal error");
     215             : 
     216           0 :     return 0.5;
     217             : }
     218             : 
     219           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(txLocPathPattern)
     220             : txPattern*
     221           0 : txLocPathPattern::getSubPatternAt(uint32_t aPos)
     222             : {
     223           0 :     return aPos < mSteps.Length() ? mSteps[aPos].pattern.get() : nullptr;
     224             : }
     225             : 
     226             : void
     227           0 : txLocPathPattern::setSubPatternAt(uint32_t aPos, txPattern* aPattern)
     228             : {
     229           0 :     NS_ASSERTION(aPos < mSteps.Length(), "setting bad subexpression index");
     230           0 :     Step* step = &mSteps[aPos];
     231           0 :     step->pattern.forget();
     232           0 :     step->pattern = aPattern;
     233           0 : }
     234             : 
     235             : #ifdef TX_TO_STRING
     236             : void
     237           0 : txLocPathPattern::toString(nsAString& aDest)
     238             : {
     239             : #ifdef DEBUG
     240           0 :     aDest.AppendLiteral("txLocPathPattern{");
     241             : #endif
     242           0 :     for (uint32_t i = 0; i < mSteps.Length(); ++i) {
     243           0 :         if (i != 0) {
     244           0 :             if (mSteps[i].isChild)
     245           0 :                 aDest.Append(char16_t('/'));
     246             :             else
     247           0 :                 aDest.AppendLiteral("//");
     248             :         }
     249           0 :         mSteps[i].pattern->toString(aDest);
     250             :     }
     251             : #ifdef DEBUG
     252           0 :     aDest.Append(char16_t('}'));
     253             : #endif
     254           0 : }
     255             : #endif
     256             : 
     257             : /*
     258             :  * txRootPattern
     259             :  *
     260             :  * a txPattern matching the document node, or '/'
     261             :  */
     262             : 
     263             : nsresult
     264           0 : txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
     265             :                        bool& aMatched)
     266             : {
     267           0 :     aMatched = txXPathNodeUtils::isRoot(aNode);
     268             : 
     269           0 :     return NS_OK;
     270             : }
     271             : 
     272           0 : double txRootPattern::getDefaultPriority()
     273             : {
     274           0 :     return 0.5;
     275             : }
     276             : 
     277           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(txRootPattern)
     278           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(txRootPattern)
     279             : 
     280             : #ifdef TX_TO_STRING
     281             : void
     282           0 : txRootPattern::toString(nsAString& aDest)
     283             : {
     284             : #ifdef DEBUG
     285           0 :     aDest.AppendLiteral("txRootPattern{");
     286             : #endif
     287           0 :     if (mSerialize)
     288           0 :         aDest.Append(char16_t('/'));
     289             : #ifdef DEBUG
     290           0 :     aDest.Append(char16_t('}'));
     291             : #endif
     292           0 : }
     293             : #endif
     294             : 
     295             : /*
     296             :  * txIdPattern
     297             :  *
     298             :  * txIdPattern matches if the given node has a ID attribute with one
     299             :  * of the space delimited values.
     300             :  * This looks like the id() function, but may only have LITERALs as
     301             :  * argument.
     302             :  */
     303           0 : txIdPattern::txIdPattern(const nsAString& aString)
     304             : {
     305           0 :     nsWhitespaceTokenizer tokenizer(aString);
     306           0 :     while (tokenizer.hasMoreTokens()) {
     307             :         // this can fail, XXX move to a Init(aString) method
     308           0 :         nsCOMPtr<nsIAtom> atom = NS_Atomize(tokenizer.nextToken());
     309           0 :         mIds.AppendObject(atom);
     310             :     }
     311           0 : }
     312             : 
     313             : nsresult
     314           0 : txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
     315             :                      bool& aMatched)
     316             : {
     317           0 :     if (!txXPathNodeUtils::isElement(aNode)) {
     318           0 :         aMatched = false;
     319             : 
     320           0 :         return NS_OK;
     321             :     }
     322             : 
     323             :     // Get a ID attribute, if there is
     324           0 :     nsIContent* content = txXPathNativeNode::getContent(aNode);
     325           0 :     NS_ASSERTION(content, "a Element without nsIContent");
     326             : 
     327           0 :     nsIAtom* id = content->GetID();
     328           0 :     aMatched = id && mIds.IndexOf(id) > -1;
     329             : 
     330           0 :     return NS_OK;
     331             : }
     332             : 
     333           0 : double txIdPattern::getDefaultPriority()
     334             : {
     335           0 :     return 0.5;
     336             : }
     337             : 
     338           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(txIdPattern)
     339           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(txIdPattern)
     340             : 
     341             : #ifdef TX_TO_STRING
     342             : void
     343           0 : txIdPattern::toString(nsAString& aDest)
     344             : {
     345             : #ifdef DEBUG
     346           0 :     aDest.AppendLiteral("txIdPattern{");
     347             : #endif
     348           0 :     aDest.AppendLiteral("id('");
     349           0 :     uint32_t k, count = mIds.Count() - 1;
     350           0 :     for (k = 0; k < count; ++k) {
     351           0 :         nsAutoString str;
     352           0 :         mIds[k]->ToString(str);
     353           0 :         aDest.Append(str);
     354           0 :         aDest.Append(char16_t(' '));
     355             :     }
     356           0 :     nsAutoString str;
     357           0 :     mIds[count]->ToString(str);
     358           0 :     aDest.Append(str);
     359           0 :     aDest.AppendLiteral("')");
     360             : #ifdef DEBUG
     361           0 :     aDest.Append(char16_t('}'));
     362             : #endif
     363           0 : }
     364             : #endif
     365             : 
     366             : /*
     367             :  * txKeyPattern
     368             :  *
     369             :  * txKeyPattern matches if the given node is in the evalation of
     370             :  * the key() function
     371             :  * This resembles the key() function, but may only have LITERALs as
     372             :  * argument.
     373             :  */
     374             : 
     375             : nsresult
     376           0 : txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
     377             :                       bool& aMatched)
     378             : {
     379           0 :     txExecutionState* es = (txExecutionState*)aContext->getPrivateContext();
     380           0 :     nsAutoPtr<txXPathNode> contextDoc(txXPathNodeUtils::getOwnerDocument(aNode));
     381           0 :     NS_ENSURE_TRUE(contextDoc, NS_ERROR_FAILURE);
     382             : 
     383           0 :     RefPtr<txNodeSet> nodes;
     384           0 :     nsresult rv = es->getKeyNodes(mName, *contextDoc, mValue, true,
     385           0 :                                   getter_AddRefs(nodes));
     386           0 :     NS_ENSURE_SUCCESS(rv, rv);
     387             : 
     388           0 :     aMatched = nodes->contains(aNode);
     389             : 
     390           0 :     return NS_OK;
     391             : }
     392             : 
     393           0 : double txKeyPattern::getDefaultPriority()
     394             : {
     395           0 :     return 0.5;
     396             : }
     397             : 
     398           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(txKeyPattern)
     399           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(txKeyPattern)
     400             : 
     401             : #ifdef TX_TO_STRING
     402             : void
     403           0 : txKeyPattern::toString(nsAString& aDest)
     404             : {
     405             : #ifdef DEBUG
     406           0 :     aDest.AppendLiteral("txKeyPattern{");
     407             : #endif
     408           0 :     aDest.AppendLiteral("key('");
     409           0 :     nsAutoString tmp;
     410           0 :     if (mPrefix) {
     411           0 :         mPrefix->ToString(tmp);
     412           0 :         aDest.Append(tmp);
     413           0 :         aDest.Append(char16_t(':'));
     414             :     }
     415           0 :     mName.mLocalName->ToString(tmp);
     416           0 :     aDest.Append(tmp);
     417           0 :     aDest.AppendLiteral(", ");
     418           0 :     aDest.Append(mValue);
     419           0 :     aDest.AppendLiteral("')");
     420             : #ifdef DEBUG
     421           0 :     aDest.Append(char16_t('}'));
     422             : #endif
     423           0 : }
     424             : #endif
     425             : 
     426             : /*
     427             :  * txStepPattern
     428             :  *
     429             :  * a txPattern to hold the NodeTest and the Predicates of a StepPattern
     430             :  */
     431             : 
     432             : nsresult
     433           0 : txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
     434             :                        bool& aMatched)
     435             : {
     436           0 :     NS_ASSERTION(mNodeTest, "Internal error");
     437             : 
     438           0 :     nsresult rv = mNodeTest->matches(aNode, aContext, aMatched);
     439           0 :     NS_ENSURE_SUCCESS(rv, rv);
     440             : 
     441           0 :     if (!aMatched) {
     442           0 :         return NS_OK;
     443             :     }
     444             : 
     445           0 :     txXPathTreeWalker walker(aNode);
     446           0 :     if ((!mIsAttr &&
     447           0 :          txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) ||
     448           0 :         !walker.moveToParent()) {
     449           0 :         aMatched = false;
     450             : 
     451           0 :         return NS_OK;
     452             :     }
     453             : 
     454           0 :     if (isEmpty()) {
     455           0 :         aMatched = true;
     456             : 
     457           0 :         return NS_OK;
     458             :     }
     459             : 
     460             :     /*
     461             :      * Evaluate Predicates
     462             :      *
     463             :      * Copy all siblings/attributes matching mNodeTest to nodes
     464             :      * Up to the last Predicate do
     465             :      *  Foreach node in nodes
     466             :      *   evaluate Predicate with node as context node
     467             :      *   if the result is a number, check the context position,
     468             :      *    otherwise convert to bool
     469             :      *   if result is true, copy node to newNodes
     470             :      *  if aNode is not member of newNodes, return false
     471             :      *  nodes = newNodes
     472             :      *
     473             :      * For the last Predicate, evaluate Predicate with aNode as
     474             :      *  context node, if the result is a number, check the position,
     475             :      *  otherwise return the result converted to boolean
     476             :      */
     477             : 
     478             :     // Create the context node set for evaluating the predicates
     479           0 :     RefPtr<txNodeSet> nodes;
     480           0 :     rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
     481           0 :     NS_ENSURE_SUCCESS(rv, rv);
     482             : 
     483           0 :     bool hasNext = mIsAttr ? walker.moveToFirstAttribute() :
     484           0 :                                walker.moveToFirstChild();
     485           0 :     while (hasNext) {
     486             :         bool matched;
     487           0 :         rv = mNodeTest->matches(walker.getCurrentPosition(), aContext, matched);
     488           0 :         NS_ENSURE_SUCCESS(rv, rv);
     489             : 
     490           0 :         if (matched) {
     491           0 :             nodes->append(walker.getCurrentPosition());
     492             :         }
     493           0 :         hasNext = mIsAttr ? walker.moveToNextAttribute() :
     494             :                             walker.moveToNextSibling();
     495             :     }
     496             : 
     497           0 :     Expr* predicate = mPredicates[0];
     498           0 :     RefPtr<txNodeSet> newNodes;
     499           0 :     rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes));
     500           0 :     NS_ENSURE_SUCCESS(rv, rv);
     501             : 
     502           0 :     uint32_t i, predLen = mPredicates.Length();
     503           0 :     for (i = 1; i < predLen; ++i) {
     504           0 :         newNodes->clear();
     505           0 :         bool contextIsInPredicate = false;
     506           0 :         txNodeSetContext predContext(nodes, aContext);
     507           0 :         while (predContext.hasNext()) {
     508           0 :             predContext.next();
     509           0 :             RefPtr<txAExprResult> exprResult;
     510           0 :             rv = predicate->evaluate(&predContext, getter_AddRefs(exprResult));
     511           0 :             NS_ENSURE_SUCCESS(rv, rv);
     512             : 
     513           0 :             switch(exprResult->getResultType()) {
     514             :                 case txAExprResult::NUMBER:
     515             :                     // handle default, [position() == numberValue()]
     516           0 :                     if ((double)predContext.position() ==
     517           0 :                         exprResult->numberValue()) {
     518           0 :                         const txXPathNode& tmp = predContext.getContextNode();
     519           0 :                         if (tmp == aNode)
     520           0 :                             contextIsInPredicate = true;
     521           0 :                         newNodes->append(tmp);
     522             :                     }
     523           0 :                     break;
     524             :                 default:
     525           0 :                     if (exprResult->booleanValue()) {
     526           0 :                         const txXPathNode& tmp = predContext.getContextNode();
     527           0 :                         if (tmp == aNode)
     528           0 :                             contextIsInPredicate = true;
     529           0 :                         newNodes->append(tmp);
     530             :                     }
     531           0 :                     break;
     532             :             }
     533             :         }
     534             :         // Move new NodeSet to the current one
     535           0 :         nodes->clear();
     536           0 :         nodes->append(*newNodes);
     537           0 :         if (!contextIsInPredicate) {
     538           0 :             aMatched = false;
     539             : 
     540           0 :             return NS_OK;
     541             :         }
     542           0 :         predicate = mPredicates[i];
     543             :     }
     544           0 :     txForwardContext evalContext(aContext, aNode, nodes);
     545           0 :     RefPtr<txAExprResult> exprResult;
     546           0 :     rv = predicate->evaluate(&evalContext, getter_AddRefs(exprResult));
     547           0 :     NS_ENSURE_SUCCESS(rv, rv);
     548             : 
     549           0 :     if (exprResult->getResultType() == txAExprResult::NUMBER) {
     550             :         // handle default, [position() == numberValue()]
     551           0 :         aMatched = ((double)evalContext.position() == exprResult->numberValue());
     552             :     } else {
     553           0 :         aMatched = exprResult->booleanValue();
     554             :     }
     555             : 
     556           0 :     return NS_OK;
     557             : } // matches
     558             : 
     559           0 : double txStepPattern::getDefaultPriority()
     560             : {
     561           0 :     if (isEmpty())
     562           0 :         return mNodeTest->getDefaultPriority();
     563           0 :     return 0.5;
     564             : }
     565             : 
     566             : txPattern::Type
     567           0 : txStepPattern::getType()
     568             : {
     569           0 :   return STEP_PATTERN;
     570             : }
     571             : 
     572           0 : TX_IMPL_PATTERN_STUBS_NO_SUB_PATTERN(txStepPattern)
     573             : Expr*
     574           0 : txStepPattern::getSubExprAt(uint32_t aPos)
     575             : {
     576           0 :     return PredicateList::getSubExprAt(aPos);
     577             : }
     578             : 
     579             : void
     580           0 : txStepPattern::setSubExprAt(uint32_t aPos, Expr* aExpr)
     581             : {
     582           0 :     PredicateList::setSubExprAt(aPos, aExpr);
     583           0 : }
     584             : 
     585             : #ifdef TX_TO_STRING
     586             : void
     587           0 : txStepPattern::toString(nsAString& aDest)
     588             : {
     589             : #ifdef DEBUG
     590           0 :     aDest.AppendLiteral("txStepPattern{");
     591             : #endif
     592           0 :     if (mIsAttr)
     593           0 :         aDest.Append(char16_t('@'));
     594           0 :     if (mNodeTest)
     595           0 :         mNodeTest->toString(aDest);
     596             : 
     597           0 :     PredicateList::toString(aDest);
     598             : #ifdef DEBUG
     599           0 :     aDest.Append(char16_t('}'));
     600             : #endif
     601           0 : }
     602             : #endif

Generated by: LCOV version 1.13