LCOV - code coverage report
Current view: top level - xmlreader/source - xmlreader.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 333 505 65.9 %
Date: 2012-08-25 Functions: 25 26 96.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 207 509 40.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "sal/config.h"
      21                 :            : 
      22                 :            : #include <cassert>
      23                 :            : #include <climits>
      24                 :            : #include <cstddef>
      25                 :            : 
      26                 :            : #include "com/sun/star/container/NoSuchElementException.hpp"
      27                 :            : #include "com/sun/star/uno/Reference.hxx"
      28                 :            : #include "com/sun/star/uno/RuntimeException.hpp"
      29                 :            : #include "com/sun/star/uno/XInterface.hpp"
      30                 :            : #include "osl/file.h"
      31                 :            : #include "rtl/oustringostreaminserter.hxx"
      32                 :            : #include "rtl/string.h"
      33                 :            : #include "rtl/ustring.h"
      34                 :            : #include "rtl/ustring.hxx"
      35                 :            : #include "sal/log.hxx"
      36                 :            : #include "sal/types.h"
      37                 :            : #include "xmlreader/pad.hxx"
      38                 :            : #include "xmlreader/span.hxx"
      39                 :            : #include "xmlreader/xmlreader.hxx"
      40                 :            : 
      41                 :            : namespace xmlreader {
      42                 :            : 
      43                 :            : namespace {
      44                 :            : 
      45                 :            : namespace css = com::sun::star;
      46                 :            : 
      47                 :  129122335 : bool isSpace(char c) {
      48         [ +  + ]:  129122335 :     switch (c) {
      49                 :            :     case '\x09':
      50                 :            :     case '\x0A':
      51                 :            :     case '\x0D':
      52                 :            :     case ' ':
      53                 :   19662276 :         return true;
      54                 :            :     default:
      55                 :  129122335 :         return false;
      56                 :            :     }
      57                 :            : }
      58                 :            : 
      59                 :            : }
      60                 :            : 
      61                 :      49377 : XmlReader::XmlReader(rtl::OUString const & fileUrl)
      62                 :            :     SAL_THROW((
      63                 :            :         css::container::NoSuchElementException, css::uno::RuntimeException)):
      64 [ +  - ][ +  - ]:      49763 :     fileUrl_(fileUrl)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      65                 :            : {
      66                 :            :     oslFileError e = osl_openFile(
      67         [ +  - ]:      49377 :         fileUrl_.pData, &fileHandle_, osl_File_OpenFlag_Read);
      68      [ +  +  - ]:      49377 :     switch (e)
      69                 :            :     {
      70                 :            :     case osl_File_E_None:
      71                 :      48995 :         break;
      72                 :            :     case osl_File_E_NOENT:
      73                 :            :         throw css::container::NoSuchElementException(
      74         [ +  - ]:        382 :             fileUrl_, css::uno::Reference< css::uno::XInterface >());
      75                 :            :     default:
      76                 :            :         throw css::uno::RuntimeException(
      77                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cannot open ")) +
      78                 :            :              fileUrl_ + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(": ")) +
      79                 :            :              rtl::OUString::valueOf(static_cast< sal_Int32 >(e))),
      80 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
                 [ #  # ]
      81                 :            :     }
      82         [ +  - ]:      48995 :     e = osl_getFileSize(fileHandle_, &fileSize_);
      83         [ +  - ]:      48995 :     if (e == osl_File_E_None) {
      84                 :            :         e = osl_mapFile(
      85                 :            :             fileHandle_, &fileAddress_, fileSize_, 0,
      86         [ +  - ]:      48995 :             osl_File_MapFlag_WillNeed);
      87                 :            :     }
      88         [ +  + ]:      48995 :     if (e != osl_File_E_None) {
      89         [ +  - ]:          4 :         oslFileError e2 = osl_closeFile(fileHandle_);
      90                 :            :         if (e2 != osl_File_E_None) {
      91                 :            :             SAL_WARN(
      92                 :            :                 "xmlreader",
      93                 :            :                 "osl_closeFile of \"" << fileUrl_ << "\" failed with " << +e2);
      94                 :            :         }
      95                 :            :         throw css::uno::RuntimeException(
      96                 :            :             ("cannot mmap " + fileUrl_ + " (" +
      97                 :            :              rtl::OUString::valueOf(static_cast< sal_Int32 >(e)) + ")"),
      98         [ +  - ]:          4 :             css::uno::Reference< css::uno::XInterface >());
      99                 :            :     }
     100                 :            :     namespaceIris_.push_back(
     101                 :            :         Span(
     102                 :            :             RTL_CONSTASCII_STRINGPARAM(
     103         [ +  - ]:      48991 :                 "http://www.w3.org/XML/1998/namespace")));
     104                 :            :     namespaces_.push_back(
     105         [ +  - ]:      48991 :         NamespaceData(Span(RTL_CONSTASCII_STRINGPARAM("xml")), NAMESPACE_XML));
     106                 :      48991 :     pos_ = static_cast< char * >(fileAddress_);
     107                 :      48991 :     end_ = pos_ + fileSize_;
     108                 :      48991 :     state_ = STATE_CONTENT;
     109                 :      48991 :     firstAttribute_ = true;
     110                 :      48991 : }
     111                 :            : 
     112         [ +  - ]:      48991 : XmlReader::~XmlReader() {
     113         [ +  - ]:      48991 :     oslFileError e = osl_unmapMappedFile(fileHandle_, fileAddress_, fileSize_);
     114                 :            :     if (e != osl_File_E_None) {
     115                 :            :         SAL_WARN(
     116                 :            :             "xmlreader",
     117                 :            :             "osl_unmapMappedFile of \"" << fileUrl_ << "\" failed with " << +e);
     118                 :            :     }
     119         [ +  - ]:      48991 :     e = osl_closeFile(fileHandle_);
     120                 :            :     if (e != osl_File_E_None) {
     121                 :            :         SAL_WARN(
     122                 :            :             "xmlreader",
     123                 :            :             "osl_closeFile of \"" << fileUrl_ << "\" failed with " << +e);
     124                 :            :     }
     125                 :      48991 : }
     126                 :            : 
     127                 :     137889 : int XmlReader::registerNamespaceIri(Span const & iri) {
     128                 :     137889 :     int id = toNamespaceId(namespaceIris_.size());
     129                 :     137889 :     namespaceIris_.push_back(iri);
     130         [ +  + ]:     137889 :     if (iri.equals(
     131                 :            :             Span(
     132                 :            :                 RTL_CONSTASCII_STRINGPARAM(
     133                 :     137889 :                     "http://www.w3.org/2001/XMLSchema-instance"))))
     134                 :            :     {
     135                 :            :         // Old user layer .xcu files used the xsi namespace prefix without
     136                 :            :         // declaring a corresponding namespace binding, see issue 77174; reading
     137                 :            :         // those files during migration would fail without this hack that can be
     138                 :            :         // removed once migration is no longer relevant (see
     139                 :            :         // configmgr::Components::parseModificationLayer):
     140                 :            :         namespaces_.push_back(
     141         [ +  - ]:      44449 :             NamespaceData(Span(RTL_CONSTASCII_STRINGPARAM("xsi")), id));
     142                 :            :     }
     143                 :     137889 :     return id;
     144                 :            : }
     145                 :            : 
     146                 :   45305189 : XmlReader::Result XmlReader::nextItem(Text reportText, Span * data, int * nsId)
     147                 :            : {
     148   [ +  +  +  +  :   45305189 :     switch (state_) {
                      + ]
     149                 :            :     case STATE_CONTENT:
     150   [ +  +  +  - ]:   37757051 :         switch (reportText) {
     151                 :            :         case TEXT_NONE:
     152                 :   31448195 :             return handleSkippedText(data, nsId);
     153                 :            :         case TEXT_RAW:
     154                 :    4468880 :             return handleRawText(data);
     155                 :            :         case TEXT_NORMALIZED:
     156                 :    1839976 :             return handleNormalizedText(data);
     157                 :            :         }
     158                 :            :     case STATE_START_TAG:
     159                 :      14244 :         return handleStartTag(nsId, data);
     160                 :            :     case STATE_END_TAG:
     161                 :    6294612 :         return handleEndTag();
     162                 :            :     case STATE_EMPTY_ELEMENT_TAG:
     163                 :    1190487 :         handleElementEnd();
     164                 :    1190487 :         return RESULT_END;
     165                 :            :     default: // STATE_DONE
     166                 :   45304993 :         return RESULT_DONE;
     167                 :            :     }
     168                 :            : }
     169                 :            : 
     170                 :   36827420 : bool XmlReader::nextAttribute(int * nsId, Span * localName) {
     171                 :            :     assert(nsId != 0 && localName != 0);
     172         [ +  + ]:   36827420 :     if (firstAttribute_) {
     173                 :   17511113 :         currentAttribute_ = attributes_.begin();
     174                 :   17511113 :         firstAttribute_ = false;
     175                 :            :     } else {
     176                 :   19316307 :         ++currentAttribute_;
     177                 :            :     }
     178 [ +  - ][ +  + ]:   36827420 :     if (currentAttribute_ == attributes_.end()) {
     179                 :   17511113 :         return false;
     180                 :            :     }
     181         [ +  + ]:   19316307 :     if (currentAttribute_->nameColon == 0) {
     182                 :     602025 :         *nsId = NAMESPACE_NONE;
     183                 :            :         *localName = Span(
     184                 :     602025 :             currentAttribute_->nameBegin,
     185                 :    1204050 :             currentAttribute_->nameEnd - currentAttribute_->nameBegin);
     186                 :            :     } else {
     187                 :            :         *nsId = getNamespaceId(
     188                 :            :             Span(
     189                 :   18714282 :                 currentAttribute_->nameBegin,
     190         [ +  - ]:   37428564 :                 currentAttribute_->nameColon - currentAttribute_->nameBegin));
     191                 :            :         *localName = Span(
     192                 :   18714282 :             currentAttribute_->nameColon + 1,
     193                 :   37428564 :             currentAttribute_->nameEnd - (currentAttribute_->nameColon + 1));
     194                 :            :     }
     195                 :   36827420 :     return true;
     196                 :            : }
     197                 :            : 
     198                 :   19272867 : Span XmlReader::getAttributeValue(bool fullyNormalize) {
     199                 :            :     return handleAttributeValue(
     200                 :   19272867 :         currentAttribute_->valueBegin, currentAttribute_->valueEnd,
     201                 :   19272867 :         fullyNormalize);
     202                 :            : }
     203                 :            : 
     204                 :   21486410 : int XmlReader::getNamespaceId(Span const & prefix) const {
     205   [ +  -  +  - ]:  125577382 :     for (NamespaceList::const_reverse_iterator i(namespaces_.rbegin());
                 [ +  - ]
     206                 :   62788691 :          i != namespaces_.rend(); ++i)
     207                 :            :     {
     208 [ +  - ][ +  + ]:   62788691 :         if (prefix.equals(i->prefix)) {
     209         [ +  - ]:   21486410 :             return i->nsId;
     210                 :            :         }
     211                 :            :     }
     212                 :   21486410 :     return NAMESPACE_UNKNOWN;
     213                 :            : }
     214                 :            : 
     215                 :      38270 : rtl::OUString XmlReader::getUrl() const {
     216                 :      38270 :     return fileUrl_;
     217                 :            : }
     218                 :            : 
     219                 :          0 : void XmlReader::normalizeLineEnds(Span const & text) {
     220                 :          0 :     char const * p = text.begin;
     221                 :          0 :     sal_Int32 n = text.length;
     222                 :          0 :     for (;;) {
     223                 :          0 :         sal_Int32 i = rtl_str_indexOfChar_WithLength(p, n, '\x0D');
     224         [ #  # ]:          0 :         if (i < 0) {
     225                 :          0 :             break;
     226                 :            :         }
     227                 :          0 :         pad_.add(p, i);
     228                 :          0 :         p += i + 1;
     229                 :          0 :         n -= i + 1;
     230 [ #  # ][ #  # ]:          0 :         if (n == 0 || *p != '\x0A') {
     231                 :          0 :             pad_.add(RTL_CONSTASCII_STRINGPARAM("\x0A"));
     232                 :            :         }
     233                 :            :     }
     234                 :          0 :     pad_.add(p, n);
     235                 :          0 : }
     236                 :            : 
     237                 :   96656339 : void XmlReader::skipSpace() {
     238         [ +  + ]:  116318615 :     while (isSpace(peek())) {
     239                 :   19662276 :         ++pos_;
     240                 :            :     }
     241                 :   96656339 : }
     242                 :            : 
     243                 :       5758 : bool XmlReader::skipComment() {
     244         [ +  + ]:       5758 :     if (rtl_str_shortenedCompare_WithLength(
     245                 :            :             pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("--"),
     246                 :       5758 :             RTL_CONSTASCII_LENGTH("--")) !=
     247                 :            :         0)
     248                 :            :     {
     249                 :        294 :         return false;
     250                 :            :     }
     251                 :       5464 :     pos_ += RTL_CONSTASCII_LENGTH("--");
     252                 :            :     sal_Int32 i = rtl_str_indexOfStr_WithLength(
     253                 :       5464 :         pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("--"));
     254         [ -  + ]:       5464 :     if (i < 0) {
     255                 :            :         throw css::uno::RuntimeException(
     256                 :            :             (rtl::OUString(
     257                 :            :                 RTL_CONSTASCII_USTRINGPARAM(
     258                 :            :                     "premature end (within comment) of ")) +
     259                 :            :              fileUrl_),
     260 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     261                 :            :     }
     262                 :       5464 :     pos_ += i + RTL_CONSTASCII_LENGTH("--");
     263         [ -  + ]:       5464 :     if (read() != '>') {
     264                 :            :         throw css::uno::RuntimeException(
     265                 :            :             (rtl::OUString(
     266                 :            :                 RTL_CONSTASCII_USTRINGPARAM(
     267                 :            :                     "illegal \"--\" within comment in ")) +
     268                 :            :              fileUrl_),
     269 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     270                 :            :     }
     271                 :       5758 :     return true;
     272                 :            : }
     273                 :            : 
     274                 :      48795 : void XmlReader::skipProcessingInstruction() {
     275                 :            :     sal_Int32 i = rtl_str_indexOfStr_WithLength(
     276                 :      48795 :         pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("?>"));
     277         [ -  + ]:      48795 :     if (i < 0) {
     278                 :            :         throw css::uno::RuntimeException(
     279                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad '<?' in ")) +
     280                 :            :              fileUrl_),
     281 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     282                 :            :     }
     283                 :      48795 :     pos_ += i + RTL_CONSTASCII_LENGTH("?>");
     284                 :      48795 : }
     285                 :            : 
     286                 :      10584 : void XmlReader::skipDocumentTypeDeclaration() {
     287                 :            :     // Neither is it checked that the doctypedecl is at the correct position in
     288                 :            :     // the document, nor that it is well-formed:
     289                 :      10584 :     for (;;) {
     290                 :      10584 :         char c = read();
     291   [ -  +  +  -  :      10584 :         switch (c) {
                      + ]
     292                 :            :         case '\0': // i.e., EOF
     293                 :            :             throw css::uno::RuntimeException(
     294                 :            :                 (rtl::OUString(
     295                 :            :                     RTL_CONSTASCII_USTRINGPARAM(
     296                 :            :                         "premature end (within DTD) of ")) +
     297                 :            :                  fileUrl_),
     298 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     299                 :            :         case '"':
     300                 :            :         case '\'':
     301                 :            :             {
     302                 :            :                 sal_Int32 i = rtl_str_indexOfChar_WithLength(
     303                 :        294 :                     pos_, end_ - pos_, c);
     304         [ -  + ]:        294 :                 if (i < 0) {
     305                 :            :                     throw css::uno::RuntimeException(
     306                 :            :                         (rtl::OUString(
     307                 :            :                             RTL_CONSTASCII_USTRINGPARAM(
     308                 :            :                                 "premature end (within DTD) of ")) +
     309                 :            :                          fileUrl_),
     310 [ #  # ][ #  # ]:          0 :                         css::uno::Reference< css::uno::XInterface >());
     311                 :            :                 }
     312                 :        294 :                 pos_ += i + 1;
     313                 :            :             }
     314                 :        294 :             break;
     315                 :            :         case '>':
     316                 :        294 :             return;
     317                 :            :         case '[':
     318                 :          0 :             for (;;) {
     319                 :          0 :                 c = read();
     320   [ #  #  #  #  :          0 :                 switch (c) {
                      # ]
     321                 :            :                 case '\0': // i.e., EOF
     322                 :            :                     throw css::uno::RuntimeException(
     323                 :            :                         (rtl::OUString(
     324                 :            :                             RTL_CONSTASCII_USTRINGPARAM(
     325                 :            :                                 "premature end (within DTD) of ")) +
     326                 :            :                          fileUrl_),
     327 [ #  # ][ #  # ]:          0 :                         css::uno::Reference< css::uno::XInterface >());
     328                 :            :                 case '"':
     329                 :            :                 case '\'':
     330                 :            :                     {
     331                 :            :                         sal_Int32 i = rtl_str_indexOfChar_WithLength(
     332                 :          0 :                             pos_, end_ - pos_, c);
     333         [ #  # ]:          0 :                         if (i < 0) {
     334                 :            :                             throw css::uno::RuntimeException(
     335                 :            :                             (rtl::OUString(
     336                 :            :                                 RTL_CONSTASCII_USTRINGPARAM(
     337                 :            :                                     "premature end (within DTD) of ")) +
     338                 :            :                              fileUrl_),
     339 [ #  # ][ #  # ]:          0 :                             css::uno::Reference< css::uno::XInterface >());
     340                 :            :                         }
     341                 :          0 :                         pos_ += i + 1;
     342                 :            :                     }
     343                 :          0 :                     break;
     344                 :            :                 case '<':
     345   [ #  #  #  # ]:          0 :                     switch (read()) {
     346                 :            :                     case '\0': // i.e., EOF
     347                 :            :                         throw css::uno::RuntimeException(
     348                 :            :                             (rtl::OUString(
     349                 :            :                                 RTL_CONSTASCII_USTRINGPARAM(
     350                 :            :                                     "premature end (within DTD) of ")) +
     351                 :            :                              fileUrl_),
     352 [ #  # ][ #  # ]:          0 :                             css::uno::Reference< css::uno::XInterface >());
     353                 :            :                     case '!':
     354                 :          0 :                         skipComment();
     355                 :          0 :                         break;
     356                 :            :                     case '?':
     357                 :          0 :                         skipProcessingInstruction();
     358                 :          0 :                         break;
     359                 :            :                     default:
     360                 :          0 :                         break;
     361                 :            :                     }
     362                 :          0 :                     break;
     363                 :            :                 case ']':
     364                 :          0 :                     skipSpace();
     365         [ #  # ]:          0 :                     if (read() != '>') {
     366                 :            :                         throw css::uno::RuntimeException(
     367                 :            :                             (rtl::OUString(
     368                 :            :                                 RTL_CONSTASCII_USTRINGPARAM(
     369                 :            :                                     "missing \">\" of DTD in ")) +
     370                 :            :                              fileUrl_),
     371 [ #  # ][ #  # ]:          0 :                             css::uno::Reference< css::uno::XInterface >());
     372                 :            :                     }
     373                 :          0 :                     return;
     374                 :            :                 default:
     375                 :          0 :                     break;
     376                 :            :                 }
     377                 :            :             }
     378                 :            :         default:
     379                 :       9996 :             break;
     380                 :            :         }
     381                 :            :     }
     382                 :            : }
     383                 :            : 
     384                 :        294 : Span XmlReader::scanCdataSection() {
     385         [ +  - ]:        294 :     if (rtl_str_shortenedCompare_WithLength(
     386                 :            :             pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("[CDATA["),
     387                 :        294 :             RTL_CONSTASCII_LENGTH("[CDATA[")) !=
     388                 :            :         0)
     389                 :            :     {
     390                 :        294 :         return Span();
     391                 :            :     }
     392                 :          0 :     pos_ += RTL_CONSTASCII_LENGTH("[CDATA[");
     393                 :          0 :     char const * begin = pos_;
     394                 :            :     sal_Int32 i = rtl_str_indexOfStr_WithLength(
     395                 :          0 :         pos_, end_ - pos_, RTL_CONSTASCII_STRINGPARAM("]]>"));
     396         [ #  # ]:          0 :     if (i < 0) {
     397                 :            :         throw css::uno::RuntimeException(
     398                 :            :             (rtl::OUString(
     399                 :            :                 RTL_CONSTASCII_USTRINGPARAM(
     400                 :            :                     "premature end (within CDATA section) of ")) +
     401                 :            :              fileUrl_),
     402 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     403                 :            :     }
     404                 :          0 :     pos_ += i + RTL_CONSTASCII_LENGTH("]]>");
     405                 :        294 :     return Span(begin, i);
     406                 :            : }
     407                 :            : 
     408                 :   57390147 : bool XmlReader::scanName(char const ** nameColon) {
     409                 :            :     assert(nameColon != 0 && *nameColon == 0);
     410                 :  389404525 :     for (char const * begin = pos_;; ++pos_) {
     411      [ +  +  + ]:  389404525 :         switch (peek()) {
     412                 :            :         case '\0': // i.e., EOF
     413                 :            :         case '\x09':
     414                 :            :         case '\x0A':
     415                 :            :         case '\x0D':
     416                 :            :         case ' ':
     417                 :            :         case '/':
     418                 :            :         case '=':
     419                 :            :         case '>':
     420                 :   57390147 :             return pos_ != begin;
     421                 :            :         case ':':
     422                 :   19194832 :             *nameColon = pos_;
     423                 :   19194832 :             break;
     424                 :            :         default:
     425                 :  312819546 :             break;
     426                 :            :         }
     427                 :            :     }
     428                 :            : }
     429                 :            : 
     430                 :     167097 : int XmlReader::scanNamespaceIri(char const * begin, char const * end) {
     431                 :            :     assert(begin != 0 && begin <= end);
     432         [ +  - ]:     167097 :     Span iri(handleAttributeValue(begin, end, false));
     433         [ +  + ]:     562897 :     for (NamespaceIris::size_type i = 0; i < namespaceIris_.size(); ++i) {
     434 [ +  - ][ +  + ]:     526676 :         if (namespaceIris_[i].equals(iri)) {
     435                 :     130876 :             return toNamespaceId(i);
     436                 :            :         }
     437                 :            :     }
     438                 :     167097 :     return XmlReader::NAMESPACE_UNKNOWN;
     439                 :            : }
     440                 :            : 
     441                 :      40296 : char const * XmlReader::handleReference(char const * position, char const * end)
     442                 :            : {
     443                 :            :     assert(position != 0 && *position == '&' && position < end);
     444                 :      40296 :     ++position;
     445         [ +  + ]:      40296 :     if (*position == '#') {
     446                 :       1920 :         ++position;
     447                 :       1920 :         sal_Int32 val = 0;
     448                 :            :         char const * p;
     449         [ +  - ]:       1920 :         if (*position == 'x') {
     450                 :       1920 :             ++position;
     451                 :       1920 :             p = position;
     452                 :       9600 :             for (;; ++position) {
     453                 :       9600 :                 char c = *position;
     454 [ +  - ][ +  + ]:       9600 :                 if (c >= '0' && c <= '9') {
     455                 :       3520 :                     val = 16 * val + (c - '0');
     456 [ +  + ][ +  - ]:       6080 :                 } else if (c >= 'A' && c <= 'F') {
     457                 :       4160 :                     val = 16 * val + (c - 'A') + 10;
     458 [ -  + ][ #  # ]:       1920 :                 } else if (c >= 'a' && c <= 'f') {
     459                 :          0 :                     val = 16 * val + (c - 'a') + 10;
     460                 :            :                 } else {
     461                 :       1920 :                     break;
     462                 :            :                 }
     463         [ -  + ]:       7680 :                 if (val > 0x10FFFF) { // avoid overflow
     464                 :            :                     throw css::uno::RuntimeException(
     465                 :            :                         (rtl::OUString(
     466                 :            :                             RTL_CONSTASCII_USTRINGPARAM(
     467                 :            :                                 "'&#x...' too large in ")) +
     468                 :            :                          fileUrl_),
     469 [ #  # ][ #  # ]:          0 :                         css::uno::Reference< css::uno::XInterface >());
     470                 :            :                 }
     471                 :            :             }
     472                 :            :         } else {
     473                 :          0 :             p = position;
     474                 :          0 :             for (;; ++position) {
     475                 :          0 :                 char c = *position;
     476 [ #  # ][ #  # ]:          0 :                 if (c >= '0' && c <= '9') {
     477                 :          0 :                     val = 10 * val + (c - '0');
     478                 :            :                 } else {
     479                 :          0 :                     break;
     480                 :            :                 }
     481         [ #  # ]:          0 :                 if (val > 0x10FFFF) { // avoid overflow
     482                 :            :                     throw css::uno::RuntimeException(
     483                 :            :                         (rtl::OUString(
     484                 :            :                             RTL_CONSTASCII_USTRINGPARAM(
     485                 :            :                                 "'&#...' too large in ")) +
     486                 :            :                          fileUrl_),
     487 [ #  # ][ #  # ]:          0 :                         css::uno::Reference< css::uno::XInterface >());
     488                 :            :                 }
     489                 :            :             }
     490                 :            :         }
     491 [ +  - ][ -  + ]:       1920 :         if (position == p || *position++ != ';') {
                 [ -  + ]
     492                 :            :             throw css::uno::RuntimeException(
     493                 :            :                 (rtl::OUString(
     494                 :            :                     RTL_CONSTASCII_USTRINGPARAM("'&#...' missing ';' in ")) +
     495                 :            :                  fileUrl_),
     496 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     497                 :            :         }
     498                 :            :         assert(val >= 0 && val <= 0x10FFFF);
     499 [ -  + ][ #  # ]:       1920 :         if ((val < 0x20 && val != 0x9 && val != 0xA && val != 0xD) ||
         [ #  # ][ #  # ]
         [ -  + ][ #  # ]
         [ +  - ][ -  + ]
     500                 :            :             (val >= 0xD800 && val <= 0xDFFF) || val == 0xFFFE || val == 0xFFFF)
     501                 :            :         {
     502                 :            :             throw css::uno::RuntimeException(
     503                 :            :                 (rtl::OUString(
     504                 :            :                     RTL_CONSTASCII_USTRINGPARAM(
     505                 :            :                         "character reference denoting invalid character in ")) +
     506                 :            :                  fileUrl_),
     507 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     508                 :            :         }
     509                 :            :         char buf[4];
     510                 :            :         sal_Int32 len;
     511         [ -  + ]:       1920 :         if (val < 0x80) {
     512                 :          0 :             buf[0] = static_cast< char >(val);
     513                 :          0 :             len = 1;
     514         [ -  + ]:       1920 :         } else if (val < 0x800) {
     515                 :          0 :             buf[0] = static_cast< char >((val >> 6) | 0xC0);
     516                 :          0 :             buf[1] = static_cast< char >((val & 0x3F) | 0x80);
     517                 :          0 :             len = 2;
     518         [ +  - ]:       1920 :         } else if (val < 0x10000) {
     519                 :       1920 :             buf[0] = static_cast< char >((val >> 12) | 0xE0);
     520                 :       1920 :             buf[1] = static_cast< char >(((val >> 6) & 0x3F) | 0x80);
     521                 :       1920 :             buf[2] = static_cast< char >((val & 0x3F) | 0x80);
     522                 :       1920 :             len = 3;
     523                 :            :         } else {
     524                 :          0 :             buf[0] = static_cast< char >((val >> 18) | 0xF0);
     525                 :          0 :             buf[1] = static_cast< char >(((val >> 12) & 0x3F) | 0x80);
     526                 :          0 :             buf[2] = static_cast< char >(((val >> 6) & 0x3F) | 0x80);
     527                 :          0 :             buf[3] = static_cast< char >((val & 0x3F) | 0x80);
     528                 :          0 :             len = 4;
     529                 :            :         }
     530         [ +  - ]:       1920 :         pad_.addEphemeral(buf, len);
     531                 :       1920 :         return position;
     532                 :            :     } else {
     533                 :            :         struct EntityRef {
     534                 :            :             char const * inBegin;
     535                 :            :             sal_Int32 inLength;
     536                 :            :             char const * outBegin;
     537                 :            :             sal_Int32 outLength;
     538                 :            :         };
     539                 :            :         static EntityRef const refs[] = {
     540                 :            :             { RTL_CONSTASCII_STRINGPARAM("amp;"),
     541                 :            :               RTL_CONSTASCII_STRINGPARAM("&") },
     542                 :            :             { RTL_CONSTASCII_STRINGPARAM("lt;"),
     543                 :            :               RTL_CONSTASCII_STRINGPARAM("<") },
     544                 :            :             { RTL_CONSTASCII_STRINGPARAM("gt;"),
     545                 :            :               RTL_CONSTASCII_STRINGPARAM(">") },
     546                 :            :             { RTL_CONSTASCII_STRINGPARAM("apos;"),
     547                 :            :               RTL_CONSTASCII_STRINGPARAM("'") },
     548                 :            :             { RTL_CONSTASCII_STRINGPARAM("quot;"),
     549                 :            :               RTL_CONSTASCII_STRINGPARAM("\"") } };
     550         [ +  - ]:      69372 :         for (std::size_t i = 0; i < sizeof refs / sizeof refs[0]; ++i) {
     551         [ +  + ]:      69372 :             if (rtl_str_shortenedCompare_WithLength(
     552                 :            :                     position, end - position, refs[i].inBegin, refs[i].inLength,
     553                 :      69372 :                     refs[i].inLength) ==
     554                 :            :                 0)
     555                 :            :             {
     556                 :      38376 :                 position += refs[i].inLength;
     557                 :      38376 :                 pad_.add(refs[i].outBegin, refs[i].outLength);
     558                 :      38376 :                 return position;
     559                 :            :             }
     560                 :            :         }
     561                 :            :         throw css::uno::RuntimeException(
     562                 :            :             (rtl::OUString(
     563                 :            :                 RTL_CONSTASCII_USTRINGPARAM("unknown entity reference in ")) +
     564                 :            :              fileUrl_),
     565 [ #  # ][ #  # ]:      40296 :             css::uno::Reference< css::uno::XInterface >());
     566                 :            :     }
     567                 :            : }
     568                 :            : 
     569                 :   19439964 : Span XmlReader::handleAttributeValue(
     570                 :            :     char const * begin, char const * end, bool fullyNormalize)
     571                 :            : {
     572                 :   19439964 :     pad_.clear();
     573         [ +  + ]:   19439964 :     if (fullyNormalize) {
     574 [ +  - ][ -  + ]:    6401860 :         while (begin != end && isSpace(*begin)) {
                 [ -  + ]
     575                 :          0 :             ++begin;
     576                 :            :         }
     577 [ +  - ][ -  + ]:    6401860 :         while (end != begin && isSpace(end[-1])) {
                 [ -  + ]
     578                 :          0 :             --end;
     579                 :            :         }
     580                 :    6401860 :         char const * p = begin;
     581                 :            :         enum Space { SPACE_NONE, SPACE_SPAN, SPACE_BREAK };
     582                 :            :             // a single true space character can go into the current span,
     583                 :            :             // everything else breaks the span
     584                 :    6401860 :         Space space = SPACE_NONE;
     585         [ +  + ]:   53278111 :         while (p != end) {
     586   [ -  +  -  + ]:   46876251 :             switch (*p) {
     587                 :            :             case '\x09':
     588                 :            :             case '\x0A':
     589                 :            :             case '\x0D':
     590   [ #  #  #  # ]:          0 :                 switch (space) {
     591                 :            :                 case SPACE_NONE:
     592                 :          0 :                     pad_.add(begin, p - begin);
     593                 :          0 :                     pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
     594                 :          0 :                     space = SPACE_BREAK;
     595                 :          0 :                     break;
     596                 :            :                 case SPACE_SPAN:
     597                 :          0 :                     pad_.add(begin, p - begin);
     598                 :          0 :                     space = SPACE_BREAK;
     599                 :          0 :                     break;
     600                 :            :                 case SPACE_BREAK:
     601                 :          0 :                     break;
     602                 :            :                 }
     603                 :          0 :                 begin = ++p;
     604                 :          0 :                 break;
     605                 :            :             case ' ':
     606   [ +  -  -  - ]:       8445 :                 switch (space) {
     607                 :            :                 case SPACE_NONE:
     608                 :       8445 :                     ++p;
     609                 :       8445 :                     space = SPACE_SPAN;
     610                 :       8445 :                     break;
     611                 :            :                 case SPACE_SPAN:
     612                 :          0 :                     pad_.add(begin, p - begin);
     613                 :          0 :                     begin = ++p;
     614                 :          0 :                     space = SPACE_BREAK;
     615                 :          0 :                     break;
     616                 :            :                 case SPACE_BREAK:
     617                 :          0 :                     begin = ++p;
     618                 :          0 :                     break;
     619                 :            :                 }
     620                 :       8445 :                 break;
     621                 :            :             case '&':
     622                 :          0 :                 pad_.add(begin, p - begin);
     623                 :          0 :                 p = handleReference(p, end);
     624                 :          0 :                 begin = p;
     625                 :          0 :                 space = SPACE_NONE;
     626                 :          0 :                 break;
     627                 :            :             default:
     628                 :   46867806 :                 ++p;
     629                 :   46867806 :                 space = SPACE_NONE;
     630                 :   46867806 :                 break;
     631                 :            :             }
     632                 :            :         }
     633                 :    6401860 :         pad_.add(begin, p - begin);
     634                 :            :     } else {
     635                 :   13038104 :         char const * p = begin;
     636         [ +  + ]:  156191767 :         while (p != end) {
     637   [ -  -  +  + ]:  143153663 :             switch (*p) {
     638                 :            :             case '\x09':
     639                 :            :             case '\x0A':
     640                 :          0 :                 pad_.add(begin, p - begin);
     641                 :          0 :                 begin = ++p;
     642                 :          0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
     643                 :          0 :                 break;
     644                 :            :             case '\x0D':
     645                 :          0 :                 pad_.add(begin, p - begin);
     646                 :          0 :                 ++p;
     647         [ #  # ]:          0 :                 if (peek() == '\x0A') {
     648                 :          0 :                     ++p;
     649                 :            :                 }
     650                 :          0 :                 begin = p;
     651                 :          0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
     652                 :          0 :                 break;
     653                 :            :             case '&':
     654                 :       1920 :                 pad_.add(begin, p - begin);
     655                 :       1920 :                 p = handleReference(p, end);
     656                 :       1920 :                 begin = p;
     657                 :       1920 :                 break;
     658                 :            :             default:
     659                 :  143151743 :                 ++p;
     660                 :  143151743 :                 break;
     661                 :            :             }
     662                 :            :         }
     663                 :   13038104 :         pad_.add(begin, p - begin);
     664                 :            :     }
     665                 :   19439964 :     return pad_.get();
     666                 :            : }
     667                 :            : 
     668                 :   19473867 : XmlReader::Result XmlReader::handleStartTag(int * nsId, Span * localName) {
     669                 :            :     assert(nsId != 0 && localName);
     670                 :   19473867 :     char const * nameBegin = pos_;
     671                 :   19473867 :     char const * nameColon = 0;
     672         [ -  + ]:   19473867 :     if (!scanName(&nameColon)) {
     673                 :            :         throw css::uno::RuntimeException(
     674                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad tag name in ")) +
     675                 :            :              fileUrl_),
     676 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     677                 :            :     }
     678                 :   19473867 :     char const * nameEnd = pos_;
     679                 :   19473867 :     NamespaceList::size_type inheritedNamespaces = namespaces_.size();
     680                 :   19473867 :     bool hasDefaultNs = false;
     681                 :   19473867 :     int defaultNsId = NAMESPACE_NONE;
     682                 :   19473867 :     attributes_.clear();
     683                 :   19633096 :     for (;;) {
     684                 :   39106963 :         char const * p = pos_;
     685                 :   39106963 :         skipSpace();
     686 [ +  + ][ +  + ]:   39106963 :         if (peek() == '/' || peek() == '>') {
                 [ +  + ]
     687                 :            :             break;
     688                 :            :         }
     689         [ +  + ]:   19633292 :         if (pos_ == p) {
     690                 :            :             throw css::uno::RuntimeException(
     691                 :            :                 (rtl::OUString(
     692                 :            :                     RTL_CONSTASCII_USTRINGPARAM(
     693                 :            :                         "missing whitespace before attribute in ")) +
     694                 :            :                  fileUrl_),
     695 [ +  - ][ +  - ]:        196 :                 css::uno::Reference< css::uno::XInterface >());
     696                 :            :         }
     697                 :   19633096 :         char const * attrNameBegin = pos_;
     698                 :   19633096 :         char const * attrNameColon = 0;
     699         [ -  + ]:   19633096 :         if (!scanName(&attrNameColon)) {
     700                 :            :             throw css::uno::RuntimeException(
     701                 :            :                 (rtl::OUString(
     702                 :            :                     RTL_CONSTASCII_USTRINGPARAM("bad attribute name in ")) +
     703                 :            :                  fileUrl_),
     704 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     705                 :            :         }
     706                 :   19633096 :         char const * attrNameEnd = pos_;
     707                 :   19633096 :         skipSpace();
     708         [ -  + ]:   19633096 :         if (read() != '=') {
     709                 :            :             throw css::uno::RuntimeException(
     710                 :            :                 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '=' in ")) +
     711                 :            :                  fileUrl_),
     712 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     713                 :            :         }
     714                 :   19633096 :         skipSpace();
     715                 :   19633096 :         char del = read();
     716 [ -  + ][ +  - ]:   19633096 :         if (del != '\'' && del != '"') {
     717                 :            :             throw css::uno::RuntimeException(
     718                 :            :                 (rtl::OUString(
     719                 :            :                     RTL_CONSTASCII_USTRINGPARAM("bad attribute value in ")) +
     720                 :            :                  fileUrl_),
     721 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     722                 :            :         }
     723                 :   19633096 :         char const * valueBegin = pos_;
     724                 :   19633096 :         sal_Int32 i = rtl_str_indexOfChar_WithLength(pos_, end_ - pos_, del);
     725         [ -  + ]:   19633096 :         if (i < 0) {
     726                 :            :             throw css::uno::RuntimeException(
     727                 :            :                 (rtl::OUString(
     728                 :            :                     RTL_CONSTASCII_USTRINGPARAM(
     729                 :            :                         "unterminated attribute value in ")) +
     730                 :            :                  fileUrl_),
     731 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     732                 :            :         }
     733                 :   19633096 :         char const * valueEnd = pos_ + i;
     734                 :   19633096 :         pos_ += i + 1;
     735   [ +  +  +  + ]:   39872563 :         if (attrNameColon == 0 &&
                 [ +  + ]
     736                 :            :             Span(attrNameBegin, attrNameEnd - attrNameBegin).equals(
     737         [ +  + ]:   20239467 :                 RTL_CONSTASCII_STRINGPARAM("xmlns")))
     738                 :            :         {
     739                 :       4346 :             hasDefaultNs = true;
     740         [ +  - ]:       4346 :             defaultNsId = scanNamespaceIri(valueBegin, valueEnd);
     741   [ +  +  +  + ]:   58284225 :         } else if (attrNameColon != 0 &&
                 [ +  + ]
     742                 :            :                    Span(attrNameBegin, attrNameColon - attrNameBegin).equals(
     743         [ +  + ]:   38655475 :                        RTL_CONSTASCII_STRINGPARAM("xmlns")))
     744                 :            :         {
     745                 :            :             namespaces_.push_back(
     746                 :            :                 NamespaceData(
     747                 :     162751 :                     Span(attrNameColon + 1, attrNameEnd - (attrNameColon + 1)),
     748 [ +  - ][ +  - ]:     162751 :                     scanNamespaceIri(valueBegin, valueEnd)));
     749                 :            :         } else {
     750                 :            :             attributes_.push_back(
     751                 :            :                 AttributeData(
     752                 :            :                     attrNameBegin, attrNameEnd, attrNameColon, valueBegin,
     753         [ +  - ]:   19466195 :                     valueEnd));
     754                 :            :         }
     755                 :            :     }
     756 [ +  + ][ +  - ]:   19473671 :     if (!hasDefaultNs && !elements_.empty()) {
         [ +  + ][ +  + ]
     757         [ +  - ]:   19424876 :         defaultNsId = elements_.top().defaultNamespaceId;
     758                 :            :     }
     759                 :   19473671 :     firstAttribute_ = true;
     760         [ +  + ]:   19473671 :     if (peek() == '/') {
     761                 :    1190487 :         state_ = STATE_EMPTY_ELEMENT_TAG;
     762                 :    1190487 :         ++pos_;
     763                 :            :     } else {
     764                 :   18283184 :         state_ = STATE_CONTENT;
     765                 :            :     }
     766         [ -  + ]:   19473671 :     if (peek() != '>') {
     767                 :            :         throw css::uno::RuntimeException(
     768                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '>' in ")) +
     769                 :            :              fileUrl_),
     770 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     771                 :            :     }
     772                 :   19473671 :     ++pos_;
     773                 :            :     elements_.push(
     774                 :            :         ElementData(
     775                 :            :             Span(nameBegin, nameEnd - nameBegin), inheritedNamespaces,
     776         [ +  - ]:   19473671 :             defaultNsId));
     777         [ +  + ]:   19473671 :     if (nameColon == 0) {
     778                 :   19388754 :         *nsId = defaultNsId;
     779                 :   19388754 :         *localName = Span(nameBegin, nameEnd - nameBegin);
     780                 :            :     } else {
     781         [ +  - ]:      85113 :         *nsId = getNamespaceId(Span(nameBegin, nameColon - nameBegin));
     782                 :      84917 :         *localName = Span(nameColon + 1, nameEnd - (nameColon + 1));
     783                 :            :     }
     784                 :   19473671 :     return RESULT_BEGIN;
     785                 :            : }
     786                 :            : 
     787                 :   18283184 : XmlReader::Result XmlReader::handleEndTag() {
     788 [ +  - ][ -  + ]:   18283184 :     if (elements_.empty()) {
     789                 :            :         throw css::uno::RuntimeException(
     790                 :            :             (rtl::OUString(
     791                 :            :                 RTL_CONSTASCII_USTRINGPARAM("spurious end tag in ")) +
     792                 :            :              fileUrl_),
     793 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     794                 :            :     }
     795                 :   18283184 :     char const * nameBegin = pos_;
     796                 :   18283184 :     char const * nameColon = 0;
     797   [ +  -  -  + ]:   36566368 :     if (!scanName(&nameColon) ||
                 [ -  + ]
     798         [ +  - ]:   18283184 :         !elements_.top().name.equals(nameBegin, pos_ - nameBegin))
     799                 :            :     {
     800                 :            :         throw css::uno::RuntimeException(
     801                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("tag mismatch in ")) +
     802                 :            :              fileUrl_),
     803 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     804                 :            :     }
     805         [ +  - ]:   18283184 :     handleElementEnd();
     806                 :   18283184 :     skipSpace();
     807         [ -  + ]:   18283184 :     if (peek() != '>') {
     808                 :            :         throw css::uno::RuntimeException(
     809                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("missing '>' in ")) +
     810                 :            :              fileUrl_),
     811 [ #  # ][ #  # ]:          0 :             css::uno::Reference< css::uno::XInterface >());
     812                 :            :     }
     813                 :   18283184 :     ++pos_;
     814                 :   18283184 :     return RESULT_END;
     815                 :            : }
     816                 :            : 
     817                 :   19473671 : void XmlReader::handleElementEnd() {
     818                 :            :     assert(!elements_.empty());
     819                 :   19473671 :     namespaces_.resize(elements_.top().inheritedNamespaces);
     820                 :   19473671 :     elements_.pop();
     821         [ +  + ]:   19473671 :     state_ = elements_.empty() ? STATE_DONE : STATE_CONTENT;
     822                 :   19473671 : }
     823                 :            : 
     824                 :   31501928 : XmlReader::Result XmlReader::handleSkippedText(Span * data, int * nsId) {
     825                 :   31501732 :     for (;;) {
     826                 :   31501928 :         sal_Int32 i = rtl_str_indexOfChar_WithLength(pos_, end_ - pos_, '<');
     827         [ -  + ]:   31501928 :         if (i < 0) {
     828                 :            :             throw css::uno::RuntimeException(
     829                 :            :                 (rtl::OUString(
     830                 :            :                     RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
     831                 :            :                  fileUrl_),
     832 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     833                 :            :         }
     834                 :   31501928 :         pos_ += i + 1;
     835   [ +  +  +  + ]:   31501928 :         switch (peek()) {
     836                 :            :         case '!':
     837                 :       4938 :             ++pos_;
     838 [ +  - ][ +  + ]:       4938 :             if (!skipComment() && !scanCdataSection().is()) {
         [ +  - ][ +  - ]
                 [ +  + ]
           [ +  +  #  # ]
     839                 :        294 :                 skipDocumentTypeDeclaration();
     840                 :            :             }
     841                 :       4938 :             break;
     842                 :            :         case '/':
     843                 :   11988572 :             ++pos_;
     844                 :   11988572 :             return handleEndTag();
     845                 :            :         case '?':
     846                 :      48795 :             ++pos_;
     847                 :      48795 :             skipProcessingInstruction();
     848                 :      48795 :             break;
     849                 :            :         default:
     850                 :   19459623 :             return handleStartTag(nsId, data);
     851                 :            :         }
     852                 :            :     }
     853                 :            : }
     854                 :            : 
     855                 :    4468880 : XmlReader::Result XmlReader::handleRawText(Span * text) {
     856                 :    4468880 :     pad_.clear();
     857                 :  134989730 :     for (char const * begin = pos_;;) {
     858   [ -  -  +  +  :  130520850 :         switch (peek()) {
                      + ]
     859                 :            :         case '\0': // i.e., EOF
     860                 :            :             throw css::uno::RuntimeException(
     861                 :            :                 (rtl::OUString(
     862                 :            :                     RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
     863                 :            :                  fileUrl_),
     864 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     865                 :            :         case '\x0D':
     866                 :          0 :             pad_.add(begin, pos_ - begin);
     867                 :          0 :             ++pos_;
     868         [ #  # ]:          0 :             if (peek() != '\x0A') {
     869                 :          0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM("\x0A"));
     870                 :            :             }
     871                 :          0 :             begin = pos_;
     872                 :          0 :             break;
     873                 :            :         case '&':
     874                 :      38376 :             pad_.add(begin, pos_ - begin);
     875                 :      38376 :             pos_ = handleReference(pos_, end_);
     876                 :      38376 :             begin = pos_;
     877                 :      38376 :             break;
     878                 :            :         case '<':
     879                 :    4468880 :             pad_.add(begin, pos_ - begin);
     880                 :    4468880 :             ++pos_;
     881   [ -  +  -  + ]:    4468880 :             switch (peek()) {
     882                 :            :             case '!':
     883                 :          0 :                 ++pos_;
     884         [ #  # ]:          0 :                 if (!skipComment()) {
     885         [ #  # ]:          0 :                     Span cdata(scanCdataSection());
     886         [ #  # ]:          0 :                     if (cdata.is()) {
     887         [ #  # ]:          0 :                         normalizeLineEnds(cdata);
     888                 :            :                     } else {
     889         [ #  # ]:          0 :                         skipDocumentTypeDeclaration();
     890                 :            :                     }
     891                 :            :                 }
     892                 :          0 :                 begin = pos_;
     893                 :          0 :                 break;
     894                 :            :             case '/':
     895                 :    4454636 :                 *text = pad_.get();
     896                 :    4454636 :                 ++pos_;
     897                 :    4454636 :                 state_ = STATE_END_TAG;
     898                 :    4454636 :                 return RESULT_TEXT;
     899                 :            :             case '?':
     900                 :          0 :                 ++pos_;
     901                 :          0 :                 skipProcessingInstruction();
     902                 :          0 :                 begin = pos_;
     903                 :          0 :                 break;
     904                 :            :             default:
     905                 :      14244 :                 *text = pad_.get();
     906                 :      14244 :                 state_ = STATE_START_TAG;
     907                 :      14244 :                 return RESULT_TEXT;
     908                 :            :             }
     909                 :          0 :             break;
     910                 :            :         default:
     911                 :  126013594 :             ++pos_;
     912                 :  126013594 :             break;
     913                 :            :         }
     914                 :            :     }
     915                 :            : }
     916                 :            : 
     917                 :    1839976 : XmlReader::Result XmlReader::handleNormalizedText(Span * text) {
     918                 :    1839976 :     pad_.clear();
     919                 :    1839976 :     char const * flowBegin = pos_;
     920                 :    1839976 :     char const * flowEnd = pos_;
     921                 :            :     enum Space { SPACE_START, SPACE_NONE, SPACE_SPAN, SPACE_BREAK };
     922                 :            :         // a single true space character can go into the current flow,
     923                 :            :         // everything else breaks the flow
     924                 :    1839976 :     Space space = SPACE_START;
     925                 :    6866682 :     for (;;) {
     926   [ -  +  +  -  :    6866682 :         switch (peek()) {
                   +  + ]
     927                 :            :         case '\0': // i.e., EOF
     928                 :            :             throw css::uno::RuntimeException(
     929                 :            :                 (rtl::OUString(
     930                 :            :                     RTL_CONSTASCII_USTRINGPARAM("premature end of ")) +
     931                 :            :                  fileUrl_),
     932 [ #  # ][ #  # ]:          0 :                 css::uno::Reference< css::uno::XInterface >());
     933                 :            :         case '\x09':
     934                 :            :         case '\x0A':
     935                 :            :         case '\x0D':
     936      [ +  +  - ]:       3564 :             switch (space) {
     937                 :            :             case SPACE_START:
     938                 :            :             case SPACE_BREAK:
     939                 :       1944 :                 break;
     940                 :            :             case SPACE_NONE:
     941                 :            :             case SPACE_SPAN:
     942                 :       1620 :                 space = SPACE_BREAK;
     943                 :       1620 :                 break;
     944                 :            :             }
     945                 :       3564 :             ++pos_;
     946                 :       3564 :             break;
     947                 :            :         case ' ':
     948   [ +  +  -  - ]:      30132 :             switch (space) {
     949                 :            :             case SPACE_START:
     950                 :            :             case SPACE_BREAK:
     951                 :      13932 :                 break;
     952                 :            :             case SPACE_NONE:
     953                 :      16200 :                 space = SPACE_SPAN;
     954                 :      16200 :                 break;
     955                 :            :             case SPACE_SPAN:
     956                 :          0 :                 space = SPACE_BREAK;
     957                 :          0 :                 break;
     958                 :            :             }
     959                 :      30132 :             ++pos_;
     960                 :      30132 :             break;
     961                 :            :         case '&':
     962   [ #  #  #  # ]:          0 :             switch (space) {
     963                 :            :             case SPACE_START:
     964                 :          0 :                 break;
     965                 :            :             case SPACE_NONE:
     966                 :            :             case SPACE_SPAN:
     967                 :          0 :                 pad_.add(flowBegin, pos_ - flowBegin);
     968                 :          0 :                 break;
     969                 :            :             case SPACE_BREAK:
     970                 :          0 :                 pad_.add(flowBegin, flowEnd - flowBegin);
     971                 :          0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
     972                 :          0 :                 break;
     973                 :            :             }
     974                 :          0 :             pos_ = handleReference(pos_, end_);
     975                 :          0 :             flowBegin = pos_;
     976                 :          0 :             flowEnd = pos_;
     977                 :          0 :             space = SPACE_NONE;
     978                 :          0 :             break;
     979                 :            :         case '<':
     980                 :    1840796 :             ++pos_;
     981   [ +  +  -  - ]:    1840796 :             switch (peek()) {
     982                 :            :             case '!':
     983                 :        820 :                 ++pos_;
     984         [ +  - ]:        820 :                 if (skipComment()) {
     985                 :        820 :                     space = SPACE_BREAK;
     986                 :            :                 } else {
     987         [ #  # ]:          0 :                     Span cdata(scanCdataSection());
     988         [ #  # ]:          0 :                     if (cdata.is()) {
     989                 :            :                         // CDATA is not normalized (similar to character
     990                 :            :                         // references; it keeps the code simple), but it might
     991                 :            :                         // arguably be better to normalize it:
     992   [ #  #  #  # ]:          0 :                         switch (space) {
     993                 :            :                         case SPACE_START:
     994                 :          0 :                             break;
     995                 :            :                         case SPACE_NONE:
     996                 :            :                         case SPACE_SPAN:
     997         [ #  # ]:          0 :                             pad_.add(flowBegin, pos_ - flowBegin);
     998                 :          0 :                             break;
     999                 :            :                         case SPACE_BREAK:
    1000         [ #  # ]:          0 :                             pad_.add(flowBegin, flowEnd - flowBegin);
    1001         [ #  # ]:          0 :                             pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
    1002                 :          0 :                             break;
    1003                 :            :                         }
    1004         [ #  # ]:          0 :                         normalizeLineEnds(cdata);
    1005                 :          0 :                         flowBegin = pos_;
    1006                 :          0 :                         flowEnd = pos_;
    1007                 :          0 :                         space = SPACE_NONE;
    1008                 :            :                     } else {
    1009         [ #  # ]:          0 :                         skipDocumentTypeDeclaration();
    1010                 :            :                     }
    1011                 :            :                 }
    1012                 :        820 :                 break;
    1013                 :            :             case '/':
    1014                 :    1839976 :                 ++pos_;
    1015                 :    1839976 :                 pad_.add(flowBegin, flowEnd - flowBegin);
    1016                 :    1839976 :                 *text = pad_.get();
    1017                 :    1839976 :                 state_ = STATE_END_TAG;
    1018                 :    1839976 :                 return RESULT_TEXT;
    1019                 :            :             case '?':
    1020                 :          0 :                 ++pos_;
    1021                 :          0 :                 skipProcessingInstruction();
    1022                 :          0 :                 space = SPACE_BREAK;
    1023                 :          0 :                 break;
    1024                 :            :             default:
    1025                 :          0 :                 pad_.add(flowBegin, flowEnd - flowBegin);
    1026                 :          0 :                 *text = pad_.get();
    1027                 :          0 :                 state_ = STATE_START_TAG;
    1028                 :          0 :                 return RESULT_TEXT;
    1029                 :            :             }
    1030                 :        820 :             break;
    1031                 :            :         default:
    1032   [ +  +  +  - ]:    4992190 :             switch (space) {
    1033                 :            :             case SPACE_START:
    1034                 :    1839812 :                 flowBegin = pos_;
    1035                 :    1839812 :                 break;
    1036                 :            :             case SPACE_NONE:
    1037                 :            :             case SPACE_SPAN:
    1038                 :    3150918 :                 break;
    1039                 :            :             case SPACE_BREAK:
    1040                 :       1460 :                 pad_.add(flowBegin, flowEnd - flowBegin);
    1041                 :       1460 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM(" "));
    1042                 :       1460 :                 flowBegin = pos_;
    1043                 :       1460 :                 break;
    1044                 :            :             }
    1045                 :    4992190 :             flowEnd = ++pos_;
    1046                 :    4992190 :             space = SPACE_NONE;
    1047                 :    4992190 :             break;
    1048                 :            :         }
    1049                 :            :     }
    1050                 :            : }
    1051                 :            : 
    1052                 :     268765 : int XmlReader::toNamespaceId(NamespaceIris::size_type pos) {
    1053                 :            :     assert(pos <= INT_MAX);
    1054                 :     268765 :     return static_cast< int >(pos);
    1055                 :            : }
    1056                 :            : 
    1057                 :            : }
    1058                 :            : 
    1059                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10