LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/comphelper/source/misc - string.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 181 225 80.4 %
Date: 2013-07-09 Functions: 26 28 92.9 %
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 <cstddef>
      23             : #include <string.h>
      24             : #include <vector>
      25             : #include <algorithm>
      26             : 
      27             : #include <rtl/ustring.hxx>
      28             : #include <rtl/ustrbuf.hxx>
      29             : #include <rtl/string.hxx>
      30             : #include <rtl/strbuf.hxx>
      31             : #include <sal/types.h>
      32             : 
      33             : #include <comphelper/string.hxx>
      34             : #include <comphelper/stlunosequence.hxx>
      35             : #include <comphelper/stl_types.hxx>
      36             : 
      37             : #include <com/sun/star/i18n/BreakIterator.hpp>
      38             : #include <com/sun/star/i18n/CharType.hpp>
      39             : #include <com/sun/star/i18n/Collator.hpp>
      40             : 
      41             : 
      42             : namespace comphelper { namespace string {
      43             : 
      44             : namespace
      45             : {
      46       16595 :     template <typename T, typename C> T tmpl_stripStart(const T &rIn,
      47             :         const C cRemove)
      48             :     {
      49       16595 :         if (rIn.isEmpty())
      50           1 :             return rIn;
      51             : 
      52       16594 :         sal_Int32 i = 0;
      53             : 
      54       35126 :         while (i < rIn.getLength())
      55             :         {
      56       18484 :             if (rIn[i] != cRemove)
      57       16546 :                 break;
      58        1938 :             ++i;
      59             :         }
      60             : 
      61       16594 :         return rIn.copy(i);
      62             :     }
      63             : }
      64             : 
      65        1858 : OString stripStart(const OString &rIn, sal_Char c)
      66             : {
      67        1858 :     return tmpl_stripStart<OString, sal_Char>(rIn, c);
      68             : }
      69             : 
      70       14737 : OUString stripStart(const OUString &rIn, sal_Unicode c)
      71             : {
      72       14737 :     return tmpl_stripStart<OUString, sal_Unicode>(rIn, c);
      73             : }
      74             : 
      75             : namespace
      76             : {
      77       22858 :     template <typename T, typename C> T tmpl_stripEnd(const T &rIn,
      78             :         const C cRemove)
      79             :     {
      80       22858 :         if (rIn.isEmpty())
      81          92 :             return rIn;
      82             : 
      83       22766 :         sal_Int32 i = rIn.getLength();
      84             : 
      85       47624 :         while (i > 0)
      86             :         {
      87       24653 :             if (rIn[i-1] != cRemove)
      88       22561 :                 break;
      89        2092 :             --i;
      90             :         }
      91             : 
      92       22766 :         return rIn.copy(0, i);
      93             :     }
      94             : }
      95             : 
      96         204 : OString stripEnd(const OString &rIn, sal_Char c)
      97             : {
      98         204 :     return tmpl_stripEnd<OString, sal_Char>(rIn, c);
      99             : }
     100             : 
     101       22654 : OUString stripEnd(const OUString &rIn, sal_Unicode c)
     102             : {
     103       22654 :     return tmpl_stripEnd<OUString, sal_Unicode>(rIn, c);
     104             : }
     105             : 
     106         200 : OString strip(const OString &rIn, sal_Char c)
     107             : {
     108         200 :     return stripEnd(stripStart(rIn, c), c);
     109             : }
     110             : 
     111       14574 : OUString strip(const OUString &rIn, sal_Unicode c)
     112             : {
     113       14574 :     return stripEnd(stripStart(rIn, c), c);
     114             : }
     115             : 
     116             : namespace
     117             : {
     118      169567 :     template <typename T, typename C> sal_Int32 tmpl_getTokenCount(const T &rIn,
     119             :         C cTok)
     120             :     {
     121             :         // Empty String: TokenCount by Definition is 0
     122      169567 :         if (rIn.isEmpty())
     123          21 :             return 0;
     124             : 
     125      169546 :         sal_Int32 nTokCount = 1;
     126     2891441 :         for (sal_Int32 i = 0; i < rIn.getLength(); ++i)
     127             :         {
     128     2721895 :             if (rIn[i] == cTok)
     129       79548 :                 ++nTokCount;
     130             :         }
     131      169546 :         return nTokCount;
     132             :     }
     133             : }
     134             : 
     135      167664 : sal_Int32 getTokenCount(const OString &rIn, sal_Char cTok)
     136             : {
     137      167664 :     return tmpl_getTokenCount<OString, sal_Char>(rIn, cTok);
     138             : }
     139             : 
     140        1903 : sal_Int32 getTokenCount(const OUString &rIn, sal_Unicode cTok)
     141             : {
     142        1903 :     return tmpl_getTokenCount<OUString, sal_Unicode>(rIn, cTok);
     143             : }
     144             : 
     145      172613 : sal_uInt32 decimalStringToNumber(
     146             :     OUString const & str )
     147             : {
     148      172613 :     sal_uInt32 result = 0;
     149      522079 :     for( sal_Int32 i = 0 ; i < str.getLength() ; )
     150             :     {
     151      176853 :         sal_uInt32 c = str.iterateCodePoints(&i);
     152      176853 :         sal_uInt32 value = 0;
     153      176853 :         if( c <= 0x0039)    // ASCII decimal digits, most common
     154      176850 :             value = c - 0x0030;
     155           3 :         else if( c >= 0x1D7F6 )    // mathematical monospace digits
     156           2 :             value = c - 0x1D7F6;
     157           1 :         else if( c >= 0x1D7EC ) // mathematical sans-serif bold digits
     158           0 :             value = c - 0x1D7EC;
     159           1 :         else if( c >= 0x1D7E2 ) // mathematical sans-serif digits
     160           0 :             value = c - 0x1D7E2;
     161           1 :         else if( c >= 0x1D7D8 ) // mathematical double-struck digits
     162           0 :             value = c - 0x1D7D8;
     163           1 :         else if( c >= 0x1D7CE ) // mathematical bold digits
     164           0 :             value = c - 0x1D7CE;
     165           1 :         else if( c >= 0x11066 ) // brahmi digits
     166           0 :             value = c - 0x11066;
     167           1 :         else if( c >= 0x104A0 ) // osmanya digits
     168           0 :             value = c - 0x104A0;
     169           1 :         else if( c >= 0xFF10 ) // fullwidth digits
     170           0 :             value = c - 0xFF10;
     171           1 :         else if( c >= 0xABF0 ) // meetei mayek digits
     172           0 :             value = c - 0xABF0;
     173           1 :         else if( c >= 0xAA50 ) // cham digits
     174           0 :             value = c - 0xAA50;
     175           1 :         else if( c >= 0xA9D0 ) // javanese digits
     176           0 :             value = c - 0xA9D0;
     177           1 :         else if( c >= 0xA900 ) // kayah li digits
     178           0 :             value = c - 0xA900;
     179           1 :         else if( c >= 0xA8D0 ) // saurashtra digits
     180           0 :             value = c - 0xA8D0;
     181           1 :         else if( c >= 0xA620 ) // vai digits
     182           0 :             value = c - 0xA620;
     183           1 :         else if( c >= 0x1C50 ) // ol chiki digits
     184           0 :             value = c - 0x1C50;
     185           1 :         else if( c >= 0x1C40 ) // lepcha digits
     186           0 :             value = c - 0x1C40;
     187           1 :         else if( c >= 0x1BB0 ) // sundanese digits
     188           0 :             value = c - 0x1BB0;
     189           1 :         else if( c >= 0x1B50 ) // balinese digits
     190           0 :             value = c - 0x1B50;
     191           1 :         else if( c >= 0x1A90 ) // tai tham tham digits
     192           0 :             value = c - 0x1A90;
     193           1 :         else if( c >= 0x1A80 ) // tai tham hora digits
     194           0 :             value = c - 0x1A80;
     195           1 :         else if( c >= 0x19D0 ) // new tai lue digits
     196           0 :             value = c - 0x19D0;
     197           1 :         else if( c >= 0x1946 ) // limbu digits
     198           0 :             value = c - 0x1946;
     199           1 :         else if( c >= 0x1810 ) // mongolian digits
     200           0 :             value = c - 0x1810;
     201           1 :         else if( c >= 0x17E0 ) // khmer digits
     202           0 :             value = c - 0x17E0;
     203           1 :         else if( c >= 0x1090 ) // myanmar shan digits
     204           0 :             value = c - 0x1090;
     205           1 :         else if( c >= 0x1040 ) // myanmar digits
     206           0 :             value = c - 0x1040;
     207           1 :         else if( c >= 0x0F20 ) // tibetan digits
     208           0 :             value = c - 0x0F20;
     209           1 :         else if( c >= 0x0ED0 ) // lao digits
     210           0 :             value = c - 0x0ED0;
     211           1 :         else if( c >= 0x0E50 ) // thai digits
     212           0 :             value = c - 0x0E50;
     213           1 :         else if( c >= 0x0D66 ) // malayalam digits
     214           0 :             value = c - 0x0D66;
     215           1 :         else if( c >= 0x0CE6 ) // kannada digits
     216           0 :             value = c - 0x0CE6;
     217           1 :         else if( c >= 0x0C66 ) // telugu digits
     218           0 :             value = c - 0x0C66;
     219           1 :         else if( c >= 0x0BE6 ) // tamil digits
     220           0 :             value = c - 0x0BE6;
     221           1 :         else if( c >= 0x0B66 ) // oriya digits
     222           0 :             value = c - 0x0B66;
     223           1 :         else if( c >= 0x0AE6 ) // gujarati digits
     224           0 :             value = c - 0x0AE6;
     225           1 :         else if( c >= 0x0A66 ) // gurmukhi digits
     226           0 :             value = c - 0x0A66;
     227           1 :         else if( c >= 0x09E6 ) // bengali digits
     228           0 :             value = c - 0x09E6;
     229           1 :         else if( c >= 0x0966 ) // devanagari digit
     230           0 :             value = c - 0x0966;
     231           1 :         else if( c >= 0x07C0 ) // nko digits
     232           1 :             value = c - 0x07C0;
     233           0 :         else if( c >= 0x06F0 ) // extended arabic-indic digits
     234           0 :             value = c - 0x06F0;
     235           0 :         else if( c >= 0x0660 ) // arabic-indic digits
     236           0 :             value = c - 0x0660;
     237      176853 :         result = result * 10 + value;
     238             :     }
     239      172613 :     return result;
     240             : }
     241             : 
     242             : using namespace ::com::sun::star;
     243             : 
     244             : // convert between sequence of string and comma separated string
     245             : 
     246          54 : OUString convertCommaSeparated(
     247             :     uno::Sequence< OUString > const& i_rSeq)
     248             : {
     249          54 :     OUStringBuffer buf;
     250             :     ::comphelper::intersperse(
     251             :         ::comphelper::stl_begin(i_rSeq), ::comphelper::stl_end(i_rSeq),
     252             :         ::comphelper::OUStringBufferAppender(buf),
     253          54 :         OUString( ", " ));
     254          54 :     return buf.makeStringAndClear();
     255             : }
     256             : 
     257             : uno::Sequence< OUString >
     258          32 :     convertCommaSeparated( OUString const& i_rString )
     259             : {
     260          32 :     std::vector< OUString > vec;
     261          32 :     sal_Int32 idx = 0;
     262          34 :     do {
     263             :       OUString kw =
     264          34 :         i_rString.getToken(0, static_cast<sal_Unicode> (','), idx);
     265          34 :       kw = kw.trim();
     266          34 :       if (!kw.isEmpty()) {
     267           4 :           vec.push_back(kw);
     268          34 :       }
     269          34 :     } while (idx >= 0);
     270          32 :     uno::Sequence< OUString > kws(vec.size());
     271          32 :     std::copy(vec.begin(), vec.end(), stl_begin(kws));
     272          32 :     return kws;
     273             : }
     274             : 
     275             : 
     276      591815 : sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS,
     277             :     const uno::Reference< i18n::XCollator > &rCollator,
     278             :     const uno::Reference< i18n::XBreakIterator > &rBI,
     279             :     const lang::Locale &rLocale )
     280             : {
     281      591815 :     sal_Int32 nRet = 0;
     282             : 
     283      591815 :     sal_Int32 nLHSLastNonDigitPos = 0;
     284      591815 :     sal_Int32 nRHSLastNonDigitPos = 0;
     285      591815 :     sal_Int32 nLHSFirstDigitPos = 0;
     286      591815 :     sal_Int32 nRHSFirstDigitPos = 0;
     287             : 
     288     1199976 :     while (nLHSFirstDigitPos < rLHS.getLength() || nRHSFirstDigitPos < rRHS.getLength())
     289             :     {
     290             :         sal_Int32 nLHSChunkLen;
     291             :         sal_Int32 nRHSChunkLen;
     292             : 
     293             :         //Compare non digit block as normal strings
     294      608159 :         nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos,
     295      608159 :             rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
     296      608159 :         nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos,
     297      608159 :             rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
     298      608159 :         if (nLHSFirstDigitPos == -1)
     299      187045 :             nLHSFirstDigitPos = rLHS.getLength();
     300      608159 :         if (nRHSFirstDigitPos == -1)
     301      275738 :             nRHSFirstDigitPos = rRHS.getLength();
     302      608159 :         nLHSChunkLen = nLHSFirstDigitPos - nLHSLastNonDigitPos;
     303      608159 :         nRHSChunkLen = nRHSFirstDigitPos - nRHSLastNonDigitPos;
     304             : 
     305      608159 :         nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos,
     306      608159 :             nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen);
     307      608159 :         if (nRet != 0)
     308      521854 :             break;
     309             : 
     310             :         //Compare digit block as one number vs another
     311       86305 :         nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos,
     312       86305 :             rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
     313       86305 :         nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos,
     314       86305 :             rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
     315       86305 :         if (nLHSLastNonDigitPos == -1)
     316          26 :             nLHSLastNonDigitPos = rLHS.getLength();
     317       86305 :         if (nRHSLastNonDigitPos == -1)
     318          10 :             nRHSLastNonDigitPos = rRHS.getLength();
     319       86305 :         nLHSChunkLen = nLHSLastNonDigitPos - nLHSFirstDigitPos;
     320       86305 :         nRHSChunkLen = nRHSLastNonDigitPos - nRHSFirstDigitPos;
     321             : 
     322             :         //To-Do: Possibly scale down those unicode codepoints that relate to
     323             :         //numbers outside of the normal 0-9 range, e.g. see GetLocalizedChar in
     324             :         //vcl
     325             : 
     326       86305 :         sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.copy(nLHSFirstDigitPos, nLHSChunkLen));
     327       86305 :         sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.copy(nRHSFirstDigitPos, nRHSChunkLen));
     328             : 
     329       86305 :         nRet = nLHS-nRHS;
     330       86305 :         if (nRet != 0)
     331       69959 :             break;
     332             :     }
     333             : 
     334             :     //Squeeze these down to -1, 0, 1 in case it gets casted to a StringCompare
     335      591815 :     if (nRet > 0)
     336      472729 :         nRet = 1;
     337      119086 :     else if (nRet < 0)
     338      119084 :         nRet = -1;
     339             : 
     340      591815 :     return nRet;
     341             : }
     342             : 
     343         308 : NaturalStringSorter::NaturalStringSorter(
     344             :     const uno::Reference< uno::XComponentContext > &rContext,
     345         308 :     const lang::Locale &rLocale) : m_aLocale(rLocale)
     346             : {
     347         308 :     m_xCollator = i18n::Collator::create( rContext );
     348         308 :     m_xCollator->loadDefaultCollator(m_aLocale, 0);
     349         308 :     m_xBI = i18n::BreakIterator::create( rContext );
     350         308 : }
     351             : 
     352             : namespace
     353             : {
     354             :     //do OPER on each element of the string, return false
     355             :     //if any OPER is false, true otherwise
     356             :     template <bool (*OPER)(sal_Unicode), typename T>
     357         830 :     bool tmpl_is_OPER_AsciiString(const T &rString)
     358             :     {
     359        3467 :         for (sal_Int32 i = 0; i < rString.getLength(); ++i)
     360             :         {
     361        2762 :             if (!OPER(rString[i]))
     362         125 :                 return false;
     363             :         }
     364         705 :         return true;
     365             :     }
     366             : }
     367             : 
     368         830 : bool isdigitAsciiString(const OString &rString)
     369             : {
     370         830 :     return tmpl_is_OPER_AsciiString<isdigitAscii>(rString);
     371             : }
     372             : 
     373           0 : bool isdigitAsciiString(const OUString &rString)
     374             : {
     375           0 :     return tmpl_is_OPER_AsciiString<isdigitAscii>(rString);
     376             : }
     377             : 
     378             : namespace
     379             : {
     380         398 :     template <typename T, typename O> T tmpl_reverseString(const T &rIn)
     381             :     {
     382         398 :         if (rIn.isEmpty())
     383           0 :             return rIn;
     384             : 
     385         398 :         sal_Int32 i = rIn.getLength();
     386         398 :         O sBuf(i);
     387        1964 :         while (i)
     388        1168 :             sBuf.append(rIn[--i]);
     389         398 :         return sBuf.makeStringAndClear();
     390             :     }
     391             : }
     392             : 
     393         397 : OUString reverseString(const OUString &rStr)
     394             : {
     395         397 :     return tmpl_reverseString<OUString, OUStringBuffer>(rStr);
     396             : }
     397             : 
     398           1 : OString reverseString(const OString &rStr)
     399             : {
     400           1 :     return tmpl_reverseString<OString, OStringBuffer>(rStr);
     401             : }
     402             : 
     403         530 : sal_Int32 indexOfAny(OUString const& rIn,
     404             :         sal_Unicode const*const pChars, sal_Int32 const nPos)
     405             : {
     406       22324 :     for (sal_Int32 i = nPos; i < rIn.getLength(); ++i)
     407             :     {
     408       21815 :         sal_Unicode const c = rIn[i];
     409       87208 :         for (sal_Unicode const* pChar = pChars; *pChar; ++pChar)
     410             :         {
     411       65414 :             if (c == *pChar)
     412             :             {
     413          21 :                 return i;
     414             :             }
     415             :         }
     416             :     }
     417         509 :     return -1;
     418             : }
     419             : 
     420             : } }
     421             : 
     422             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10