1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <formula/formulahelper.hxx>
23 #include <formula/IFunctionDescription.hxx>
24 #include <unotools/charclass.hxx>
25 #include <unotools/syslocale.hxx>
33 class OEmptyFunctionDescription
: public IFunctionDescription
36 OEmptyFunctionDescription(){}
37 virtual ~OEmptyFunctionDescription(){}
39 virtual OUString
getFunctionName() const override
{ return OUString(); }
40 virtual const IFunctionCategory
* getCategory() const override
{ return nullptr; }
41 virtual OUString
getDescription() const override
{ return OUString(); }
42 virtual sal_Int32
getSuppressedArgumentCount() const override
{ return 0; }
43 virtual OUString
getFormula(const ::std::vector
< OUString
>& ) const override
{ return OUString(); }
44 virtual void fillVisibleArgumentMapping(::std::vector
<sal_uInt16
>& ) const override
{}
45 virtual void initArgumentInfo() const override
{}
46 virtual OUString
getSignature() const override
{ return OUString(); }
47 virtual OUString
getHelpId() const override
{ return ""; }
48 virtual bool isHidden() const override
{ return false; }
49 virtual sal_uInt32
getParameterCount() const override
{ return 0; }
50 virtual sal_uInt32
getVarArgsStart() const override
{ return 0; }
51 virtual sal_uInt32
getVarArgsLimit() const override
{ return 0; }
52 virtual OUString
getParameterName(sal_uInt32
) const override
{ return OUString(); }
53 virtual OUString
getParameterDescription(sal_uInt32
) const override
{ return OUString(); }
54 virtual bool isParameterOptional(sal_uInt32
) const override
{ return false; }
58 // class FormulaHelper - static Method
61 #define FUNC_NOTFOUND -1
63 FormulaHelper::FormulaHelper(const IFunctionManager
* _pFunctionManager
)
64 :m_rCharClass(m_aSysLocale
.GetCharClass())
65 ,m_pFunctionManager(_pFunctionManager
)
66 ,open(_pFunctionManager
->getSingleToken(IFunctionManager::eOk
))
67 ,close(_pFunctionManager
->getSingleToken(IFunctionManager::eClose
))
68 ,sep(_pFunctionManager
->getSingleToken(IFunctionManager::eSep
))
69 ,arrayOpen(_pFunctionManager
->getSingleToken(IFunctionManager::eArrayOpen
))
70 ,arrayClose(_pFunctionManager
->getSingleToken(IFunctionManager::eArrayClose
))
74 sal_Int32
FormulaHelper::GetCategoryCount() const
76 return m_pFunctionManager
->getCount();
79 bool FormulaHelper::GetNextFunc( const OUString
& rFormula
,
81 sal_Int32
& rFStart
, // Input and output
82 sal_Int32
* pFEnd
, // = NULL
83 const IFunctionDescription
** ppFDesc
, // = NULL
84 ::std::vector
< OUString
>* pArgs
) const // = NULL
86 sal_Int32 nOldStart
= rFStart
;
89 rFStart
= GetFunctionStart( rFormula
, rFStart
, bBack
, ppFDesc
? &aFname
: nullptr );
90 bool bFound
= ( rFStart
!= FUNC_NOTFOUND
);
95 *pFEnd
= GetFunctionEnd( rFormula
, rFStart
);
100 const sal_uInt32 nCategoryCount
= m_pFunctionManager
->getCount();
101 for(sal_uInt32 j
= 0; j
< nCategoryCount
&& !*ppFDesc
; ++j
)
103 const IFunctionCategory
* pCategory
= m_pFunctionManager
->getCategory(j
);
104 const sal_uInt32 nCount
= pCategory
->getCount();
105 for(sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
107 const IFunctionDescription
* pCurrent
= pCategory
->getFunction(i
);
108 if ( pCurrent
->getFunctionName().equalsIgnoreAsciiCase(aFname
) )
113 }// for(sal_uInt32 i = 0 ; i < nCount; ++i)
115 if ( *ppFDesc
&& pArgs
)
117 GetArgStrings( *pArgs
,rFormula
, rFStart
, static_cast<sal_uInt16
>((*ppFDesc
)->getParameterCount() ));
121 static OEmptyFunctionDescription s_aFunctionDescription
;
122 *ppFDesc
= &s_aFunctionDescription
;
133 void FormulaHelper::FillArgStrings( std::u16string_view rFormula
,
136 ::std::vector
< OUString
>& _rArgs
) const
138 sal_Int32 nStart
= 0;
143 for ( i
=0; i
<nArgs
&& !bLast
; i
++ )
145 nStart
= GetArgStart( rFormula
, nFuncPos
, i
);
147 if ( i
+1<nArgs
) // last argument?
149 nEnd
= GetArgStart( rFormula
, nFuncPos
, i
+1 );
151 if ( nEnd
!= nStart
)
152 _rArgs
.push_back(OUString(rFormula
.substr( nStart
, nEnd
-1-nStart
)));
155 _rArgs
.emplace_back();
161 nEnd
= GetFunctionEnd( rFormula
, nFuncPos
)-1;
163 _rArgs
.push_back( OUString(rFormula
.substr( nStart
, nEnd
-nStart
)) );
165 _rArgs
.emplace_back();
170 for ( ; i
<nArgs
; i
++ )
171 _rArgs
.emplace_back();
175 void FormulaHelper::GetArgStrings( ::std::vector
< OUString
>& _rArgs
,
176 std::u16string_view rFormula
,
178 sal_uInt16 nArgs
) const
182 FillArgStrings( rFormula
, nFuncPos
, nArgs
, _rArgs
);
187 static bool IsFormulaText(const CharClass
& rCharClass
, const OUString
& rStr
, sal_Int32 nPos
)
189 if( rCharClass
.isLetterNumeric( rStr
, nPos
) )
192 { // In internationalized versions function names may contain a dot
193 // and in every version also an underscore... ;-)
194 sal_Unicode c
= rStr
[nPos
];
195 return c
== '.' || c
== '_';
200 sal_Int32
FormulaHelper::GetFunctionStart( const OUString
& rFormula
,
203 OUString
* pFuncName
) const
205 sal_Int32 nStrLen
= rFormula
.getLength();
207 if ( nStrLen
< nStart
)
210 sal_Int32 nFStart
= FUNC_NOTFOUND
;
211 sal_Int32 nParPos
= bBack
? ::std::min( nStart
, nStrLen
- 1) : nStart
;
221 while ( !bFound
&& (nParPos
> 0) )
223 if ( rFormula
[nParPos
] == '"' )
226 while ( (nParPos
> 0) && rFormula
[nParPos
] != '"' )
233 bFound
= rFormula
[nParPos
] == '(';
241 while ( !bFound
&& (0 <= nParPos
&& nParPos
< nStrLen
) )
243 if ( rFormula
[nParPos
] == '"' )
246 while ( (nParPos
< nStrLen
) && rFormula
[nParPos
] != '"' )
252 bFound
= rFormula
[nParPos
] == '(';
259 if ( bFound
&& (nParPos
> 0) )
263 while ( (nFStart
> 0) && IsFormulaText(m_rCharClass
, rFormula
, nFStart
))
271 if ( IsFormulaText( m_rCharClass
, rFormula
, nFStart
) )
275 *pFuncName
= rFormula
.copy( nFStart
, nParPos
-nFStart
);
277 else // Brackets without function -> keep searching
282 else if (nParPos
> 0)
288 else // No brackets found
290 nFStart
= FUNC_NOTFOUND
;
301 sal_Int32
FormulaHelper::GetFunctionEnd( std::u16string_view rStr
, sal_Int32 nStart
) const
303 sal_Int32 nStrLen
= rStr
.size();
305 if ( nStrLen
< nStart
)
309 bool bInArray
= false;
312 while ( !bFound
&& (nStart
< nStrLen
) )
314 sal_Unicode c
= rStr
[nStart
];
319 while ( (nStart
< nStrLen
) && rStr
[nStart
] != '"' )
322 else if ( c
== open
)
324 else if ( c
== close
)
327 if ( nParCount
== 0 )
329 else if ( nParCount
< 0 )
332 nStart
--; // read one too far
335 else if ( c
== arrayOpen
)
339 else if ( c
== arrayClose
)
345 if ( !bInArray
&& nParCount
== 0 )
348 nStart
--; // read one too far
351 nStart
++; // Set behind found position
354 // nStart > nStrLen can happen if there was an unclosed quote; instead of
355 // checking that in every loop iteration check it once here.
356 return std::min(nStart
, nStrLen
);
360 sal_Int32
FormulaHelper::GetArgStart( std::u16string_view rStr
, sal_Int32 nStart
, sal_uInt16 nArg
) const
362 sal_Int32 nStrLen
= rStr
.size();
364 if ( nStrLen
< nStart
)
368 bool bInArray
= false;
371 while ( !bFound
&& (nStart
< nStrLen
) )
373 sal_Unicode c
= rStr
[nStart
];
378 while ( (nStart
< nStrLen
) && rStr
[nStart
] != '"' )
381 else if ( c
== open
)
383 bFound
= ( nArg
== 0 );
386 else if ( c
== close
)
389 bFound
= ( nParCount
== 0 );
391 else if ( c
== arrayOpen
)
395 else if ( c
== arrayClose
)
401 if ( !bInArray
&& nParCount
== 1 )
404 bFound
= ( nArg
== 0 );
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */