1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _ZFORFIND_HXX 25 #define _ZFORFIND_HXX 26 27 #include <tools/string.hxx> 28 29 class Date; 30 class SvNumberformat; 31 class SvNumberFormatter; 32 33 #define SV_MAX_ANZ_INPUT_STRINGS 20 // max count of substrings in input scanner 34 35 class ImpSvNumberInputScan 36 { 37 public: 38 ImpSvNumberInputScan( SvNumberFormatter* pFormatter ); 39 ~ImpSvNumberInputScan(); 40 41 /*!*/ void ChangeIntl(); // MUST be called if language changes 42 43 /// set reference date for offset calculation 44 void ChangeNullDate( 45 const sal_uInt16 nDay, 46 const sal_uInt16 nMonth, 47 const sal_uInt16 nYear ); 48 49 /// convert input string to number 50 sal_Bool IsNumberFormat( 51 const String& rString, /// input string 52 short& F_Type, /// format type (in + out) 53 double& fOutNumber, /// value determined (out) 54 const SvNumberformat* pFormat = NULL /// optional a number format to which compare against 55 ); 56 57 /// after IsNumberFormat: get decimal position GetDecPos() const58 short GetDecPos() const { return nDecPos; } 59 /// after IsNumberFormat: get count of numeric substrings in input string GetAnzNums() const60 sal_uInt16 GetAnzNums() const { return nAnzNums; } 61 62 /// set threshold of two-digit year input SetYear2000(sal_uInt16 nVal)63 void SetYear2000( sal_uInt16 nVal ) { nYear2000 = nVal; } 64 /// get threshold of two-digit year input GetYear2000() const65 sal_uInt16 GetYear2000() const { return nYear2000; } 66 67 private: 68 SvNumberFormatter* pFormatter; 69 String* pUpperMonthText; // Array of month names, uppercase 70 String* pUpperAbbrevMonthText; // Array of month names, abbreviated, uppercase 71 String* pUpperDayText; // Array of day of week names, uppercase 72 String* pUpperAbbrevDayText; // Array of day of week names, abbreviated, uppercase 73 String aUpperCurrSymbol; // Currency symbol, uppercase 74 sal_Bool bTextInitialized; // Whether days and months are initialized 75 Date* pNullDate; // 30Dec1899 76 // Variables for provisional results: 77 String sStrArray[SV_MAX_ANZ_INPUT_STRINGS]; // Array of scanned substrings 78 sal_Bool IsNum[SV_MAX_ANZ_INPUT_STRINGS]; // Whether a substring is numeric 79 sal_uInt16 nNums[SV_MAX_ANZ_INPUT_STRINGS]; // Sequence of offsets to numeric strings 80 sal_uInt16 nAnzStrings; // Total count of scanned substrings 81 sal_uInt16 nAnzNums; // Count of numeric substrings 82 sal_Bool bDecSepInDateSeps; // True <=> DecSep in {.,-,/,DateSep} 83 sal_uInt8 nMatchedAllStrings; // Scan...String() matched all substrings, 84 // bit mask of nMatched... constants 85 86 static const sal_uInt8 nMatchedEndString; // 0x01 87 static const sal_uInt8 nMatchedMidString; // 0x02 88 static const sal_uInt8 nMatchedStartString; // 0x04 89 static const sal_uInt8 nMatchedVirgin; // 0x08 90 static const sal_uInt8 nMatchedUsedAsReturn; // 0x10 91 92 int nSign; // Sign of number 93 short nMonth; // Month (1..x) if date 94 // negative => short format 95 short nMonthPos; // 1 = front, 2 = middle 96 // 3 = end 97 sal_uInt16 nTimePos; // Index of first time separator (+1) 98 short nDecPos; // Index of substring containing "," (+1) 99 short nNegCheck; // '( )' for negative 100 short nESign; // Sign of exponent 101 short nAmPm; // +1 AM, -1 PM, 0 if none 102 short nLogical; // -1 => False, 1 => True 103 sal_uInt16 nThousand; // Count of group (AKA thousand) separators 104 sal_uInt16 nPosThousandString; // Position of concatenaded 000,000,000 string 105 short eScannedType; // Scanned type 106 short eSetType; // Preset Type 107 108 sal_uInt16 nStringScanNumFor; // Fixed strings recognized in 109 // pFormat->NumFor[nNumForStringScan] 110 short nStringScanSign; // Sign resulting of FixString 111 sal_uInt16 nYear2000; // Two-digit threshold 112 // Year as 20xx 113 // default 18 114 // number <= nYear2000 => 20xx 115 // number > nYear2000 => 19xx 116 sal_uInt16 nTimezonePos; // Index of timezone separator (+1) 117 sal_uInt8 nMayBeIso8601; // 0:=dontknowyet, 1:=yes, 2:=no 118 119 #ifdef _ZFORFIND_CXX // methods private to implementation 120 void Reset(); // Reset all variables before start of analysis 121 122 void InitText(); // Init of months and days of week 123 124 // Convert string to double. 125 // Only simple unsigned floating point values without any error detection, 126 // decimal separator has to be '.' 127 // If bForceFraction==sal_True the string is taken to be the fractional part 128 // of 0.1234 without the leading 0. (thus being just "1234"). 129 double StringToDouble( 130 const String& rStr, 131 sal_Bool bForceFraction = sal_False ); 132 133 sal_Bool NextNumberStringSymbol( // Next number/string symbol 134 const sal_Unicode*& pStr, 135 String& rSymbol ); 136 137 sal_Bool SkipThousands( // Concatenate ,000,23 blocks 138 const sal_Unicode*& pStr, // in input to 000123 139 String& rSymbol ); 140 141 void NumberStringDivision( // Divide numbers/strings into 142 const String& rString ); // arrays and variables above. 143 // Leading blanks and blanks 144 // after numbers are thrown away 145 146 147 // optimized substring versions 148 StringContains(const String & rWhat,const String & rString,xub_StrLen nPos)149 static inline sal_Bool StringContains( // Whether rString contains rWhat at nPos 150 const String& rWhat, 151 const String& rString, 152 xub_StrLen nPos ) 153 { // mostly used with one character 154 if ( rWhat.GetChar(0) != rString.GetChar(nPos) ) 155 return sal_False; 156 return StringContainsImpl( rWhat, rString, nPos ); 157 } StringPtrContains(const String & rWhat,const sal_Unicode * pString,xub_StrLen nPos)158 static inline sal_Bool StringPtrContains( // Whether pString contains rWhat at nPos 159 const String& rWhat, 160 const sal_Unicode* pString, 161 xub_StrLen nPos ) // nPos MUST be a valid offset from pString 162 { // mostly used with one character 163 if ( rWhat.GetChar(0) != *(pString+nPos) ) 164 return sal_False; 165 return StringPtrContainsImpl( rWhat, pString, nPos ); 166 } 167 static sal_Bool StringContainsImpl( //! DO NOT use directly 168 const String& rWhat, 169 const String& rString, 170 xub_StrLen nPos ); 171 static sal_Bool StringPtrContainsImpl( //! DO NOT use directly 172 const String& rWhat, 173 const sal_Unicode* pString, 174 xub_StrLen nPos ); 175 176 177 static inline sal_Bool SkipChar( // Skip a special character 178 sal_Unicode c, 179 const String& rString, 180 xub_StrLen& nPos ); 181 static inline void SkipBlanks( // Skip blank 182 const String& rString, 183 xub_StrLen& nPos ); 184 static inline sal_Bool SkipString( // Jump over rWhat in rString at nPos 185 const String& rWhat, 186 const String& rString, 187 xub_StrLen& nPos ); 188 189 inline sal_Bool GetThousandSep( // Recognizes exactly ,111 as group separator 190 const String& rString, 191 xub_StrLen& nPos, 192 sal_uInt16 nStringPos ); 193 short GetLogical( // Get boolean value 194 const String& rString ); 195 short GetMonth( // Get month and advance string position 196 const String& rString, 197 xub_StrLen& nPos ); 198 int GetDayOfWeek( // Get day of week and advance string position 199 const String& rString, 200 xub_StrLen& nPos ); 201 sal_Bool GetCurrency( // Get currency symbol and advance string position 202 const String& rString, 203 xub_StrLen& nPos, 204 const SvNumberformat* pFormat = NULL ); // optional number format to match against 205 sal_Bool GetTimeAmPm( // Get symbol AM or PM and advance string position 206 const String& rString, 207 xub_StrLen& nPos ); 208 inline sal_Bool GetDecSep( // Get decimal separator and advance string position 209 const String& rString, 210 xub_StrLen& nPos ); 211 inline sal_Bool GetTime100SecSep( // Get hundredth seconds separator and advance string position 212 const String& rString, 213 xub_StrLen& nPos ); 214 int GetSign( // Get sign and advance string position 215 const String& rString, // Including special case '(' 216 xub_StrLen& nPos ); 217 short GetESign( // Get sign of exponent and advance string position 218 const String& rString, 219 xub_StrLen& nPos ); 220 221 inline sal_Bool GetNextNumber( // Get next number as array offset 222 sal_uInt16& i, 223 sal_uInt16& j ); 224 225 void GetTimeRef( // Converts time -> double (only decimals) 226 double& fOutNumber, // result as double 227 sal_uInt16 nIndex, // Index of hour in input 228 sal_uInt16 nAnz ); // Count of time substrings in input 229 sal_uInt16 ImplGetDay ( sal_uInt16 nIndex ); // Day input, 0 if no match 230 sal_uInt16 ImplGetMonth( sal_uInt16 nIndex ); // Month input, zero based return, NumberOfMonths if no match 231 sal_uInt16 ImplGetYear ( sal_uInt16 nIndex ); // Year input, 0 if no match 232 sal_Bool GetDateRef( // Conversion of date to number 233 double& fDays, // OUT: days diff to null date 234 sal_uInt16& nCounter, // Count of date substrings 235 const SvNumberformat* pFormat = NULL ); // optional number format to match against 236 237 sal_Bool ScanStartString( // Analyze start of string 238 const String& rString, 239 const SvNumberformat* pFormat = NULL ); 240 sal_Bool ScanMidString( // Analyze middle substring 241 const String& rString, 242 sal_uInt16 nStringPos, 243 const SvNumberformat* pFormat = NULL ); 244 sal_Bool ScanEndString( // Analyze end of string 245 const String& rString, 246 const SvNumberformat* pFormat = NULL ); 247 248 // Whether input may be a ISO 8601 date format, yyyy-mm-dd... 249 // checks if at least 3 numbers and first number>31 250 bool MayBeIso8601(); 251 252 // Compare rString to substring of array indexed by nString 253 // nString == 0xFFFF => last substring 254 sal_Bool ScanStringNumFor( 255 const String& rString, 256 xub_StrLen nPos, 257 const SvNumberformat* pFormat, 258 sal_uInt16 nString, 259 sal_Bool bDontDetectNegation = sal_False ); 260 261 // if nMatchedAllStrings set nMatchedUsedAsReturn and return sal_True, 262 // else do nothing and return sal_False 263 sal_Bool MatchedReturn(); 264 265 //! Be sure that the string to be analyzed is already converted to upper 266 //! case and if it contained native humber digits that they are already 267 //! converted to ASCII. 268 sal_Bool IsNumberFormatMain( // Main anlyzing function 269 const String& rString, 270 double& fOutNumber, // return value if string is numeric 271 const SvNumberformat* pFormat = NULL // optional number format to match against 272 ); 273 274 static inline sal_Bool MyIsdigit( sal_Unicode c ); 275 276 // native number transliteration if necessary 277 void TransformInput( String& rString ); 278 279 #endif // _ZFORFIND_CXX 280 }; 281 282 283 284 #endif // _ZFORFIND_HXX 285