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

Generated by: LCOV version 1.10