/**************************************************************
 * 
 * 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_basegfx.hxx"

#include <stringconversiontools.hxx>
#include <rtl/math.hxx>

namespace basegfx
{
    namespace internal
    {
        void lcl_skipSpaces(sal_Int32& 				io_rPos, 
                            const ::rtl::OUString& 	rStr, 
                            const sal_Int32 		nLen)
        {
            while( io_rPos < nLen &&
                    sal_Unicode(' ') == rStr[io_rPos] )
            {
                ++io_rPos;
            }
        }

        void lcl_skipSpacesAndCommas(sal_Int32& 			io_rPos, 
                                        const ::rtl::OUString& rStr, 
                                        const sal_Int32 		nLen)
        {
            while(io_rPos < nLen 
                    && (sal_Unicode(' ') == rStr[io_rPos] || sal_Unicode(',') == rStr[io_rPos]))
            {
                ++io_rPos;
            }
        }

        bool lcl_getDoubleChar(double& o_fRetval, sal_Int32& io_rPos, const ::rtl::OUString& rStr)
        {
            sal_Unicode aChar( rStr[io_rPos] );
            ::rtl::OUStringBuffer sNumberString;

            // sign
            if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            // numbers before point
            while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            // point
            if(sal_Unicode('.') == aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            // numbers after point
            while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            // 'e'
            if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];

                // sign for 'e'
                if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
                {
                    sNumberString.append(rStr[io_rPos]);
                    aChar = rStr[++io_rPos];
                }

                // number for 'e'
                while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
                {
                    sNumberString.append(rStr[io_rPos]);
                    aChar = rStr[++io_rPos];
                }
            }

            if(sNumberString.getLength())
            {
                rtl_math_ConversionStatus eStatus;
                o_fRetval = ::rtl::math::stringToDouble( sNumberString.makeStringAndClear(), 
                                                            (sal_Unicode)('.'), 
                                                            (sal_Unicode)(','), 
                                                            &eStatus, 
                                                            NULL );
                return ( eStatus == rtl_math_ConversionStatus_Ok );
            }

            return false;
        }

        bool lcl_importDoubleAndSpaces( double& 				o_fRetval, 
                                        sal_Int32& 				io_rPos, 
                                        const ::rtl::OUString& 	rStr, 
                                        const sal_Int32 		nLen )
        {
            if( !lcl_getDoubleChar(o_fRetval, io_rPos, rStr) )
                return false;

            lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);

            return true;
        }

        bool lcl_importNumberAndSpaces(sal_Int32&                o_nRetval,
                                        sal_Int32& 				io_rPos, 
                                        const ::rtl::OUString& 	rStr, 
                                        const sal_Int32 		nLen)
        {
            sal_Unicode aChar( rStr[io_rPos] );
            ::rtl::OUStringBuffer sNumberString;

            if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
            {
                sNumberString.append(rStr[io_rPos]);
                aChar = rStr[++io_rPos];
            }

            if(sNumberString.getLength())
            {
                o_nRetval = sNumberString.makeStringAndClear().toInt32();
                lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);

                return true;
            }

            return false;
        }

        void lcl_skipNumber(sal_Int32& 				io_rPos, 
                            const ::rtl::OUString& 	rStr, 
                            const sal_Int32 		nLen)
        {
            bool bSignAllowed(true);

            while(io_rPos < nLen && lcl_isOnNumberChar(rStr, io_rPos, bSignAllowed, true))
            {
                bSignAllowed = false;
                ++io_rPos;
            }
        }

        void lcl_skipDouble(sal_Int32& io_rPos, const ::rtl::OUString& rStr)
        {
            sal_Unicode aChar( rStr[io_rPos] );

            // sign
            if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
            {
                aChar = rStr[++io_rPos];
            }

            // numbers before point
            while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
            {
                aChar = rStr[++io_rPos];
            }

            // point
            if(sal_Unicode('.') == aChar)
            {
                aChar = rStr[++io_rPos];
            }

            // numbers after point
            while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
            {
                aChar = rStr[++io_rPos];
            }

            // 'e'
            if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
            {
                aChar = rStr[++io_rPos];

                // sign of 'e'
                if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
                {
                    aChar = rStr[++io_rPos];
                }

                // numbers for 'e'
                while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
                {
                    aChar = rStr[++io_rPos];
                }
            }
        }

        void lcl_putNumberCharWithSpace( ::rtl::OUStringBuffer& rStr, 
                                            double 		        fValue,
                                            double 		        fOldValue,
                                            bool 			        bUseRelativeCoordinates )
        {
            if( bUseRelativeCoordinates )
                fValue -= fOldValue;

            const sal_Int32 aLen( rStr.getLength() );
            if(aLen)
            {
                if( lcl_isOnNumberChar(rStr.charAt(aLen - 1), false, true) && 
                    fValue >= 0.0 )
                {
                    rStr.append( sal_Unicode(' ') );
                }
            }

            lcl_putNumberChar(rStr, fValue);
        }
    } // namespace internal
}

// eof