blob: 3d2c16817a71b1e4132ca1ec8f3c9ea11b72e2b2 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_i18npool.hxx"
#include <cclass_unicode.hxx>
#include <unicode/uchar.h>
#include <rtl/math.hxx>
#include <rtl/ustring.hxx>
#include <com/sun/star/i18n/KParseTokens.hpp>
#include <com/sun/star/i18n/KParseType.hpp>
#include <com/sun/star/i18n/UnicodeType.hpp>
#include <com/sun/star/i18n/XLocaleData.hpp>
#include <com/sun/star/i18n/NativeNumberMode.hpp>
#include <string.h> // memcpy()
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::rtl;
namespace com { namespace sun { namespace star { namespace i18n {
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_ILLEGAL = 0x00000000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR = 0x00000001;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR_BOOL = 0x00000002;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR_WORD = 0x00000004;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR_VALUE = 0x00000008;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR_STRING = 0x00000010;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_CHAR_DONTCARE= 0x00000020;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_BOOL = 0x00000040;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_WORD = 0x00000080;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_WORD_SEP = 0x00000100;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE = 0x00000200;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE_SEP = 0x00000400;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE_EXP = 0x00000800;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE_SIGN = 0x00001000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE_EXP_VALUE = 0x00002000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_VALUE_DIGIT = 0x00004000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_NAME_SEP = 0x20000000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_STRING_SEP = 0x40000000;
const UPT_FLAG_TYPE cclass_Unicode::TOKEN_EXCLUDED = 0x80000000;
#define TOKEN_DIGIT_FLAGS (TOKEN_CHAR_VALUE | TOKEN_VALUE | TOKEN_VALUE_EXP | TOKEN_VALUE_EXP_VALUE | TOKEN_VALUE_DIGIT)
// Default identifier/name specification is [A-Za-z_][A-Za-z0-9_]*
const sal_uInt8 cclass_Unicode::nDefCnt = 128;
const UPT_FLAG_TYPE cclass_Unicode::pDefaultParserTable[ nDefCnt ] =
{
// (...) == Calc formula compiler specific, commented out and modified
/* \0 */ TOKEN_EXCLUDED,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
/* 9 \t */ TOKEN_CHAR_DONTCARE | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL)
TOKEN_ILLEGAL,
/* 11 \v */ TOKEN_CHAR_DONTCARE | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL)
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
TOKEN_ILLEGAL,
/* 32 */ TOKEN_CHAR_DONTCARE | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 33 ! */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 34 " */ TOKEN_CHAR_STRING | TOKEN_STRING_SEP,
/* 35 # */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_WORD_SEP)
/* 36 $ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_CHAR_WORD | TOKEN_WORD)
/* 37 % */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_VALUE)
/* 38 & */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 39 ' */ TOKEN_NAME_SEP,
/* 40 ( */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 41 ) */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 42 * */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 43 + */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP | TOKEN_VALUE_EXP | TOKEN_VALUE_SIGN,
/* 44 , */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_CHAR_VALUE | TOKEN_VALUE)
/* 45 - */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP | TOKEN_VALUE_EXP | TOKEN_VALUE_SIGN,
/* 46 . */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_WORD | TOKEN_CHAR_VALUE | TOKEN_VALUE)
/* 47 / */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
//for ( i = 48; i < 58; i++ )
/* 48 0 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 49 1 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 50 2 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 51 3 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 52 4 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 53 5 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 54 6 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 55 7 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 56 8 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 57 9 */ TOKEN_DIGIT_FLAGS | TOKEN_WORD,
/* 58 : */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_WORD)
/* 59 ; */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 60 < */ TOKEN_CHAR_BOOL | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 61 = */ TOKEN_CHAR | TOKEN_BOOL | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 62 > */ TOKEN_CHAR_BOOL | TOKEN_BOOL | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 63 ? */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_CHAR_WORD | TOKEN_WORD)
/* 64 @ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
//for ( i = 65; i < 91; i++ )
/* 65 A */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 66 B */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 67 C */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 68 D */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 69 E */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 70 F */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 71 G */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 72 H */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 73 I */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 74 J */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 75 K */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 76 L */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 77 M */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 78 N */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 79 O */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 80 P */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 81 Q */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 82 R */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 83 S */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 84 T */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 85 U */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 86 V */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 87 W */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 88 X */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 89 Y */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 90 Z */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 91 [ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 92 \ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 93 ] */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 94 ^ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP,
/* 95 _ */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 96 ` */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
//for ( i = 97; i < 123; i++ )
/* 97 a */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 98 b */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 99 c */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 100 d */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 101 e */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 102 f */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 103 g */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 104 h */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 105 i */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 106 j */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 107 k */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 108 l */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 109 m */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 110 n */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 111 o */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 112 p */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 113 q */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 114 r */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 115 s */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 116 t */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 117 u */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 118 v */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 119 w */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 120 x */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 121 y */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 122 z */ TOKEN_CHAR_WORD | TOKEN_WORD,
/* 123 { */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 124 | */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 125 } */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 126 ~ */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP, // (TOKEN_ILLEGAL // UNUSED)
/* 127 */ TOKEN_CHAR | TOKEN_WORD_SEP | TOKEN_VALUE_SEP // (TOKEN_ILLEGAL // UNUSED)
};
const sal_Int32 cclass_Unicode::pParseTokensType[ nDefCnt ] =
{
/* \0 */ KParseTokens::ASC_OTHER,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
/* 9 \t */ KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
/* 11 \v */ KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
KParseTokens::ASC_CONTROL,
/* 32 */ KParseTokens::ASC_OTHER,
/* 33 ! */ KParseTokens::ASC_OTHER,
/* 34 " */ KParseTokens::ASC_OTHER,
/* 35 # */ KParseTokens::ASC_OTHER,
/* 36 $ */ KParseTokens::ASC_DOLLAR,
/* 37 % */ KParseTokens::ASC_OTHER,
/* 38 & */ KParseTokens::ASC_OTHER,
/* 39 ' */ KParseTokens::ASC_OTHER,
/* 40 ( */ KParseTokens::ASC_OTHER,
/* 41 ) */ KParseTokens::ASC_OTHER,
/* 42 * */ KParseTokens::ASC_OTHER,
/* 43 + */ KParseTokens::ASC_OTHER,
/* 44 , */ KParseTokens::ASC_OTHER,
/* 45 - */ KParseTokens::ASC_OTHER,
/* 46 . */ KParseTokens::ASC_DOT,
/* 47 / */ KParseTokens::ASC_OTHER,
//for ( i = 48; i < 58; i++ )
/* 48 0 */ KParseTokens::ASC_DIGIT,
/* 49 1 */ KParseTokens::ASC_DIGIT,
/* 50 2 */ KParseTokens::ASC_DIGIT,
/* 51 3 */ KParseTokens::ASC_DIGIT,
/* 52 4 */ KParseTokens::ASC_DIGIT,
/* 53 5 */ KParseTokens::ASC_DIGIT,
/* 54 6 */ KParseTokens::ASC_DIGIT,
/* 55 7 */ KParseTokens::ASC_DIGIT,
/* 56 8 */ KParseTokens::ASC_DIGIT,
/* 57 9 */ KParseTokens::ASC_DIGIT,
/* 58 : */ KParseTokens::ASC_COLON,
/* 59 ; */ KParseTokens::ASC_OTHER,
/* 60 < */ KParseTokens::ASC_OTHER,
/* 61 = */ KParseTokens::ASC_OTHER,
/* 62 > */ KParseTokens::ASC_OTHER,
/* 63 ? */ KParseTokens::ASC_OTHER,
/* 64 @ */ KParseTokens::ASC_OTHER,
//for ( i = 65; i < 91; i++ )
/* 65 A */ KParseTokens::ASC_UPALPHA,
/* 66 B */ KParseTokens::ASC_UPALPHA,
/* 67 C */ KParseTokens::ASC_UPALPHA,
/* 68 D */ KParseTokens::ASC_UPALPHA,
/* 69 E */ KParseTokens::ASC_UPALPHA,
/* 70 F */ KParseTokens::ASC_UPALPHA,
/* 71 G */ KParseTokens::ASC_UPALPHA,
/* 72 H */ KParseTokens::ASC_UPALPHA,
/* 73 I */ KParseTokens::ASC_UPALPHA,
/* 74 J */ KParseTokens::ASC_UPALPHA,
/* 75 K */ KParseTokens::ASC_UPALPHA,
/* 76 L */ KParseTokens::ASC_UPALPHA,
/* 77 M */ KParseTokens::ASC_UPALPHA,
/* 78 N */ KParseTokens::ASC_UPALPHA,
/* 79 O */ KParseTokens::ASC_UPALPHA,
/* 80 P */ KParseTokens::ASC_UPALPHA,
/* 81 Q */ KParseTokens::ASC_UPALPHA,
/* 82 R */ KParseTokens::ASC_UPALPHA,
/* 83 S */ KParseTokens::ASC_UPALPHA,
/* 84 T */ KParseTokens::ASC_UPALPHA,
/* 85 U */ KParseTokens::ASC_UPALPHA,
/* 86 V */ KParseTokens::ASC_UPALPHA,
/* 87 W */ KParseTokens::ASC_UPALPHA,
/* 88 X */ KParseTokens::ASC_UPALPHA,
/* 89 Y */ KParseTokens::ASC_UPALPHA,
/* 90 Z */ KParseTokens::ASC_UPALPHA,
/* 91 [ */ KParseTokens::ASC_OTHER,
/* 92 \ */ KParseTokens::ASC_OTHER,
/* 93 ] */ KParseTokens::ASC_OTHER,
/* 94 ^ */ KParseTokens::ASC_OTHER,
/* 95 _ */ KParseTokens::ASC_UNDERSCORE,
/* 96 ` */ KParseTokens::ASC_OTHER,
//for ( i = 97; i < 123; i++ )
/* 97 a */ KParseTokens::ASC_LOALPHA,
/* 98 b */ KParseTokens::ASC_LOALPHA,
/* 99 c */ KParseTokens::ASC_LOALPHA,
/* 100 d */ KParseTokens::ASC_LOALPHA,
/* 101 e */ KParseTokens::ASC_LOALPHA,
/* 102 f */ KParseTokens::ASC_LOALPHA,
/* 103 g */ KParseTokens::ASC_LOALPHA,
/* 104 h */ KParseTokens::ASC_LOALPHA,
/* 105 i */ KParseTokens::ASC_LOALPHA,
/* 106 j */ KParseTokens::ASC_LOALPHA,
/* 107 k */ KParseTokens::ASC_LOALPHA,
/* 108 l */ KParseTokens::ASC_LOALPHA,
/* 109 m */ KParseTokens::ASC_LOALPHA,
/* 110 n */ KParseTokens::ASC_LOALPHA,
/* 111 o */ KParseTokens::ASC_LOALPHA,
/* 112 p */ KParseTokens::ASC_LOALPHA,
/* 113 q */ KParseTokens::ASC_LOALPHA,
/* 114 r */ KParseTokens::ASC_LOALPHA,
/* 115 s */ KParseTokens::ASC_LOALPHA,
/* 116 t */ KParseTokens::ASC_LOALPHA,
/* 117 u */ KParseTokens::ASC_LOALPHA,
/* 118 v */ KParseTokens::ASC_LOALPHA,
/* 119 w */ KParseTokens::ASC_LOALPHA,
/* 120 x */ KParseTokens::ASC_LOALPHA,
/* 121 y */ KParseTokens::ASC_LOALPHA,
/* 122 z */ KParseTokens::ASC_LOALPHA,
/* 123 { */ KParseTokens::ASC_OTHER,
/* 124 | */ KParseTokens::ASC_OTHER,
/* 125 } */ KParseTokens::ASC_OTHER,
/* 126 ~ */ KParseTokens::ASC_OTHER,
/* 127 */ KParseTokens::ASC_OTHER
};
// static
const sal_Unicode* cclass_Unicode::StrChr( const sal_Unicode* pStr, sal_Unicode c )
{
if ( !pStr )
return NULL;
while ( *pStr )
{
if ( *pStr == c )
return pStr;
pStr++;
}
return NULL;
}
sal_Int32 cclass_Unicode::getParseTokensType( const sal_Unicode* aStr, sal_Int32 nPos )
{
sal_Unicode c = aStr[nPos];
if ( c < nDefCnt )
return pParseTokensType[ sal_uInt8(c) ];
else
{
//! all KParseTokens::UNI_... must be matched
switch ( u_charType( (sal_uInt32) c ) )
{
case U_UPPERCASE_LETTER :
return KParseTokens::UNI_UPALPHA;
case U_LOWERCASE_LETTER :
return KParseTokens::UNI_LOALPHA;
case U_TITLECASE_LETTER :
return KParseTokens::UNI_TITLE_ALPHA;
case U_MODIFIER_LETTER :
return KParseTokens::UNI_MODIFIER_LETTER;
case U_OTHER_LETTER :
// Non_Spacing_Mark could not be as leading character
if (nPos == 0) break;
// fall through, treat it as Other_Letter.
case U_NON_SPACING_MARK :
return KParseTokens::UNI_OTHER_LETTER;
case U_DECIMAL_DIGIT_NUMBER :
return KParseTokens::UNI_DIGIT;
case U_LETTER_NUMBER :
return KParseTokens::UNI_LETTER_NUMBER;
case U_OTHER_NUMBER :
return KParseTokens::UNI_OTHER_NUMBER;
}
return KParseTokens::UNI_OTHER;
}
}
sal_Bool cclass_Unicode::setupInternational( const Locale& rLocale )
{
sal_Bool bChanged = (aParserLocale.Language != rLocale.Language
|| aParserLocale.Country != rLocale.Country
|| aParserLocale.Variant != rLocale.Variant);
if ( bChanged )
{
aParserLocale.Language = rLocale.Language;
aParserLocale.Country = rLocale.Country;
aParserLocale.Variant = rLocale.Variant;
}
if ( !xLocaleData.is() && xMSF.is() )
{
Reference <
XInterface > xI =
xMSF->createInstance( OUString(
RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.LocaleData" ) ) );
if ( xI.is() )
{
Any x = xI->queryInterface( getCppuType((const Reference< XLocaleData>*)0) );
x >>= xLocaleData;
}
}
return bChanged;
}
void cclass_Unicode::setupParserTable( const Locale& rLocale, sal_Int32 startCharTokenType,
const OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
const OUString& userDefinedCharactersCont )
{
bool bIntlEqual = (rLocale.Language == aParserLocale.Language &&
rLocale.Country == aParserLocale.Country &&
rLocale.Variant == aParserLocale.Variant);
if ( !pTable || !bIntlEqual ||
startCharTokenType != nStartTypes ||
contCharTokenType != nContTypes ||
userDefinedCharactersStart != aStartChars ||
userDefinedCharactersCont != aContChars )
initParserTable( rLocale, startCharTokenType, userDefinedCharactersStart,
contCharTokenType, userDefinedCharactersCont );
}
void cclass_Unicode::initParserTable( const Locale& rLocale, sal_Int32 startCharTokenType,
const OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
const OUString& userDefinedCharactersCont )
{
// (Re)Init
setupInternational( rLocale );
// Memory of pTable is reused.
if ( !pTable )
pTable = new UPT_FLAG_TYPE[nDefCnt];
memcpy( pTable, pDefaultParserTable, sizeof(UPT_FLAG_TYPE) * nDefCnt );
// Start and cont tables only need reallocation if different length.
if ( pStart && userDefinedCharactersStart.getLength() != aStartChars.getLength() )
{
delete [] pStart;
pStart = NULL;
}
if ( pCont && userDefinedCharactersCont.getLength() != aContChars.getLength() )
{
delete [] pCont;
pCont = NULL;
}
nStartTypes = startCharTokenType;
nContTypes = contCharTokenType;
aStartChars = userDefinedCharactersStart;
aContChars = userDefinedCharactersCont;
// specials
if( xLocaleData.is() )
{
LocaleDataItem aItem =
xLocaleData->getLocaleItem( aParserLocale );
//!TODO: theoretically separators may be a string, adjustment would have to be
//! done here and in parsing and in ::rtl::math::stringToDouble()
cGroupSep = aItem.thousandSeparator.getStr()[0];
cDecimalSep = aItem.decimalSeparator.getStr()[0];
}
if ( cGroupSep < nDefCnt )
pTable[cGroupSep] |= TOKEN_VALUE;
if ( cDecimalSep < nDefCnt )
pTable[cDecimalSep] |= TOKEN_CHAR_VALUE | TOKEN_VALUE;
// Modify characters according to KParseTokens definitions.
{
using namespace KParseTokens;
sal_uInt8 i;
if ( !(nStartTypes & ASC_UPALPHA) )
for ( i = 65; i < 91; i++ )
pTable[i] &= ~TOKEN_CHAR_WORD; // not allowed as start character
if ( !(nContTypes & ASC_UPALPHA) )
for ( i = 65; i < 91; i++ )
pTable[i] &= ~TOKEN_WORD; // not allowed as cont character
if ( !(nStartTypes & ASC_LOALPHA) )
for ( i = 97; i < 123; i++ )
pTable[i] &= ~TOKEN_CHAR_WORD; // not allowed as start character
if ( !(nContTypes & ASC_LOALPHA) )
for ( i = 97; i < 123; i++ )
pTable[i] &= ~TOKEN_WORD; // not allowed as cont character
if ( nStartTypes & ASC_DIGIT )
for ( i = 48; i < 58; i++ )
pTable[i] |= TOKEN_CHAR_WORD; // allowed as start character
if ( !(nContTypes & ASC_DIGIT) )
for ( i = 48; i < 58; i++ )
pTable[i] &= ~TOKEN_WORD; // not allowed as cont character
if ( !(nStartTypes & ASC_UNDERSCORE) )
pTable[95] &= ~TOKEN_CHAR_WORD; // not allowed as start character
if ( !(nContTypes & ASC_UNDERSCORE) )
pTable[95] &= ~TOKEN_WORD; // not allowed as cont character
if ( nStartTypes & ASC_DOLLAR )
pTable[36] |= TOKEN_CHAR_WORD; // allowed as start character
if ( nContTypes & ASC_DOLLAR )
pTable[36] |= TOKEN_WORD; // allowed as cont character
if ( nStartTypes & ASC_DOT )
pTable[46] |= TOKEN_CHAR_WORD; // allowed as start character
if ( nContTypes & ASC_DOT )
pTable[46] |= TOKEN_WORD; // allowed as cont character
if ( nStartTypes & ASC_COLON )
pTable[58] |= TOKEN_CHAR_WORD; // allowed as start character
if ( nContTypes & ASC_COLON )
pTable[58] |= TOKEN_WORD; // allowed as cont character
if ( nStartTypes & ASC_CONTROL )
for ( i = 1; i < 32; i++ )
pTable[i] |= TOKEN_CHAR_WORD; // allowed as start character
if ( nContTypes & ASC_CONTROL )
for ( i = 1; i < 32; i++ )
pTable[i] |= TOKEN_WORD; // allowed as cont character
if ( nStartTypes & ASC_ANY_BUT_CONTROL )
for ( i = 32; i < nDefCnt; i++ )
pTable[i] |= TOKEN_CHAR_WORD; // allowed as start character
if ( nContTypes & ASC_ANY_BUT_CONTROL )
for ( i = 32; i < nDefCnt; i++ )
pTable[i] |= TOKEN_WORD; // allowed as cont character
}
// Merge in (positively override with) user defined characters.
// StartChars
sal_Int32 nLen = aStartChars.getLength();
if ( nLen )
{
if ( !pStart )
pStart = new UPT_FLAG_TYPE[ nLen ];
const sal_Unicode* p = aStartChars.getStr();
for ( sal_Int32 j=0; j<nLen; j++, p++ )
{
pStart[j] = TOKEN_CHAR_WORD;
if ( *p < nDefCnt )
pTable[*p] |= TOKEN_CHAR_WORD;
}
}
// ContChars
nLen = aContChars.getLength();
if ( nLen )
{
if ( !pCont )
pCont = new UPT_FLAG_TYPE[ nLen ];
const sal_Unicode* p = aContChars.getStr();
for ( sal_Int32 j=0; j<nLen; j++ )
{
pCont[j] = TOKEN_WORD;
if ( *p < nDefCnt )
pTable[*p] |= TOKEN_WORD;
}
}
}
void cclass_Unicode::destroyParserTable()
{
if ( pCont )
delete [] pCont;
if ( pStart )
delete [] pStart;
if ( pTable )
delete [] pTable;
}
UPT_FLAG_TYPE cclass_Unicode::getFlags( const sal_Unicode* aStr, sal_Int32 nPos )
{
UPT_FLAG_TYPE nMask;
sal_Unicode c = aStr[nPos];
if ( c < nDefCnt )
nMask = pTable[ sal_uInt8(c) ];
else
nMask = getFlagsExtended( aStr, nPos );
switch ( eState )
{
case ssGetChar :
case ssRewindFromValue :
case ssIgnoreLeadingInRewind :
case ssGetWordFirstChar :
if ( !(nMask & TOKEN_CHAR_WORD) )
{
nMask |= getStartCharsFlags( c );
if ( nMask & TOKEN_CHAR_WORD )
nMask &= ~TOKEN_EXCLUDED;
}
break;
case ssGetValue :
case ssGetWord :
if ( !(nMask & TOKEN_WORD) )
{
nMask |= getContCharsFlags( c );
if ( nMask & TOKEN_WORD )
nMask &= ~TOKEN_EXCLUDED;
}
break;
default:
; // other cases aren't needed, no compiler warning
}
return nMask;
}
UPT_FLAG_TYPE cclass_Unicode::getFlagsExtended( const sal_Unicode* aStr, sal_Int32 nPos )
{
sal_Unicode c = aStr[nPos];
if ( c == cGroupSep )
return TOKEN_VALUE;
else if ( c == cDecimalSep )
return TOKEN_CHAR_VALUE | TOKEN_VALUE;
using namespace i18n;
bool bStart = (eState == ssGetChar || eState == ssGetWordFirstChar ||
eState == ssRewindFromValue || eState == ssIgnoreLeadingInRewind);
sal_Int32 nTypes = (bStart ? nStartTypes : nContTypes);
//! all KParseTokens::UNI_... must be matched
switch ( u_charType( (sal_uInt32) c ) )
{
case U_UPPERCASE_LETTER :
return (nTypes & KParseTokens::UNI_UPALPHA) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL;
case U_LOWERCASE_LETTER :
return (nTypes & KParseTokens::UNI_LOALPHA) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL;
case U_TITLECASE_LETTER :
return (nTypes & KParseTokens::UNI_TITLE_ALPHA) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL;
case U_MODIFIER_LETTER :
return (nTypes & KParseTokens::UNI_MODIFIER_LETTER) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL;
case U_NON_SPACING_MARK :
case U_COMBINING_SPACING_MARK :
// Non_Spacing_Mark can't be a leading character,
// nor can a spacing combining mark.
if (bStart)
return TOKEN_ILLEGAL;
// fall through, treat it as Other_Letter.
case U_OTHER_LETTER :
return (nTypes & KParseTokens::UNI_OTHER_LETTER) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL;
case U_DECIMAL_DIGIT_NUMBER :
return ((nTypes & KParseTokens::UNI_DIGIT) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL) | TOKEN_DIGIT_FLAGS;
case U_LETTER_NUMBER :
return ((nTypes & KParseTokens::UNI_LETTER_NUMBER) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL) | TOKEN_DIGIT_FLAGS;
case U_OTHER_NUMBER :
return ((nTypes & KParseTokens::UNI_OTHER_NUMBER) ?
(bStart ? TOKEN_CHAR_WORD : TOKEN_WORD) :
TOKEN_ILLEGAL) | TOKEN_DIGIT_FLAGS;
case U_SPACE_SEPARATOR :
return ((nTypes & KParseTokens::IGNORE_LEADING_WS) ?
TOKEN_CHAR_DONTCARE : (bStart ? TOKEN_CHAR_WORD : (TOKEN_CHAR_DONTCARE | TOKEN_WORD_SEP | TOKEN_VALUE_SEP) ));
}
return TOKEN_ILLEGAL;
}
UPT_FLAG_TYPE cclass_Unicode::getStartCharsFlags( sal_Unicode c )
{
if ( pStart )
{
const sal_Unicode* pStr = aStartChars.getStr();
const sal_Unicode* p = StrChr( pStr, c );
if ( p )
return pStart[ p - pStr ];
}
return TOKEN_ILLEGAL;
}
UPT_FLAG_TYPE cclass_Unicode::getContCharsFlags( sal_Unicode c )
{
if ( pCont )
{
const sal_Unicode* pStr = aContChars.getStr();
const sal_Unicode* p = StrChr( pStr, c );
if ( p )
return pCont[ p - pStr ];
}
return TOKEN_ILLEGAL;
}
void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 nPos, sal_Int32 nTokenType )
{
using namespace i18n;
const sal_Unicode* const pTextStart = rText.getStr() + nPos;
eState = ssGetChar;
//! All the variables below (plus ParseResult) have to be resetted on ssRewindFromValue!
const sal_Unicode* pSym = pTextStart;
const sal_Unicode* pSrc = pSym;
OUString aSymbol;
sal_Unicode c = *pSrc;
sal_Unicode cLast = 0;
int nDecSeps = 0;
bool bQuote = false;
bool bMightBeWord = true;
bool bMightBeWordLast = true;
//! All the variables above (plus ParseResult) have to be resetted on ssRewindFromValue!
while ( (c != 0) && (eState != ssStop) )
{
UPT_FLAG_TYPE nMask = getFlags( pTextStart, pSrc - pTextStart );
if ( nMask & TOKEN_EXCLUDED )
eState = ssBounce;
if ( bMightBeWord )
{ // only relevant for ssGetValue fall back
if ( eState == ssGetChar || eState == ssRewindFromValue ||
eState == ssIgnoreLeadingInRewind )
bMightBeWord = ((nMask & TOKEN_CHAR_WORD) != 0);
else
bMightBeWord = ((nMask & TOKEN_WORD) != 0);
}
sal_Int32 nParseTokensType = getParseTokensType( pTextStart, pSrc - pTextStart );
pSrc++;
switch (eState)
{
case ssGetChar :
case ssRewindFromValue :
case ssIgnoreLeadingInRewind :
{
if ( (nMask & TOKEN_CHAR_VALUE) && eState != ssRewindFromValue
&& eState != ssIgnoreLeadingInRewind )
{ //! must be first, may fall back to ssGetWord via bMightBeWord
eState = ssGetValue;
if ( nMask & TOKEN_VALUE_DIGIT )
{
if ( 128 <= c )
r.TokenType = KParseType::UNI_NUMBER;
else
r.TokenType = KParseType::ASC_NUMBER;
}
else if ( c == cDecimalSep )
{
if ( *pSrc )
++nDecSeps;
else
eState = ssRewindFromValue;
// retry for ONE_SINGLE_CHAR or others
}
}
else if ( nMask & TOKEN_CHAR_WORD )
{
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
}
else if ( nMask & TOKEN_NAME_SEP )
{
eState = ssGetWordFirstChar;
bQuote = true;
pSym++;
nParseTokensType = 0; // will be taken of first real character
r.TokenType = KParseType::SINGLE_QUOTE_NAME;
}
else if ( nMask & TOKEN_CHAR_STRING )
{
eState = ssGetString;
pSym++;
nParseTokensType = 0; // will be taken of first real character
r.TokenType = KParseType::DOUBLE_QUOTE_STRING;
}
else if ( nMask & TOKEN_CHAR_DONTCARE )
{
if ( nStartTypes & KParseTokens::IGNORE_LEADING_WS )
{
if (eState == ssRewindFromValue)
eState = ssIgnoreLeadingInRewind;
r.LeadingWhiteSpace++;
pSym++;
nParseTokensType = 0; // wait until real character
bMightBeWord = true;
}
else
eState = ssBounce;
}
else if ( nMask & TOKEN_CHAR_BOOL )
{
eState = ssGetBool;
r.TokenType = KParseType::BOOLEAN;
}
else if ( nMask & TOKEN_CHAR )
{ //! must be last
eState = ssStop;
r.TokenType = KParseType::ONE_SINGLE_CHAR;
}
else
eState = ssBounce; // not known
}
break;
case ssGetValue :
{
if ( nMask & TOKEN_VALUE_DIGIT )
{
if ( 128 <= c )
r.TokenType = KParseType::UNI_NUMBER;
else if ( r.TokenType != KParseType::UNI_NUMBER )
r.TokenType = KParseType::ASC_NUMBER;
}
if ( nMask & TOKEN_VALUE )
{
if ( c == cDecimalSep && ++nDecSeps > 1 )
{
if ( pSrc - pTextStart == 2 )
eState = ssRewindFromValue;
// consecutive separators
else
eState = ssStopBack;
}
// else keep it going
}
else if ( c == 'E' || c == 'e' )
{
UPT_FLAG_TYPE nNext = getFlags( pTextStart, pSrc - pTextStart );
if ( nNext & TOKEN_VALUE_EXP )
; // keep it going
else if ( bMightBeWord && ((nNext & TOKEN_WORD) || !*pSrc) )
{ // might be a numerical name (1.2efg)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
}
else
eState = ssStopBack;
}
else if ( nMask & TOKEN_VALUE_SIGN )
{
if ( (cLast == 'E') || (cLast == 'e') )
{
UPT_FLAG_TYPE nNext = getFlags( pTextStart, pSrc - pTextStart );
if ( nNext & TOKEN_VALUE_EXP_VALUE )
; // keep it going
else if ( bMightBeWord && ((nNext & TOKEN_WORD) || !*pSrc) )
{ // might be a numerical name (1.2e+fg)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
}
else
eState = ssStopBack;
}
else if ( bMightBeWord )
{ // might be a numerical name (1.2+fg)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
}
else
eState = ssStopBack;
}
else if ( bMightBeWord && (nMask & TOKEN_WORD) )
{ // might be a numerical name (1995.A1)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
}
else
eState = ssStopBack;
}
break;
case ssGetWordFirstChar :
eState = ssGetWord;
// fall thru
case ssGetWord :
{
if ( nMask & TOKEN_WORD )
; // keep it going
else if ( nMask & TOKEN_NAME_SEP )
{
if ( bQuote )
{
if ( cLast == '\\' )
{ // escaped
aSymbol += OUString( pSym, pSrc - pSym - 2 );
aSymbol += OUString( &c, 1);
}
else
{
eState = ssStop;
aSymbol += OUString( pSym, pSrc - pSym - 1 );
}
pSym = pSrc;
}
else
eState = ssStopBack;
}
else if ( bQuote )
; // keep it going
else
eState = ssStopBack;
}
break;
case ssGetString :
{
if ( nMask & TOKEN_STRING_SEP )
{
if ( cLast == '\\' )
{ // escaped
aSymbol += OUString( pSym, pSrc - pSym - 2 );
aSymbol += OUString( &c, 1);
}
else if ( c == *pSrc &&
!(nContTypes & KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING) )
{ // "" => literal " escaped
aSymbol += OUString( pSym, pSrc - pSym );
pSrc++;
}
else
{
eState = ssStop;
aSymbol += OUString( pSym, pSrc - pSym - 1 );
}
pSym = pSrc;
}
}
break;
case ssGetBool :
{
if ( (nMask & TOKEN_BOOL) )
eState = ssStop; // maximum 2: <, >, <>, <=, >=
else
eState = ssStopBack;
}
break;
case ssStopBack :
case ssBounce :
case ssStop :
; // nothing, no compiler warning
break;
}
if ( eState == ssRewindFromValue )
{
r = ParseResult();
pSym = pTextStart;
pSrc = pSym;
aSymbol = OUString();
c = *pSrc;
cLast = 0;
nDecSeps = 0;
bQuote = false;
bMightBeWord = true;
bMightBeWordLast = true;
}
else
{
if ( !(r.TokenType & nTokenType) )
{
if ( (r.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
&& (nTokenType & KParseType::IDENTNAME) && bMightBeWord )
; // keep a number that might be a word
else if ( r.LeadingWhiteSpace == (pSrc - pTextStart) )
; // keep ignored white space
else if ( !r.TokenType && eState == ssGetValue && (nMask & TOKEN_VALUE_SEP) )
; // keep uncertain value
else
eState = ssBounce;
}
if ( eState == ssBounce )
{
r.TokenType = 0;
eState = ssStopBack;
}
if ( eState == ssStopBack )
{ // put back
pSrc--;
bMightBeWord = bMightBeWordLast;
eState = ssStop;
}
if ( eState != ssStop )
{
if ( !r.StartFlags )
r.StartFlags |= nParseTokensType;
else
r.ContFlags |= nParseTokensType;
}
bMightBeWordLast = bMightBeWord;
cLast = c;
c = *pSrc;
}
}
// r.CharLen is the length in characters (not code points) of the parsed
// token not including any leading white space, change this calculation if
// multi-code-point Unicode characters are to be supported.
r.CharLen = pSrc - pTextStart - r.LeadingWhiteSpace;
r.EndPos = nPos + (pSrc - pTextStart);
if ( r.TokenType & KParseType::ASC_NUMBER )
{
r.Value = rtl_math_uStringToDouble( pTextStart + r.LeadingWhiteSpace,
pTextStart + r.EndPos, cDecimalSep, cGroupSep, NULL, NULL );
if ( bMightBeWord )
r.TokenType |= KParseType::IDENTNAME;
}
else if ( r.TokenType & KParseType::UNI_NUMBER )
{
if ( !xNatNumSup.is() )
{
#define NATIVENUMBERSUPPLIER_SERVICENAME "com.sun.star.i18n.NativeNumberSupplier"
if ( xMSF.is() )
{
xNatNumSup = Reference< XNativeNumberSupplier > (
xMSF->createInstance( OUString(
RTL_CONSTASCII_USTRINGPARAM(
NATIVENUMBERSUPPLIER_SERVICENAME ) ) ),
UNO_QUERY );
}
if ( !xNatNumSup.is() )
{
throw RuntimeException( OUString(
#ifdef DBG_UTIL
RTL_CONSTASCII_USTRINGPARAM(
"cclass_Unicode::parseText: can't instanciate "
NATIVENUMBERSUPPLIER_SERVICENAME )
#endif
), *this );
}
#undef NATIVENUMBERSUPPLIER_SERVICENAME
}
OUString aTmp( pTextStart + r.LeadingWhiteSpace, r.EndPos - nPos +
r.LeadingWhiteSpace );
// transliterate to ASCII
aTmp = xNatNumSup->getNativeNumberString( aTmp, aParserLocale,
NativeNumberMode::NATNUM0 );
r.Value = ::rtl::math::stringToDouble( aTmp, cDecimalSep, cGroupSep, NULL, NULL );
if ( bMightBeWord )
r.TokenType |= KParseType::IDENTNAME;
}
else if ( r.TokenType & (KParseType::SINGLE_QUOTE_NAME | KParseType::DOUBLE_QUOTE_STRING) )
{
if ( pSym < pSrc )
{ //! open quote
aSymbol += OUString( pSym, pSrc - pSym );
r.TokenType |= KParseType::MISSING_QUOTE;
}
r.DequotedNameOrString = aSymbol;
}
}
} } } }