Branch data 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 : : #ifndef _ZFORFIND_HXX
21 : : #define _ZFORFIND_HXX
22 : :
23 : : #include <tools/string.hxx>
24 : : #include <com/sun/star/uno/Sequence.hxx>
25 : : #include <rtl/ustring.hxx>
26 : :
27 : : class Date;
28 : : class SvNumberformat;
29 : : class SvNumberFormatter;
30 : :
31 : : #define SV_MAX_ANZ_INPUT_STRINGS 20 // max count of substrings in input scanner
32 : :
33 : : class ImpSvNumberInputScan
34 : : {
35 : : public:
36 : : ImpSvNumberInputScan( SvNumberFormatter* pFormatter );
37 : : ~ImpSvNumberInputScan();
38 : :
39 : : /*!*/ void ChangeIntl(); // MUST be called if language changes
40 : :
41 : : /// set reference date for offset calculation
42 : : void ChangeNullDate(
43 : : const sal_uInt16 nDay,
44 : : const sal_uInt16 nMonth,
45 : : const sal_uInt16 nYear );
46 : :
47 : : /// convert input string to number
48 : : bool IsNumberFormat(
49 : : const String& rString, /// input string
50 : : short& F_Type, /// format type (in + out)
51 : : double& fOutNumber, /// value determined (out)
52 : : const SvNumberformat* pFormat = NULL /// optional a number format to which compare against
53 : : );
54 : :
55 : : /// after IsNumberFormat: get decimal position
56 : 0 : short GetDecPos() const { return nDecPos; }
57 : : /// after IsNumberFormat: get count of numeric substrings in input string
58 : 0 : sal_uInt16 GetAnzNums() const { return nAnzNums; }
59 : :
60 : : /// set threshold of two-digit year input
61 : 2868 : void SetYear2000( sal_uInt16 nVal ) { nYear2000 = nVal; }
62 : : /// get threshold of two-digit year input
63 : 48 : sal_uInt16 GetYear2000() const { return nYear2000; }
64 : :
65 : : /** Whether input can be forced to ISO 8601 format.
66 : :
67 : : Depends on locale's date separator and a specific date format order.
68 : :
69 : : @param eDateFormat
70 : : Evaluated only on first call during one scan process, subsequent
71 : : calls return state of nCanForceToIso8601!
72 : :
73 : : @see nCanForceToIso8601
74 : : */
75 : : bool CanForceToIso8601( DateFormat eDateFormat );
76 : :
77 : : private:
78 : : SvNumberFormatter* pFormatter;
79 : : String* pUpperMonthText; // Array of month names, uppercase
80 : : String* pUpperAbbrevMonthText; // Array of month names, abbreviated, uppercase
81 : : String* pUpperGenitiveMonthText; // Array of genitive month names, uppercase
82 : : String* pUpperGenitiveAbbrevMonthText; // Array of genitive month names, abbreviated, uppercase
83 : : String* pUpperPartitiveMonthText; // Array of partitive month names, uppercase
84 : : String* pUpperPartitiveAbbrevMonthText; // Array of partitive month names, abbreviated, uppercase
85 : : String* pUpperDayText; // Array of day of week names, uppercase
86 : : String* pUpperAbbrevDayText; // Array of day of week names, abbreviated, uppercase
87 : : String aUpperCurrSymbol; // Currency symbol, uppercase
88 : : bool bTextInitialized; // Whether days and months are initialized
89 : : bool bScanGenitiveMonths; // Whether to scan an input for genitive months
90 : : bool bScanPartitiveMonths; // Whether to scan an input for partitive months
91 : : Date* pNullDate; // 30Dec1899
92 : : // Variables for provisional results:
93 : : String sStrArray[SV_MAX_ANZ_INPUT_STRINGS]; // Array of scanned substrings
94 : : bool IsNum[SV_MAX_ANZ_INPUT_STRINGS]; // Whether a substring is numeric
95 : : sal_uInt16 nNums[SV_MAX_ANZ_INPUT_STRINGS]; // Sequence of offsets to numeric strings
96 : : sal_uInt16 nAnzStrings; // Total count of scanned substrings
97 : : sal_uInt16 nAnzNums; // Count of numeric substrings
98 : : bool bDecSepInDateSeps; // True <=> DecSep in {.,-,/,DateSep}
99 : : sal_uInt8 nMatchedAllStrings; // Scan...String() matched all substrings,
100 : : // bit mask of nMatched... constants
101 : :
102 : : static const sal_uInt8 nMatchedEndString; // 0x01
103 : : static const sal_uInt8 nMatchedMidString; // 0x02
104 : : static const sal_uInt8 nMatchedStartString; // 0x04
105 : : static const sal_uInt8 nMatchedVirgin; // 0x08
106 : : static const sal_uInt8 nMatchedUsedAsReturn; // 0x10
107 : :
108 : : int nSign; // Sign of number
109 : : short nMonth; // Month (1..x) if date
110 : : // negative => short format
111 : : short nMonthPos; // 1 = front, 2 = middle
112 : : // 3 = end
113 : : sal_uInt16 nTimePos; // Index of first time separator (+1)
114 : : short nDecPos; // Index of substring containing "," (+1)
115 : : short nNegCheck; // '( )' for negative
116 : : short nESign; // Sign of exponent
117 : : short nAmPm; // +1 AM, -1 PM, 0 if none
118 : : short nLogical; // -1 => False, 1 => True
119 : : sal_uInt16 nThousand; // Count of group (AKA thousand) separators
120 : : sal_uInt16 nPosThousandString; // Position of concatenaded 000,000,000 string
121 : : short eScannedType; // Scanned type
122 : : short eSetType; // Preset Type
123 : :
124 : : sal_uInt16 nStringScanNumFor; // Fixed strings recognized in
125 : : // pFormat->NumFor[nNumForStringScan]
126 : : short nStringScanSign; // Sign resulting of FixString
127 : : sal_uInt16 nYear2000; // Two-digit threshold
128 : : // Year as 20xx
129 : : // default 18
130 : : // number <= nYear2000 => 20xx
131 : : // number > nYear2000 => 19xx
132 : : sal_uInt16 nTimezonePos; // Index of timezone separator (+1)
133 : :
134 : : /** State of ISO 8601 detection.
135 : :
136 : : 0:= don't know yet
137 : : 1:= no
138 : : 2:= yes, <=2 digits in year
139 : : 3:= yes, 3 digits in year
140 : : 4:= yes, >=4 digits in year
141 : :
142 : : @see MayBeIso8601()
143 : : */
144 : : sal_uInt8 nMayBeIso8601;
145 : :
146 : : /** State of ISO 8601 can be forced.
147 : :
148 : : 0:= don't know yet
149 : : 1:= no
150 : : 2:= yes
151 : :
152 : : @see CanForceToIso8601()
153 : : */
154 : : sal_uInt8 nCanForceToIso8601;
155 : :
156 : : /** State of dd-month-yy or yy-month-dd detection, with month name.
157 : :
158 : : 0:= don't know yet
159 : : 1:= no
160 : : 2:= yes, dd-month-yy
161 : : 3:= yes, yy-month-dd
162 : :
163 : : @see MayBeMonthDate()
164 : : */
165 : : sal_uInt8 nMayBeMonthDate;
166 : :
167 : : /** Input matched this locale dependent date acceptance pattern.
168 : : -2 if not checked yet, -1 if no match, >=0 matched pattern.
169 : :
170 : : @see IsAcceptedDatePattern()
171 : : */
172 : : sal_Int32 nAcceptedDatePattern;
173 : : com::sun::star::uno::Sequence< rtl::OUString > sDateAcceptancePatterns;
174 : :
175 : : /** If input matched a date acceptance pattern that starts at input
176 : : particle sStrArray[nDatePatternStart].
177 : :
178 : : @see IsAcceptedDatePattern()
179 : : */
180 : : sal_uInt16 nDatePatternStart;
181 : :
182 : : #ifdef _ZFORFIND_CXX // methods private to implementation
183 : : void Reset(); // Reset all variables before start of analysis
184 : :
185 : : void InitText(); // Init of months and days of week
186 : :
187 : : // Convert string to double.
188 : : // Only simple unsigned floating point values without any error detection,
189 : : // decimal separator has to be '.'
190 : : // If bForceFraction==true the string is taken to be the fractional part
191 : : // of 0.1234 without the leading 0. (thus being just "1234").
192 : : double StringToDouble(
193 : : const String& rStr,
194 : : bool bForceFraction = false );
195 : :
196 : : bool NextNumberStringSymbol( // Next number/string symbol
197 : : const sal_Unicode*& pStr,
198 : : String& rSymbol );
199 : :
200 : : bool SkipThousands( // Concatenate ,000,23 blocks
201 : : const sal_Unicode*& pStr, // in input to 000123
202 : : String& rSymbol );
203 : :
204 : : void NumberStringDivision( // Divide numbers/strings into
205 : : const String& rString ); // arrays and variables above.
206 : : // Leading blanks and blanks
207 : : // after numbers are thrown away
208 : :
209 : :
210 : : // optimized substring versions
211 : :
212 : 41649 : static inline bool StringContains( // Whether rString contains rWhat at nPos
213 : : const String& rWhat,
214 : : const String& rString,
215 : : xub_StrLen nPos )
216 : : { // mostly used with one character
217 [ + + ]: 41649 : if ( rWhat.GetChar(0) != rString.GetChar(nPos) )
218 : 40672 : return false;
219 : 41649 : return StringContainsImpl( rWhat, rString, nPos );
220 : : }
221 : 0 : static inline bool StringPtrContains( // Whether pString contains rWhat at nPos
222 : : const String& rWhat,
223 : : const sal_Unicode* pString,
224 : : xub_StrLen nPos ) // nPos MUST be a valid offset from pString
225 : : { // mostly used with one character
226 [ # # ]: 0 : if ( rWhat.GetChar(0) != *(pString+nPos) )
227 : 0 : return false;
228 : 0 : return StringPtrContainsImpl( rWhat, pString, nPos );
229 : : }
230 : : static bool StringContainsImpl( //! DO NOT use directly
231 : : const String& rWhat,
232 : : const String& rString,
233 : : xub_StrLen nPos );
234 : : static bool StringPtrContainsImpl( //! DO NOT use directly
235 : : const String& rWhat,
236 : : const sal_Unicode* pString,
237 : : xub_StrLen nPos );
238 : :
239 : :
240 : : static inline bool SkipChar( // Skip a special character
241 : : sal_Unicode c,
242 : : const String& rString,
243 : : xub_StrLen& nPos );
244 : : static inline void SkipBlanks( // Skip blank
245 : : const String& rString,
246 : : xub_StrLen& nPos );
247 : : static inline bool SkipString( // Jump over rWhat in rString at nPos
248 : : const String& rWhat,
249 : : const String& rString,
250 : : xub_StrLen& nPos );
251 : :
252 : : inline bool GetThousandSep( // Recognizes exactly ,111 as group separator
253 : : const String& rString,
254 : : xub_StrLen& nPos,
255 : : sal_uInt16 nStringPos );
256 : : short GetLogical( // Get boolean value
257 : : const String& rString );
258 : : short GetMonth( // Get month and advance string position
259 : : const String& rString,
260 : : xub_StrLen& nPos );
261 : : int GetDayOfWeek( // Get day of week and advance string position
262 : : const String& rString,
263 : : xub_StrLen& nPos );
264 : : bool GetCurrency( // Get currency symbol and advance string position
265 : : const String& rString,
266 : : xub_StrLen& nPos,
267 : : const SvNumberformat* pFormat = NULL ); // optional number format to match against
268 : : bool GetTimeAmPm( // Get symbol AM or PM and advance string position
269 : : const String& rString,
270 : : xub_StrLen& nPos );
271 : : inline bool GetDecSep( // Get decimal separator and advance string position
272 : : const String& rString,
273 : : xub_StrLen& nPos );
274 : : inline bool GetTime100SecSep( // Get hundredth seconds separator and advance string position
275 : : const String& rString,
276 : : xub_StrLen& nPos );
277 : : int GetSign( // Get sign and advance string position
278 : : const String& rString, // Including special case '('
279 : : xub_StrLen& nPos );
280 : : short GetESign( // Get sign of exponent and advance string position
281 : : const String& rString,
282 : : xub_StrLen& nPos );
283 : :
284 : : inline bool GetNextNumber( // Get next number as array offset
285 : : sal_uInt16& i,
286 : : sal_uInt16& j );
287 : :
288 : : /** Converts time -> double (only decimals)
289 : :
290 : : @return TRUE if time, FALSE if not (e.g. hours >12 with AM/PM)
291 : : */
292 : : bool GetTimeRef(
293 : : double& fOutNumber, // result as double
294 : : sal_uInt16 nIndex, // Index of hour in input
295 : : sal_uInt16 nAnz ); // Count of time substrings in input
296 : : sal_uInt16 ImplGetDay ( sal_uInt16 nIndex ); // Day input, 0 if no match
297 : : sal_uInt16 ImplGetMonth( sal_uInt16 nIndex ); // Month input, zero based return, NumberOfMonths if no match
298 : : sal_uInt16 ImplGetYear ( sal_uInt16 nIndex ); // Year input, 0 if no match
299 : : bool GetDateRef( // Conversion of date to number
300 : : double& fDays, // OUT: days diff to null date
301 : : sal_uInt16& nCounter, // Count of date substrings
302 : : const SvNumberformat* pFormat = NULL ); // optional number format to match against
303 : :
304 : : bool ScanStartString( // Analyze start of string
305 : : const String& rString,
306 : : const SvNumberformat* pFormat = NULL );
307 : : bool ScanMidString( // Analyze middle substring
308 : : const String& rString,
309 : : sal_uInt16 nStringPos,
310 : : const SvNumberformat* pFormat = NULL );
311 : : bool ScanEndString( // Analyze end of string
312 : : const String& rString,
313 : : const SvNumberformat* pFormat = NULL );
314 : :
315 : : // Compare rString to substring of array indexed by nString
316 : : // nString == 0xFFFF => last substring
317 : : bool ScanStringNumFor(
318 : : const String& rString,
319 : : xub_StrLen nPos,
320 : : const SvNumberformat* pFormat,
321 : : sal_uInt16 nString,
322 : : bool bDontDetectNegation = false );
323 : :
324 : : // if nMatchedAllStrings set nMatchedUsedAsReturn and return true,
325 : : // else do nothing and return false
326 : : bool MatchedReturn();
327 : :
328 : : //! Be sure that the string to be analyzed is already converted to upper
329 : : //! case and if it contained native humber digits that they are already
330 : : //! converted to ASCII.
331 : : bool IsNumberFormatMain( // Main anlyzing function
332 : : const String& rString,
333 : : const SvNumberformat* pFormat = NULL // optional number format to match against
334 : : );
335 : :
336 : : static inline bool MyIsdigit( sal_Unicode c );
337 : :
338 : : // native number transliteration if necessary
339 : : void TransformInput( String& rString );
340 : :
341 : : /** Whether input matches locale dependent date acceptance pattern.
342 : :
343 : : @param nStartPatternAt
344 : : The pattern matching starts at input particle
345 : : sStrArray[nStartPatternAt].
346 : :
347 : : NOTE: once called the result is remembered, subsequent calls with
348 : : different parameters do not check for a match and do not lead to a
349 : : different result.
350 : : */
351 : : bool IsAcceptedDatePattern( sal_uInt16 nStartPatternAt );
352 : :
353 : : /** Sets (not advances!) rPos to sStrArray[nParticle].Len() if string
354 : : matches separator in pattern at nParticle.
355 : :
356 : : @returns TRUE if separator matched.
357 : : */
358 : : bool SkipDatePatternSeparator( sal_uInt16 nParticle, xub_StrLen & rPos );
359 : :
360 : : /** Obtain order of accepted date pattern coded as, for example,
361 : : ('D'<<16)|('M'<<8)|'Y'
362 : : */
363 : : sal_uInt32 GetDatePatternOrder();
364 : :
365 : : /** Obtain date format order, from accepted date pattern if available or
366 : : otherwise the locale's default order.
367 : : */
368 : : DateFormat GetDateOrder();
369 : :
370 : : /** Whether input may be an ISO 8601 date format, yyyy-mm-dd...
371 : :
372 : : Checks if input has at least 3 numbers for yyyy-mm-dd and the separator
373 : : is '-', and 1<=mm<=12 and 1<=dd<=31.
374 : :
375 : : @see nMayBeIso8601
376 : : */
377 : : bool MayBeIso8601();
378 : :
379 : : /** Whether input may be a dd-month-yy format, with month name, not
380 : : number.
381 : :
382 : : @see nMayBeMonthDate
383 : : */
384 : : bool MayBeMonthDate();
385 : :
386 : : #endif // _ZFORFIND_CXX
387 : : };
388 : :
389 : :
390 : :
391 : : #endif // _ZFORFIND_HXX
392 : :
393 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|