LCOV - code coverage report
Current view: top level - configmgr/source - valueparser.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 148 205 72.2 %
Date: 2015-06-13 12:38:46 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/sequence.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       50000 : bool parseHexDigit(char c, int * value) {
      52             :     assert(value != 0);
      53       50000 :     if (c >= '0' && c <= '9') {
      54       14500 :         *value = c - '0';
      55       14500 :         return true;
      56             :     }
      57       35500 :     if (c >= 'A' && c <= 'F') {
      58       26250 :         *value = c - 'A' + 10;
      59       26250 :         return true;
      60             :     }
      61        9250 :     if (c >= 'a' && c <= 'f') {
      62        9250 :         *value = c - 'a' + 10;
      63        9250 :         return true;
      64             :     }
      65           0 :     return false;
      66             : }
      67             : 
      68      585764 : bool parseValue(xmlreader::Span const & text, sal_Bool * value) {
      69             :     assert(text.is() && value != 0);
      70      585764 :     if (text.equals("true") || text.equals("1")) {
      71      340774 :         *value = true;
      72      340774 :         return true;
      73             :     }
      74      244990 :     if (text.equals("false") || text.equals("0")) {
      75      244990 :         *value = false;
      76      244990 :         return true;
      77             :     }
      78           0 :     return false;
      79             : }
      80             : 
      81       22878 : 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       22878 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
      88             :         static_cast< sal_Int32 >(
      89             :             OString(
      90             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
      91       22878 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt32(16)) :
      92       45756 :         OString(text.begin, text.length).toInt32();
      93             :         //TODO: check valid lexical representation
      94       22878 :     if (n >= SAL_MIN_INT16 && n <= SAL_MAX_INT16) {
      95       22878 :         *value = static_cast< sal_Int16 >(n);
      96       22878 :         return true;
      97             :     }
      98           0 :     return false;
      99             : }
     100             : 
     101      921616 : 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      921616 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
     108             :         static_cast< sal_Int32 >(
     109             :             OString(
     110             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
     111      921616 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt32(16)) :
     112     1843232 :         OString(text.begin, text.length).toInt32();
     113             :         //TODO: check valid lexical representation
     114      921616 :     return true;
     115             : }
     116             : 
     117       10750 : 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       10750 :             RTL_CONSTASCII_LENGTH("0X")) == 0 ?
     124             :         static_cast< sal_Int64 >(
     125             :             OString(
     126             :                 text.begin + RTL_CONSTASCII_LENGTH("0X"),
     127       10750 :                 text.length - RTL_CONSTASCII_LENGTH("0X")).toUInt64(16)) :
     128       21500 :         OString(text.begin, text.length).toInt64();
     129             :         //TODO: check valid lexical representation
     130       10750 :     return true;
     131             : }
     132             : 
     133       20000 : bool parseValue(xmlreader::Span const & text, double * value) {
     134             :     assert(text.is() && value != 0);
     135       20000 :     *value = OString(text.begin, text.length).toDouble();
     136             :         //TODO: check valid lexical representation
     137       20000 :     return true;
     138             : }
     139             : 
     140     3740123 : bool parseValue(xmlreader::Span const & text, OUString * value) {
     141             :     assert(text.is() && value != 0);
     142     3740123 :     *value = text.convertFromUtf8();
     143     3740123 :     return true;
     144             : }
     145             : 
     146        8250 : bool parseValue(
     147             :     xmlreader::Span const & text, css::uno::Sequence< sal_Int8 > * value)
     148             : {
     149             :     assert(text.is() && value != 0);
     150        8250 :     if ((text.length & 1) != 0) {
     151           0 :         return false;
     152             :     }
     153        8250 :     std::vector< sal_Int8 > seq;
     154       41500 :     for (sal_Int32 i = 0; i != text.length;) {
     155             :         int n1;
     156             :         int n2;
     157       50000 :         if (!parseHexDigit(text.begin[i++], &n1) ||
     158       25000 :             !parseHexDigit(text.begin[i++], &n2))
     159             :         {
     160           0 :             return false;
     161             :         }
     162       25000 :         seq.push_back(static_cast< sal_Int8 >((n1 << 4) | n2));
     163             :     }
     164        8250 :     *value = comphelper::containerToSequence(seq);
     165        8250 :     return true;
     166             : }
     167             : 
     168     4677881 : template< typename T > css::uno::Any parseSingleValue(
     169             :     xmlreader::Span const & text)
     170             : {
     171     3133373 :     T val;
     172     4677881 :     if (!parseValue(text, &val)) {
     173           0 :         throw css::uno::RuntimeException("invalid value");
     174             :     }
     175     4677881 :     return css::uno::makeAny(val);
     176             : }
     177             : 
     178      242750 : template< typename T > css::uno::Any parseListValue(
     179             :     OString const & separator, xmlreader::Span const & text)
     180             : {
     181      242750 :     std::vector< T > seq;
     182      242750 :     xmlreader::Span sep;
     183      242750 :     if (separator.isEmpty()) {
     184      212250 :         sep = xmlreader::Span(RTL_CONSTASCII_STRINGPARAM(" "));
     185             :     } else {
     186       30500 :         sep = xmlreader::Span(separator.getStr(), separator.getLength());
     187             :     }
     188      242750 :     if (text.length != 0) {
     189      631500 :         for (xmlreader::Span t(text);;) {
     190             :             sal_Int32 i = rtl_str_indexOfStr_WithLength(
     191      631500 :                 t.begin, t.length, sep.begin, sep.length);
     192      615000 :             T val;
     193     1263000 :             if (!parseValue(
     194     1263000 :                     xmlreader::Span(t.begin, i == -1 ? t.length : i), &val))
     195             :             {
     196           0 :                 throw css::uno::RuntimeException("invalid value");
     197             :             }
     198      631500 :             seq.push_back(val);
     199      631500 :             if (i < 0) {
     200      204250 :                 break;
     201             :             }
     202      427250 :             t.begin += i + sep.length;
     203      427250 :             t.length -= i + sep.length;
     204             :         }
     205             :     }
     206      242750 :     return css::uno::makeAny(comphelper::containerToSequence(seq));
     207             : }
     208             : 
     209     4920631 : css::uno::Any parseValue(
     210             :     OString const & separator, xmlreader::Span const & text, Type type)
     211             : {
     212     4920631 :     switch (type) {
     213             :     case TYPE_ANY:
     214           0 :         throw css::uno::RuntimeException("invalid value of type any");
     215             :     case TYPE_BOOLEAN:
     216      585764 :         return parseSingleValue< sal_Bool >(text);
     217             :     case TYPE_SHORT:
     218       22878 :         return parseSingleValue< sal_Int16 >(text);
     219             :     case TYPE_INT:
     220      908116 :         return parseSingleValue< sal_Int32 >(text);
     221             :     case TYPE_LONG:
     222        7750 :         return parseSingleValue< sal_Int64 >(text);
     223             :     case TYPE_DOUBLE:
     224       20000 :         return parseSingleValue< double >(text);
     225             :     case TYPE_STRING:
     226     3125123 :         return parseSingleValue< OUString >(text);
     227             :     case TYPE_HEXBINARY:
     228        8250 :         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         750 :         return parseListValue< sal_Int32 >(separator, text);
     235             :     case TYPE_LONG_LIST:
     236         250 :         return parseListValue< sal_Int64 >(separator, text);
     237             :     case TYPE_DOUBLE_LIST:
     238           0 :         return parseListValue< double >(separator, text);
     239             :     case TYPE_STRING_LIST:
     240      241750 :         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       73515 : ValueParser::ValueParser(int layer): type_(TYPE_ERROR), layer_(layer), state_() {}
     253             : 
     254       73515 : ValueParser::~ValueParser() {}
     255             : 
     256    29759697 : xmlreader::XmlReader::Text ValueParser::getTextMode() const {
     257    29759697 :     if (node_.is()) {
     258     9595742 :         switch (state_) {
     259             :         case STATE_TEXT:
     260     9515922 :             if (!items_.empty()) {
     261       39910 :                 break;
     262             :             }
     263             :             // fall through
     264             :         case STATE_IT:
     265             :             return
     266    16310004 :                 (type_ == TYPE_STRING || type_ == TYPE_STRING_LIST ||
     267     3107266 :                  !separator_.isEmpty())
     268             :                 ? xmlreader::XmlReader::TEXT_RAW
     269    16004398 :                 : xmlreader::XmlReader::TEXT_NORMALIZED;
     270             :         default:
     271           0 :             break;
     272             :         }
     273             :     }
     274    20203865 :     return xmlreader::XmlReader::TEXT_NONE;
     275             : }
     276             : 
     277    12602619 : bool ValueParser::startElement(
     278             :     xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name,
     279             :     std::set< OUString > const *)
     280             : {
     281    12602619 :     if (!node_.is()) {
     282    12562709 :         return false;
     283             :     }
     284       39910 :     switch (state_) {
     285             :     case STATE_TEXT:
     286      119730 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && name.equals("it") &&
     287      119730 :             isListType(type_) && separator_.isEmpty())
     288             :         {
     289       39910 :             pad_.clear();
     290             :                 // before first <it>, characters are not ignored; assume they
     291             :                 // are only whitespace
     292       39910 :             state_ = STATE_IT;
     293       39910 :             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    12602619 : bool ValueParser::endElement() {
     342    12602619 :     if (!node_.is()) {
     343     7674578 :         return false;
     344             :     }
     345     4928041 :     switch (state_) {
     346             :     case STATE_TEXT:
     347             :         {
     348     4888131 :             css::uno::Any *pValue = NULL;
     349             : 
     350     4888131 :             switch (node_->kind()) {
     351             :             case Node::KIND_PROPERTY:
     352     3306139 :                 pValue = static_cast< PropertyNode * >(node_.get())->getValuePtr(layer_);
     353     3306139 :                 break;
     354             :             case Node::KIND_LOCALIZED_PROPERTY:
     355             :                 {
     356     1581992 :                     NodeMap & members = node_->getMembers();
     357     1581992 :                     NodeMap::iterator i(members.find(localizedName_));
     358             :                     LocalizedValueNode *pLVNode;
     359     1581992 :                     if (i == members.end()) {
     360     1554000 :                         pLVNode = new LocalizedValueNode(layer_);
     361             :                         members.insert(
     362     1554000 :                             NodeMap::value_type(localizedName_, pLVNode ));
     363             :                     } else {
     364       27992 :                         pLVNode = static_cast< LocalizedValueNode * >(i->second.get());
     365             :                     }
     366     1581992 :                     pValue = pLVNode->getValuePtr(layer_);
     367             :                 }
     368     1581992 :                 break;
     369             :             default:
     370             :                 assert(false); // this cannot happen
     371           0 :                 return false;
     372             :             }
     373             : 
     374     4888131 :             if (items_.empty()) {
     375     4880721 :                 *pValue = parseValue(separator_, pad_.get(), type_);
     376     4880721 :                 pad_.clear();
     377             :             } else {
     378        7410 :                 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        7410 :                     *pValue = convertItems< OUString >();
     396        7410 :                     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        7410 :                 items_.clear();
     405             :             }
     406     4888131 :             separator_.clear();
     407     4888131 :             node_.clear();
     408             :         }
     409     4888131 :         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       39910 :             parseValue(OString(), pad_.get(), elementType(type_)));
     417       39910 :         pad_.clear();
     418       39910 :         state_ = STATE_TEXT;
     419       39910 :         break;
     420             :     }
     421     4928041 :     return true;
     422             : }
     423             : 
     424     4627791 : void ValueParser::characters(xmlreader::Span const & text) {
     425     4627791 :     if (node_.is()) {
     426             :         assert(state_ == STATE_TEXT || state_ == STATE_IT);
     427     4627791 :         pad_.add(text.begin, text.length);
     428             :     }
     429     4627791 : }
     430             : 
     431     4888131 : void ValueParser::start(
     432             :     rtl::Reference< Node > const & node, OUString const & localizedName)
     433             : {
     434             :     assert(node.is() && !node_.is());
     435     4888131 :     node_ = node;
     436     4888131 :     localizedName_ = localizedName;
     437     4888131 :     state_ = STATE_TEXT;
     438     4888131 : }
     439             : 
     440             : 
     441        7410 : template< typename T > css::uno::Any ValueParser::convertItems() {
     442        7410 :     css::uno::Sequence< T > seq(items_.size());
     443       47320 :     for (sal_Int32 i = 0; i < seq.getLength(); ++i) {
     444       39910 :         bool ok = (items_[i] >>= seq[i]);
     445             :         assert(ok);
     446             :         (void) ok; // avoid warnings
     447             :     }
     448        7410 :     return css::uno::makeAny(seq);
     449             : }
     450             : 
     451             : }
     452             : 
     453             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11