LCOV - code coverage report
Current view: top level - configmgr/source - valueparser.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 148 205 72.2 %
Date: 2014-11-03 Functions: 27 37 73.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             : /*
       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 <set>
      24             : 
      25             : #include <com/sun/star/uno/Any.hxx>
      26             : #include <com/sun/star/uno/Reference.hxx>
      27             : #include <com/sun/star/uno/RuntimeException.hpp>
      28             : #include <com/sun/star/uno/Sequence.hxx>
      29             : #include <com/sun/star/uno/XInterface.hpp>
      30             : #include <comphelper/sequenceasvector.hxx>
      31             : #include <rtl/string.h>
      32             : #include <rtl/string.hxx>
      33             : #include <rtl/ustring.hxx>
      34             : #include <sal/types.h>
      35             : #include <xmlreader/span.hxx>
      36             : #include <xmlreader/xmlreader.hxx>
      37             : 
      38             : #include "localizedvaluenode.hxx"
      39             : #include "node.hxx"
      40             : #include "nodemap.hxx"
      41             : #include "parsemanager.hxx"
      42             : #include "propertynode.hxx"
      43             : #include "type.hxx"
      44             : #include "valueparser.hxx"
      45             : #include "xmldata.hxx"
      46             : 
      47             : namespace configmgr {
      48             : 
      49             : namespace {
      50             : 
      51       76200 : bool parseHexDigit(char c, int * value) {
      52             :     assert(value != 0);
      53       76200 :     if (c >= '0' && c <= '9') {
      54       22098 :         *value = c - '0';
      55       22098 :         return true;
      56             :     }
      57       54102 :     if (c >= 'A' && c <= 'F') {
      58       40005 :         *value = c - 'A' + 10;
      59       40005 :         return true;
      60             :     }
      61       14097 :     if (c >= 'a' && c <= 'f') {
      62       14097 :         *value = c - 'a' + 10;
      63       14097 :         return true;
      64             :     }
      65           0 :     return false;
      66             : }
      67             : 
      68      895547 : bool parseValue(xmlreader::Span const & text, sal_Bool * value) {
      69             :     assert(text.is() && value != 0);
      70      895547 :     if (text.equals("true") || text.equals("1")) {
      71      521334 :         *value = true;
      72      521334 :         return true;
      73             :     }
      74      374213 :     if (text.equals("false") || text.equals("0")) {
      75      374213 :         *value = false;
      76      374213 :         return true;
      77             :     }
      78           0 :     return false;
      79             : }
      80             : 
      81       34867 : bool parseValue(xmlreader::Span const & text, sal_Int16 * value) {
      82             :     assert(text.is() && value != 0);
      83             :     // For backwards compatibility, support hexadecimal values:
      84             :     sal_Int32 n =
      85             :         rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
      86             :             text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
      87       34867 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
      88             :         static_cast< sal_Int32 >(
      89             :             OString(
      90             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
      91       34867 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt32(16)) :
      92       69734 :         OString(text.begin, text.length).toInt32();
      93             :         //TODO: check valid lexical representation
      94       34867 :     if (n >= SAL_MIN_INT16 && n <= SAL_MAX_INT16) {
      95       34867 :         *value = static_cast< sal_Int16 >(n);
      96       34867 :         return true;
      97             :     }
      98           0 :     return false;
      99             : }
     100             : 
     101     1386789 : bool parseValue(xmlreader::Span const & text, sal_Int32 * value) {
     102             :     assert(text.is() && value != 0);
     103             :     // For backwards compatibility, support hexadecimal values:
     104             :     *value =
     105             :         rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     106             :             text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
     107     1386789 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
     108             :         static_cast< sal_Int32 >(
     109             :             OString(
     110             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
     111     1386789 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt32(16)) :
     112     2773578 :         OString(text.begin, text.length).toInt32();
     113             :         //TODO: check valid lexical representation
     114     1386789 :     return true;
     115             : }
     116             : 
     117       16383 : bool parseValue(xmlreader::Span const & text, sal_Int64 * value) {
     118             :     assert(text.is() && value != 0);
     119             :     // For backwards compatibility, support hexadecimal values:
     120             :     *value =
     121             :         rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     122             :             text.begin, text.length, RTL_CONSTASCII_STRINGPARAM("0X"),
     123       16383 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
     124             :         static_cast< sal_Int64 >(
     125             :             OString(
     126             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
     127       16383 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt64(16)) :
     128       32766 :         OString(text.begin, text.length).toInt64();
     129             :         //TODO: check valid lexical representation
     130       16383 :     return true;
     131             : }
     132             : 
     133       30480 : bool parseValue(xmlreader::Span const & text, double * value) {
     134             :     assert(text.is() && value != 0);
     135       30480 :     *value = OString(text.begin, text.length).toDouble();
     136             :         //TODO: check valid lexical representation
     137       30480 :     return true;
     138             : }
     139             : 
     140     5644435 : bool parseValue(xmlreader::Span const & text, OUString * value) {
     141             :     assert(text.is() && value != 0);
     142     5644435 :     *value = text.convertFromUtf8();
     143     5644435 :     return true;
     144             : }
     145             : 
     146       12573 : bool parseValue(
     147             :     xmlreader::Span const & text, css::uno::Sequence< sal_Int8 > * value)
     148             : {
     149             :     assert(text.is() && value != 0);
     150       12573 :     if ((text.length & 1) != 0) {
     151           0 :         return false;
     152             :     }
     153       12573 :     comphelper::SequenceAsVector< sal_Int8 > seq;
     154       63246 :     for (sal_Int32 i = 0; i != text.length;) {
     155             :         int n1;
     156             :         int n2;
     157       76200 :         if (!parseHexDigit(text.begin[i++], &n1) ||
     158       38100 :             !parseHexDigit(text.begin[i++], &n2))
     159             :         {
     160           0 :             return false;
     161             :         }
     162       38100 :         seq.push_back(static_cast< sal_Int8 >((n1 << 4) | n2));
     163             :     }
     164       12573 :     *value = seq.getAsConstList();
     165       12573 :     return true;
     166             : }
     167             : 
     168     7072384 : template< typename T > css::uno::Any parseSingleValue(
     169             :     xmlreader::Span const & text)
     170             : {
     171     4733464 :     T val;
     172     7072384 :     if (!parseValue(text, &val)) {
     173           0 :         throw css::uno::RuntimeException("invalid value");
     174             :     }
     175     7072384 :     return css::uno::makeAny(val);
     176             : }
     177             : 
     178      364236 : template< typename T > css::uno::Any parseListValue(
     179             :     OString const & separator, xmlreader::Span const & text)
     180             : {
     181      364236 :     comphelper::SequenceAsVector< T > seq;
     182      364236 :     xmlreader::Span sep;
     183      364236 :     if (separator.isEmpty()) {
     184      319659 :         sep = xmlreader::Span(RTL_CONSTASCII_STRINGPARAM(" "));
     185             :     } else {
     186       44577 :         sep = xmlreader::Span(separator.getStr(), separator.getLength());
     187             :     }
     188      364236 :     if (text.length != 0) {
     189      948690 :         for (xmlreader::Span t(text);;) {
     190             :             sal_Int32 i = rtl_str_indexOfStr_WithLength(
     191      948690 :                 t.begin, t.length, sep.begin, sep.length);
     192      923544 :             T val;
     193     1897380 :             if (!parseValue(
     194     1897380 :                     xmlreader::Span(t.begin, i == -1 ? t.length : i), &val))
     195             :             {
     196           0 :                 throw css::uno::RuntimeException("invalid value");
     197             :             }
     198      948690 :             seq.push_back(val);
     199      948690 :             if (i < 0) {
     200      306705 :                 break;
     201             :             }
     202      641985 :             t.begin += i + sep.length;
     203      641985 :             t.length -= i + sep.length;
     204             :         }
     205             :     }
     206      364236 :     return css::uno::makeAny(seq.getAsConstList());
     207             : }
     208             : 
     209     7436620 : css::uno::Any parseValue(
     210             :     OString const & separator, xmlreader::Span const & text, Type type)
     211             : {
     212     7436620 :     switch (type) {
     213             :     case TYPE_ANY:
     214           0 :         throw css::uno::RuntimeException("invalid value of type any");
     215             :     case TYPE_BOOLEAN:
     216      895547 :         return parseSingleValue< sal_Bool >(text);
     217             :     case TYPE_SHORT:
     218       34867 :         return parseSingleValue< sal_Int16 >(text);
     219             :     case TYPE_INT:
     220     1366215 :         return parseSingleValue< sal_Int32 >(text);
     221             :     case TYPE_LONG:
     222       11811 :         return parseSingleValue< sal_Int64 >(text);
     223             :     case TYPE_DOUBLE:
     224       30480 :         return parseSingleValue< double >(text);
     225             :     case TYPE_STRING:
     226     4720891 :         return parseSingleValue< OUString >(text);
     227             :     case TYPE_HEXBINARY:
     228       12573 :         return parseSingleValue< css::uno::Sequence< sal_Int8 > >(text);
     229             :     case TYPE_BOOLEAN_LIST:
     230           0 :         return parseListValue< sal_Bool >(separator, text);
     231             :     case TYPE_SHORT_LIST:
     232           0 :         return parseListValue< sal_Int16 >(separator, text);
     233             :     case TYPE_INT_LIST:
     234        1143 :         return parseListValue< sal_Int32 >(separator, text);
     235             :     case TYPE_LONG_LIST:
     236         381 :         return parseListValue< sal_Int64 >(separator, text);
     237             :     case TYPE_DOUBLE_LIST:
     238           0 :         return parseListValue< double >(separator, text);
     239             :     case TYPE_STRING_LIST:
     240      362712 :         return parseListValue< OUString >(separator, text);
     241             :     case TYPE_HEXBINARY_LIST:
     242             :         return parseListValue< css::uno::Sequence< sal_Int8 > >(
     243           0 :             separator, text);
     244             :     default:
     245             :         assert(false);
     246           0 :         throw css::uno::RuntimeException("this cannot happen");
     247             :     }
     248             : }
     249             : 
     250             : }
     251             : 
     252      116940 : ValueParser::ValueParser(int layer): type_(TYPE_ERROR), layer_(layer), state_() {}
     253             : 
     254      116940 : ValueParser::~ValueParser() {}
     255             : 
     256    45056071 : xmlreader::XmlReader::Text ValueParser::getTextMode() const {
     257    45056071 :     if (node_.is()) {
     258    14502702 :         switch (state_) {
     259             :         case STATE_TEXT:
     260    14380660 :             if (!items_.empty()) {
     261       61021 :                 break;
     262             :             }
     263             :             // fall through
     264             :         case STATE_IT:
     265             :             return
     266    24668182 :                 (type_ == TYPE_STRING || type_ == TYPE_STRING_LIST ||
     267     4705653 :                  !separator_.isEmpty())
     268             :                 ? xmlreader::XmlReader::TEXT_RAW
     269    24177709 :                 : xmlreader::XmlReader::TEXT_NORMALIZED;
     270             :         default:
     271           0 :             break;
     272             :         }
     273             :     }
     274    30614390 :     return xmlreader::XmlReader::TEXT_NONE;
     275             : }
     276             : 
     277    19090158 : bool ValueParser::startElement(
     278             :     xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name,
     279             :     std::set< OUString > const *)
     280             : {
     281    19090158 :     if (!node_.is()) {
     282    19029137 :         return false;
     283             :     }
     284       61021 :     switch (state_) {
     285             :     case STATE_TEXT:
     286      183063 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && name.equals("it") &&
     287      183063 :             isListType(type_) && separator_.isEmpty())
     288             :         {
     289       61021 :             pad_.clear();
     290             :                 // before first <it>, characters are not ignored; assume they
     291             :                 // are only whitespace
     292       61021 :             state_ = STATE_IT;
     293       61021 :             return true;
     294             :         }
     295             :         // fall through
     296             :     case STATE_IT:
     297           0 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     298           0 :             name.equals("unicode") &&
     299           0 :             (type_ == TYPE_STRING || type_ == TYPE_STRING_LIST))
     300             :         {
     301           0 :             sal_Int32 scalar = -1;
     302             :             for (;;) {
     303             :                 int attrNsId;
     304           0 :                 xmlreader::Span attrLn;
     305           0 :                 if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     306           0 :                     break;
     307             :                 }
     308           0 :                 if (attrNsId == ParseManager::NAMESPACE_OOR &&
     309           0 :                     attrLn.equals("scalar"))
     310             :                 {
     311           0 :                     if (!parseValue(reader.getAttributeValue(true), &scalar)) {
     312           0 :                         scalar = -1;
     313             :                     }
     314           0 :                     break;
     315             :                 }
     316           0 :             }
     317           0 :             if (scalar >= 0 && scalar < 0x20 && scalar != 0x09 &&
     318           0 :                 scalar != 0x0A && scalar != 0x0D)
     319             :             {
     320           0 :                 char c = static_cast< char >(scalar);
     321           0 :                 pad_.add(&c, 1);
     322           0 :             } else if (scalar == 0xFFFE) {
     323           0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM("\xEF\xBF\xBE"));
     324           0 :             } else if (scalar == 0xFFFF) {
     325           0 :                 pad_.add(RTL_CONSTASCII_STRINGPARAM("\xEF\xBF\xBF"));
     326             :             } else {
     327             :                 throw css::uno::RuntimeException(
     328           0 :                     "bad unicode scalar attribute in " + reader.getUrl());
     329             :             }
     330           0 :             state_ = State(state_ + 1);
     331           0 :             return true;
     332             :         }
     333           0 :         break;
     334             :     default:
     335           0 :         break;
     336             :     }
     337             :     throw css::uno::RuntimeException(
     338           0 :         "bad member <" + name.convertFromUtf8() + "> in " + reader.getUrl());
     339             : }
     340             : 
     341    19090158 : bool ValueParser::endElement() {
     342    19090158 :     if (!node_.is()) {
     343    11640908 :         return false;
     344             :     }
     345     7449250 :     switch (state_) {
     346             :     case STATE_TEXT:
     347             :         {
     348     7388229 :             css::uno::Any *pValue = NULL;
     349             : 
     350     7388229 :             switch (node_->kind()) {
     351             :             case Node::KIND_PROPERTY:
     352     5026883 :                 pValue = static_cast< PropertyNode * >(node_.get())->getValuePtr(layer_);
     353     5026883 :                 break;
     354             :             case Node::KIND_LOCALIZED_PROPERTY:
     355             :                 {
     356     2361346 :                     NodeMap & members = node_->getMembers();
     357     2361346 :                     NodeMap::iterator i(members.find(localizedName_));
     358             :                     LocalizedValueNode *pLVNode;
     359     2361346 :                     if (i == members.end()) {
     360     2360134 :                         pLVNode = new LocalizedValueNode(layer_);
     361             :                         members.insert(
     362     2360134 :                             NodeMap::value_type(localizedName_, pLVNode ));
     363             :                     } else {
     364        1212 :                         pLVNode = static_cast< LocalizedValueNode * >(i->second.get());
     365             :                     }
     366     2361346 :                     pValue = pLVNode->getValuePtr(layer_);
     367             :                 }
     368     2361346 :                 break;
     369             :             default:
     370             :                 assert(false); // this cannot happen
     371           0 :                 return false;
     372             :             }
     373             : 
     374     7388229 :             if (items_.empty()) {
     375     7375599 :                 *pValue = parseValue(separator_, pad_.get(), type_);
     376     7375599 :                 pad_.clear();
     377             :             } else {
     378       12630 :                 switch (type_) {
     379             :                 case TYPE_BOOLEAN_LIST:
     380           0 :                     *pValue = convertItems< sal_Bool >();
     381           0 :                     break;
     382             :                 case TYPE_SHORT_LIST:
     383           0 :                     *pValue = convertItems< sal_Int16 >();
     384           0 :                     break;
     385             :                 case TYPE_INT_LIST:
     386           0 :                     *pValue = convertItems< sal_Int32 >();
     387           0 :                     break;
     388             :                 case TYPE_LONG_LIST:
     389           0 :                     *pValue = convertItems< sal_Int64 >();
     390           0 :                     break;
     391             :                 case TYPE_DOUBLE_LIST:
     392           0 :                     *pValue = convertItems< double >();
     393           0 :                     break;
     394             :                 case TYPE_STRING_LIST:
     395       12630 :                     *pValue = convertItems< OUString >();
     396       12630 :                     break;
     397             :                 case TYPE_HEXBINARY_LIST:
     398           0 :                     *pValue = convertItems< css::uno::Sequence< sal_Int8 > >();
     399           0 :                     break;
     400             :                 default:
     401             :                     assert(false); // this cannot happen
     402           0 :                     break;
     403             :                 }
     404       12630 :                 items_.clear();
     405             :             }
     406     7388229 :             separator_ = OString();
     407     7388229 :             node_.clear();
     408             :         }
     409     7388229 :         break;
     410             :     case STATE_TEXT_UNICODE:
     411             :     case STATE_IT_UNICODE:
     412           0 :         state_ = State(state_ - 1);
     413           0 :         break;
     414             :     case STATE_IT:
     415             :         items_.push_back(
     416       61021 :             parseValue(OString(), pad_.get(), elementType(type_)));
     417       61021 :         pad_.clear();
     418       61021 :         state_ = STATE_TEXT;
     419       61021 :         break;
     420             :     }
     421     7449250 :     return true;
     422             : }
     423             : 
     424     6992431 : void ValueParser::characters(xmlreader::Span const & text) {
     425     6992431 :     if (node_.is()) {
     426             :         assert(state_ == STATE_TEXT || state_ == STATE_IT);
     427     6992431 :         pad_.add(text.begin, text.length);
     428             :     }
     429     6992431 : }
     430             : 
     431     7388229 : void ValueParser::start(
     432             :     rtl::Reference< Node > const & node, OUString const & localizedName)
     433             : {
     434             :     assert(node.is() && !node_.is());
     435     7388229 :     node_ = node;
     436     7388229 :     localizedName_ = localizedName;
     437     7388229 :     state_ = STATE_TEXT;
     438     7388229 : }
     439             : 
     440             : 
     441       12630 : template< typename T > css::uno::Any ValueParser::convertItems() {
     442       12630 :     css::uno::Sequence< T > seq(items_.size());
     443       73651 :     for (sal_Int32 i = 0; i < seq.getLength(); ++i) {
     444       61021 :         bool ok = (items_[i] >>= seq[i]);
     445             :         assert(ok);
     446             :         (void) ok; // avoid warnings
     447             :     }
     448       12630 :     return css::uno::makeAny(seq);
     449             : }
     450             : 
     451             : }
     452             : 
     453             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10