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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_unotools.hxx"
26 
27 #include <unotools/charclass.hxx>
28 #include <tools/string.hxx>
29 #include <tools/debug.hxx>
30 
31 #ifndef _COMPHELPER_COMPONENTFACTORY_HXX_
32 #include <comphelper/componentfactory.hxx>
33 #endif
34 #include <com/sun/star/uno/XInterface.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 
37 #define CHARCLASS_LIBRARYNAME "i18n"
38 #define CHARCLASS_SERVICENAME "com.sun.star.i18n.CharacterClassification"
39 
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::i18n;
42 using namespace ::com::sun::star::uno;
43 
44 
CharClass(const Reference<lang::XMultiServiceFactory> & xSF,const lang::Locale & rLocale)45 CharClass::CharClass(
46 			const Reference< lang::XMultiServiceFactory > & xSF,
47 			const lang::Locale& rLocale
48 			)
49 		:
50 		xSMgr( xSF )
51 {
52 	setLocale( rLocale );
53 	if ( xSMgr.is() )
54 	{
55 		try
56 		{
57 			xCC = Reference< XCharacterClassification > ( xSMgr->createInstance(
58 				::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CHARCLASS_SERVICENAME ) ) ),
59 				uno::UNO_QUERY );
60 		}
61 		catch ( Exception& )
62 		{
63 			DBG_ERRORFILE( "CharClass ctor: Exception caught!" );
64 		}
65 	}
66 	else
67 	{	// try to get an instance somehow
68 		getComponentInstance();
69 	}
70 }
71 
72 
CharClass(const::com::sun::star::lang::Locale & rLocale)73 CharClass::CharClass(
74 			const ::com::sun::star::lang::Locale& rLocale )
75 {
76 	setLocale( rLocale );
77 	getComponentInstance();
78 }
79 
80 
~CharClass()81 CharClass::~CharClass()
82 {
83 }
84 
85 
getComponentInstance()86 void CharClass::getComponentInstance()
87 {
88 	try
89 	{
90 		// CharClass may be needed by "small tools" like the Setup
91 		// => maybe no service manager => loadLibComponentFactory
92 		Reference < XInterface > xI = ::comphelper::getComponentInstance(
93 			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( CHARCLASS_LIBRARYNAME ) ) ),
94 			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CHARCLASS_SERVICENAME ) ) );
95 		if ( xI.is() )
96 		{
97 			Any x = xI->queryInterface( ::getCppuType((const Reference< XCharacterClassification >*)0) );
98 			x >>= xCC;
99 		}
100 	}
101 	catch ( Exception& )
102 	{
103 		DBG_ERRORFILE( "getComponentInstance: Exception caught!" );
104 	}
105 }
106 
107 
setLocale(const::com::sun::star::lang::Locale & rLocale)108 void CharClass::setLocale( const ::com::sun::star::lang::Locale& rLocale )
109 {
110     ::osl::MutexGuard aGuard( aMutex );
111 	aLocale.Language = rLocale.Language;
112 	aLocale.Country = rLocale.Country;
113 	aLocale.Variant = rLocale.Variant;
114 }
115 
116 
getLocale() const117 const ::com::sun::star::lang::Locale& CharClass::getLocale() const
118 {
119     ::osl::MutexGuard aGuard( aMutex );
120     return aLocale;
121 }
122 
123 
124 // static
isAsciiNumeric(const String & rStr)125 sal_Bool CharClass::isAsciiNumeric( const String& rStr )
126 {
127 	if ( !rStr.Len() )
128 		return sal_False;
129 	register const sal_Unicode* p = rStr.GetBuffer();
130 	register const sal_Unicode* const pStop = p + rStr.Len();
131 	do
132 	{
133 		if ( !isAsciiDigit( *p ) )
134 			return sal_False;
135 	} while ( ++p < pStop );
136 	return sal_True;
137 }
138 
139 
140 // static
isAsciiAlpha(const String & rStr)141 sal_Bool CharClass::isAsciiAlpha( const String& rStr )
142 {
143 	if ( !rStr.Len() )
144 		return sal_False;
145 	register const sal_Unicode* p = rStr.GetBuffer();
146 	register const sal_Unicode* const pStop = p + rStr.Len();
147 	do
148 	{
149 		if ( !isAsciiAlpha( *p ) )
150 			return sal_False;
151 	} while ( ++p < pStop );
152 	return sal_True;
153 }
154 
155 
156 // static
isAsciiAlphaNumeric(const String & rStr)157 sal_Bool CharClass::isAsciiAlphaNumeric( const String& rStr )
158 {
159 	if ( !rStr.Len() )
160 		return sal_False;
161 	register const sal_Unicode* p = rStr.GetBuffer();
162 	register const sal_Unicode* const pStop = p + rStr.Len();
163 	do
164 	{
165 		if ( !isAsciiAlphaNumeric( *p ) )
166 			return sal_False;
167 	} while ( ++p < pStop );
168 	return sal_True;
169 }
170 
171 
isAlpha(const String & rStr,xub_StrLen nPos) const172 sal_Bool CharClass::isAlpha( const String& rStr, xub_StrLen nPos ) const
173 {
174     sal_Unicode c = rStr.GetChar( nPos );
175     if ( c < 128 )
176         return isAsciiAlpha( c );
177 
178 	try
179 	{
180 		if ( xCC.is() )
181             return  (xCC->getCharacterType( rStr, nPos, getLocale() ) &
182 				nCharClassAlphaType) != 0;
183 		else
184 			return sal_False;
185 	}
186 	catch ( Exception& )
187 	{
188 		DBG_ERRORFILE( "isAlpha: Exception caught!" );
189 		return sal_False;
190 	}
191 }
192 
193 
isAlpha(const String & rStr) const194 sal_Bool CharClass::isAlpha( const String& rStr ) const
195 {
196 	try
197 	{
198 		if ( xCC.is() )
199             return isAlphaType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) );
200 		else
201 			return sal_False;
202 	}
203 	catch ( Exception& )
204 	{
205 		DBG_ERRORFILE( "isAlpha: Exception caught!" );
206 		return sal_False;
207 	}
208 }
209 
210 
isLetter(const String & rStr,xub_StrLen nPos) const211 sal_Bool CharClass::isLetter( const String& rStr, xub_StrLen nPos ) const
212 {
213     sal_Unicode c = rStr.GetChar( nPos );
214     if ( c < 128 )
215         return isAsciiAlpha( c );
216 
217 	try
218 	{
219 		if ( xCC.is() )
220             return  (xCC->getCharacterType( rStr, nPos, getLocale() ) &
221 				nCharClassLetterType) != 0;
222 		else
223 			return sal_False;
224 	}
225 	catch ( Exception& )
226 	{
227 		DBG_ERRORFILE( "isLetter: Exception caught!" );
228 		return sal_False;
229 	}
230 }
231 
232 
isLetter(const String & rStr) const233 sal_Bool CharClass::isLetter( const String& rStr ) const
234 {
235 	try
236 	{
237 		if ( xCC.is() )
238             return isLetterType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) );
239 		else
240 			return sal_False;
241 	}
242 	catch ( Exception& )
243 	{
244 		DBG_ERRORFILE( "isLetter: Exception caught!" );
245 		return sal_False;
246 	}
247 }
248 
249 
isDigit(const String & rStr,xub_StrLen nPos) const250 sal_Bool CharClass::isDigit( const String& rStr, xub_StrLen nPos ) const
251 {
252     sal_Unicode c = rStr.GetChar( nPos );
253     if ( c < 128 )
254         return isAsciiDigit( c );
255 
256 	try
257 	{
258 		if ( xCC.is() )
259             return  (xCC->getCharacterType( rStr, nPos, getLocale() ) &
260 				KCharacterType::DIGIT) != 0;
261 		else
262 			return sal_False;
263 	}
264 	catch ( Exception& )
265 	{
266 		DBG_ERRORFILE( "isDigit: Exception caught!" );
267 		return sal_False;
268 	}
269 }
270 
271 
isNumeric(const String & rStr) const272 sal_Bool CharClass::isNumeric( const String& rStr ) const
273 {
274 	try
275 	{
276 		if ( xCC.is() )
277             return isNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) );
278 		else
279 			return sal_False;
280 	}
281 	catch ( Exception& )
282 	{
283 		DBG_ERRORFILE( "isNumeric: Exception caught!" );
284 		return sal_False;
285 	}
286 }
287 
288 
isAlphaNumeric(const String & rStr,xub_StrLen nPos) const289 sal_Bool CharClass::isAlphaNumeric( const String& rStr,	xub_StrLen nPos ) const
290 {
291     sal_Unicode c = rStr.GetChar( nPos );
292     if ( c < 128 )
293         return isAsciiAlphaNumeric( c );
294 
295 	try
296 	{
297 		if ( xCC.is() )
298             return  (xCC->getCharacterType( rStr, nPos, getLocale() ) &
299 				(nCharClassAlphaType | KCharacterType::DIGIT)) != 0;
300 		else
301 			return sal_False;
302 	}
303 	catch ( Exception& )
304 	{
305 		DBG_ERRORFILE( "isAlphaNumeric: Exception caught!" );
306 		return sal_False;
307 	}
308 }
309 
310 
isAlphaNumeric(const String & rStr) const311 sal_Bool CharClass::isAlphaNumeric( const String& rStr ) const
312 {
313 	try
314 	{
315 		if ( xCC.is() )
316             return isAlphaNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) );
317 		else
318 			return sal_False;
319 	}
320 	catch ( Exception& )
321 	{
322 		DBG_ERRORFILE( "isAlphaNumeric: Exception caught!" );
323 		return sal_False;
324 	}
325 }
326 
327 
isLetterNumeric(const String & rStr,xub_StrLen nPos) const328 sal_Bool CharClass::isLetterNumeric( const String& rStr, xub_StrLen nPos ) const
329 {
330     sal_Unicode c = rStr.GetChar( nPos );
331     if ( c < 128 )
332         return isAsciiAlphaNumeric( c );
333 
334 	try
335 	{
336 		if ( xCC.is() )
337             return  (xCC->getCharacterType( rStr, nPos, getLocale() ) &
338 				(nCharClassLetterType | KCharacterType::DIGIT)) != 0;
339 		else
340 			return sal_False;
341 	}
342 	catch ( Exception& )
343 	{
344 		DBG_ERRORFILE( "isLetterNumeric: Exception caught!" );
345 		return sal_False;
346 	}
347 }
348 
349 
isLetterNumeric(const String & rStr) const350 sal_Bool CharClass::isLetterNumeric( const String& rStr ) const
351 {
352 	try
353 	{
354 		if ( xCC.is() )
355             return isLetterNumericType( xCC->getStringType( rStr, 0, rStr.Len(), getLocale() ) );
356 		else
357 			return sal_False;
358 	}
359 	catch ( Exception& )
360 	{
361 		DBG_ERRORFILE( "isLetterNumeric: Exception caught!" );
362 		return sal_False;
363 	}
364 }
365 
366 
toUpper(const String & rStr,xub_StrLen nPos,xub_StrLen nCount) const367 String CharClass::toUpper( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const
368 {
369 	return toUpper_rtl(rStr, nPos, nCount);
370 }
371 
372 
toLower(const String & rStr,xub_StrLen nPos,xub_StrLen nCount) const373 String CharClass::toLower( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const
374 {
375 	return toLower_rtl(::rtl::OUString(rStr), nPos, nCount);
376 }
377 
378 
toTitle(const String & rStr,xub_StrLen nPos,xub_StrLen nCount) const379 String CharClass::toTitle( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const
380 {
381 	try
382 	{
383 		if ( xCC.is() )
384             return xCC->toTitle( rStr, nPos, nCount, getLocale() );
385 		else
386 			return rStr.Copy( nPos, nCount );
387 	}
388 	catch ( Exception& )
389 	{
390 		DBG_ERRORFILE( "toTitle: Exception caught!" );
391 		return rStr.Copy( nPos, nCount );
392 	}
393 }
394 
395 
toUpper_rtl(const::rtl::OUString & rStr,sal_Int32 nPos,sal_Int32 nCount) const396 ::rtl::OUString CharClass::toUpper_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const
397 {
398 	try
399 	{
400 		if ( xCC.is() )
401             return xCC->toUpper( rStr, nPos, nCount, getLocale() );
402 		else
403 			return rStr.copy( nPos, nCount );
404 	}
405 	catch ( Exception& )
406 	{
407 		DBG_ERRORFILE( "toUpper: Exception caught!" );
408 		return rStr.copy( nPos, nCount );
409 	}
410 }
411 
412 
toLower_rtl(const::rtl::OUString & rStr,sal_Int32 nPos,sal_Int32 nCount) const413 ::rtl::OUString CharClass::toLower_rtl( const ::rtl::OUString& rStr, sal_Int32 nPos, sal_Int32 nCount ) const
414 {
415 	try
416 	{
417 		if ( xCC.is() )
418             return xCC->toLower( rStr, nPos, nCount, getLocale() );
419 		else
420 			return rStr.copy( nPos, nCount );
421 	}
422 	catch ( Exception& )
423 	{
424 		DBG_ERRORFILE( "toLower: Exception caught!" );
425 		return rStr.copy( nPos, nCount );
426 	}
427 }
428 
429 
getType(const String & rStr,xub_StrLen nPos) const430 sal_Int16 CharClass::getType( const String& rStr, xub_StrLen nPos ) const
431 {
432 	try
433 	{
434 		if ( xCC.is() )
435 			return xCC->getType( rStr, nPos );
436 		else
437 			return 0;
438 	}
439 	catch ( Exception& )
440 	{
441 		DBG_ERRORFILE( "getType: Exception caught!" );
442 		return 0;
443 	}
444 }
445 
446 
getCharacterDirection(const String & rStr,xub_StrLen nPos) const447 sal_Int16 CharClass::getCharacterDirection( const String& rStr, xub_StrLen nPos ) const
448 {
449 	try
450 	{
451 		if ( xCC.is() )
452 			return xCC->getCharacterDirection( rStr, nPos );
453 		else
454 			return 0;
455 	}
456 	catch ( Exception& )
457 	{
458 		DBG_ERRORFILE( "getCharacterDirection: Exception caught!" );
459 		return 0;
460 	}
461 }
462 
463 
getScript(const String & rStr,xub_StrLen nPos) const464 sal_Int16 CharClass::getScript( const String& rStr, xub_StrLen nPos ) const
465 {
466 	try
467 	{
468 		if ( xCC.is() )
469 			return xCC->getScript( rStr, nPos );
470 		else
471 			return 0;
472 	}
473 	catch ( Exception& )
474 	{
475 		DBG_ERRORFILE( "getScript: Exception caught!" );
476 		return 0;
477 	}
478 }
479 
480 
getCharacterType(const String & rStr,xub_StrLen nPos) const481 sal_Int32 CharClass::getCharacterType( const String& rStr, xub_StrLen nPos ) const
482 {
483 	try
484 	{
485 		if ( xCC.is() )
486             return xCC->getCharacterType( rStr, nPos, getLocale() );
487 		else
488 			return 0;
489 	}
490 	catch ( Exception& )
491 	{
492 		DBG_ERRORFILE( "getCharacterType: Exception caught!" );
493 		return 0;
494 	}
495 }
496 
497 
getStringType(const String & rStr,xub_StrLen nPos,xub_StrLen nCount) const498 sal_Int32 CharClass::getStringType( const String& rStr, xub_StrLen nPos, xub_StrLen nCount ) const
499 {
500 	try
501 	{
502 		if ( xCC.is() )
503             return xCC->getStringType( rStr, nPos, nCount, getLocale() );
504 		else
505 			return 0;
506 	}
507 	catch ( Exception& )
508 	{
509 		DBG_ERRORFILE( "getStringType: Exception caught!" );
510 		return 0;
511 	}
512 }
513 
514 
parseAnyToken(const String & rStr,sal_Int32 nPos,sal_Int32 nStartCharFlags,const String & userDefinedCharactersStart,sal_Int32 nContCharFlags,const String & userDefinedCharactersCont) const515 ::com::sun::star::i18n::ParseResult CharClass::parseAnyToken(
516 			const String& rStr,
517 			sal_Int32 nPos,
518 			sal_Int32 nStartCharFlags,
519 			const String& userDefinedCharactersStart,
520 			sal_Int32 nContCharFlags,
521 			const String& userDefinedCharactersCont ) const
522 {
523 	try
524 	{
525 		if ( xCC.is() )
526             return xCC->parseAnyToken( rStr, nPos, getLocale(),
527 				nStartCharFlags, userDefinedCharactersStart,
528 				nContCharFlags, userDefinedCharactersCont );
529 		else
530 			return ParseResult();
531 	}
532 	catch ( Exception& e )
533 	{
534 #ifdef DBG_UTIL
535         ByteString aMsg( "parseAnyToken: Exception caught\n" );
536         aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
537         DBG_ERRORFILE( aMsg.GetBuffer() );
538 #else
539         (void)e;
540 #endif
541 		return ParseResult();
542 	}
543 }
544 
545 
parsePredefinedToken(sal_Int32 nTokenType,const String & rStr,sal_Int32 nPos,sal_Int32 nStartCharFlags,const String & userDefinedCharactersStart,sal_Int32 nContCharFlags,const String & userDefinedCharactersCont) const546 ::com::sun::star::i18n::ParseResult CharClass::parsePredefinedToken(
547 			sal_Int32 nTokenType,
548 			const String& rStr,
549 			sal_Int32 nPos,
550 			sal_Int32 nStartCharFlags,
551 			const String& userDefinedCharactersStart,
552 			sal_Int32 nContCharFlags,
553 			const String& userDefinedCharactersCont ) const
554 {
555 	try
556 	{
557 		if ( xCC.is() )
558             return xCC->parsePredefinedToken( nTokenType, rStr, nPos, getLocale(),
559 				nStartCharFlags, userDefinedCharactersStart,
560 				nContCharFlags, userDefinedCharactersCont );
561 		else
562 			return ParseResult();
563 	}
564 	catch ( Exception& e )
565 	{
566 #ifdef DBG_UTIL
567         ByteString aMsg( "parsePredefinedToken: Exception caught\n" );
568         aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
569         DBG_ERRORFILE( aMsg.GetBuffer() );
570 #else
571         (void)e;
572 #endif
573 		return ParseResult();
574 	}
575 }
576 
577 
578 
579