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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_basegfx.hxx"
24 
25 #include <stringconversiontools.hxx>
26 #include <rtl/math.hxx>
27 
28 namespace basegfx
29 {
30     namespace internal
31     {
32         void lcl_skipSpaces(sal_Int32& 				io_rPos,
33                             const ::rtl::OUString& 	rStr,
34                             const sal_Int32 		nLen)
35         {
36             while( io_rPos < nLen &&
37                     sal_Unicode(' ') == rStr[io_rPos] )
38             {
39                 ++io_rPos;
40             }
41         }
42 
43         void lcl_skipSpacesAndCommas(sal_Int32& 			io_rPos,
44                                         const ::rtl::OUString& rStr,
45                                         const sal_Int32 		nLen)
46         {
47             while(io_rPos < nLen
48                     && (sal_Unicode(' ') == rStr[io_rPos] || sal_Unicode(',') == rStr[io_rPos]))
49             {
50                 ++io_rPos;
51             }
52         }
53 
54         bool lcl_getDoubleChar(double& o_fRetval, sal_Int32& io_rPos, const ::rtl::OUString& rStr)
55         {
56             sal_Unicode aChar( rStr[io_rPos] );
57             ::rtl::OUStringBuffer sNumberString;
58 
59             // sign
60             if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
61             {
62                 sNumberString.append(rStr[io_rPos]);
63                 aChar = rStr[++io_rPos];
64             }
65 
66             // numbers before point
67             while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
68             {
69                 sNumberString.append(rStr[io_rPos]);
70                 aChar = rStr[++io_rPos];
71             }
72 
73             // point
74             if(sal_Unicode('.') == aChar)
75             {
76                 sNumberString.append(rStr[io_rPos]);
77                 aChar = rStr[++io_rPos];
78             }
79 
80             // numbers after point
81             while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
82             {
83                 sNumberString.append(rStr[io_rPos]);
84                 aChar = rStr[++io_rPos];
85             }
86 
87             // 'e'
88             if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
89             {
90                 sNumberString.append(rStr[io_rPos]);
91                 aChar = rStr[++io_rPos];
92 
93                 // sign for 'e'
94                 if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
95                 {
96                     sNumberString.append(rStr[io_rPos]);
97                     aChar = rStr[++io_rPos];
98                 }
99 
100                 // number for 'e'
101                 while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
102                 {
103                     sNumberString.append(rStr[io_rPos]);
104                     aChar = rStr[++io_rPos];
105                 }
106             }
107 
108             if(sNumberString.getLength())
109             {
110                 rtl_math_ConversionStatus eStatus;
111                 o_fRetval = ::rtl::math::stringToDouble( sNumberString.makeStringAndClear(),
112                                                             (sal_Unicode)('.'),
113                                                             (sal_Unicode)(','),
114                                                             &eStatus,
115                                                             NULL );
116                 return ( eStatus == rtl_math_ConversionStatus_Ok );
117             }
118 
119             return false;
120         }
121 
122         bool lcl_importDoubleAndSpaces( double& 				o_fRetval,
123                                         sal_Int32& 				io_rPos,
124                                         const ::rtl::OUString& 	rStr,
125                                         const sal_Int32 		nLen )
126         {
127             if( !lcl_getDoubleChar(o_fRetval, io_rPos, rStr) )
128                 return false;
129 
130             lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
131 
132             return true;
133         }
134 
135         bool lcl_importNumberAndSpaces(sal_Int32&                o_nRetval,
136                                         sal_Int32& 				io_rPos,
137                                         const ::rtl::OUString& 	rStr,
138                                         const sal_Int32 		nLen)
139         {
140             sal_Unicode aChar( rStr[io_rPos] );
141             ::rtl::OUStringBuffer sNumberString;
142 
143             if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
144             {
145                 sNumberString.append(rStr[io_rPos]);
146                 aChar = rStr[++io_rPos];
147             }
148 
149             while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
150             {
151                 sNumberString.append(rStr[io_rPos]);
152                 aChar = rStr[++io_rPos];
153             }
154 
155             if(sNumberString.getLength())
156             {
157                 o_nRetval = sNumberString.makeStringAndClear().toInt32();
158                 lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
159 
160                 return true;
161             }
162 
163             return false;
164         }
165 
166         void lcl_skipNumber(sal_Int32& 				io_rPos,
167                             const ::rtl::OUString& 	rStr,
168                             const sal_Int32 		nLen)
169         {
170             bool bSignAllowed(true);
171 
172             while(io_rPos < nLen && lcl_isOnNumberChar(rStr, io_rPos, bSignAllowed, true))
173             {
174                 bSignAllowed = false;
175                 ++io_rPos;
176             }
177         }
178 
179         void lcl_skipDouble(sal_Int32& io_rPos, const ::rtl::OUString& rStr)
180         {
181             sal_Unicode aChar( rStr[io_rPos] );
182 
183             // sign
184             if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
185             {
186                 aChar = rStr[++io_rPos];
187             }
188 
189             // numbers before point
190             while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
191             {
192                 aChar = rStr[++io_rPos];
193             }
194 
195             // point
196             if(sal_Unicode('.') == aChar)
197             {
198                 aChar = rStr[++io_rPos];
199             }
200 
201             // numbers after point
202             while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
203             {
204                 aChar = rStr[++io_rPos];
205             }
206 
207             // 'e'
208             if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
209             {
210                 aChar = rStr[++io_rPos];
211 
212                 // sign of 'e'
213                 if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
214                 {
215                     aChar = rStr[++io_rPos];
216                 }
217 
218                 // numbers for 'e'
219                 while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
220                 {
221                     aChar = rStr[++io_rPos];
222                 }
223             }
224         }
225 
226         void lcl_putNumberCharWithSpace( ::rtl::OUStringBuffer& rStr,
227                                             double 		        fValue,
228                                             double 		        fOldValue,
229                                             bool 			        bUseRelativeCoordinates )
230         {
231             if( bUseRelativeCoordinates )
232                 fValue -= fOldValue;
233 
234             const sal_Int32 aLen( rStr.getLength() );
235             if(aLen)
236             {
237                 if( lcl_isOnNumberChar(rStr.charAt(aLen - 1), false, true) &&
238                     fValue >= 0.0 )
239                 {
240                     rStr.append( sal_Unicode(' ') );
241                 }
242             }
243 
244             lcl_putNumberChar(rStr, fValue);
245         }
246     } // namespace internal
247 }
248 
249 // eof
250