1+ /* Copyright (C) 2014 Runtime Revolution Ltd.
2+
3+ This file is part of LiveCode.
4+
5+ LiveCode is free software; you can redistribute it and/or modify it under
6+ the terms of the GNU General Public License v3 as published by the Free
7+ Software Foundation.
8+
9+ LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
10+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+ for more details.
13+
14+ You should have received a copy of the GNU General Public License
15+ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
16+
17+ #include " foundation.h"
18+ #include " foundation-private.h"
19+ #include " foundation-auto.h"
20+
21+ #define R8L 384
22+
23+ inline void MCU_skip_spaces (const char *&sptr, uinteger_t &l)
24+ {
25+ while (l && isspace ((uint8_t )*sptr))
26+ {
27+ sptr++;
28+ l--;
29+ }
30+ }
31+
32+ static integer_t MCU_strtol (const char *sptr, uindex_t &l, int8_t c, bool &done,
33+ bool reals, bool octals)
34+ {
35+ done = false ;
36+ MCU_skip_spaces (sptr, l);
37+ if (!l)
38+ return 0 ;
39+ bool negative = false ;
40+ integer_t value = 0 ;
41+ if (*sptr == ' -' || *sptr == ' +' )
42+ {
43+ negative = *sptr == ' -' ;
44+ sptr++;
45+ l--;
46+ }
47+ if (!l)
48+ return 0 ;
49+ uinteger_t startlength = l;
50+ uint16_t base = 10 ;
51+ if (l && *sptr == ' 0' )
52+ {
53+ if (l > 2 && MCNativeCharFold (*(sptr + 1 )) == ' x' )
54+ {
55+ base = 16 ;
56+ sptr += 2 ;
57+ l -= 2 ;
58+ }
59+ else
60+ {
61+ if (octals)
62+ {
63+ base = 8 ;
64+ sptr++;
65+ l--;
66+ }
67+ }
68+ }
69+ while (l)
70+ {
71+ if (isdigit ((uint8_t )*sptr))
72+ {
73+ integer_t v = *sptr - ' 0' ;
74+ if (base < 16 && value > INTEGER_MAX / base - v) // prevent overflow
75+ return 0 ;
76+ value *= base;
77+ value += v;
78+ }
79+ else
80+ if (isspace ((uint8_t )*sptr))
81+ {
82+ MCU_skip_spaces (sptr, l);
83+ if (l && *sptr == c)
84+ {
85+ sptr++;
86+ l--;
87+ }
88+ break ;
89+ }
90+ else
91+ if (l && c && *sptr == c)
92+ {
93+ sptr++;
94+ l--;
95+ break ;
96+ }
97+ else
98+ if (*sptr == ' .' )
99+ {
100+ if (startlength > 1 )
101+ {
102+ if (reals)
103+ {
104+ // MDW-2013-06-09: [[ Bug 10964 ]] Round integral values to nearest
105+ // (consistent with getuint4() and round()).
106+ if (*(sptr+1 ) > ' 4' )
107+ {
108+ value++;
109+ }
110+ do
111+ {
112+ sptr++;
113+ l--;
114+ }
115+ while (l && isdigit ((uint8_t )*sptr));
116+ }
117+ else
118+ do
119+ {
120+ sptr++;
121+ l--;
122+ }
123+ while (l && *sptr == ' 0' );
124+ if (l == 0 )
125+ break ;
126+ if (*sptr == c || isspace ((uint8_t )*sptr))
127+ {
128+ sptr++;
129+ l--;
130+ break ;
131+ }
132+ }
133+ return 0 ;
134+ }
135+ else
136+ {
137+ char c = MCNativeCharFold (*sptr);
138+ if (base == 16 && c >= ' a' && c <= ' f' )
139+ {
140+ value *= base;
141+ value += c - ' a' + 10 ;
142+ }
143+ else
144+ return 0 ;
145+ }
146+ sptr++;
147+ l--;
148+ }
149+ if (negative)
150+ value = -value;
151+ MCU_skip_spaces (sptr, l);
152+ done = true ;
153+ return value;
154+ }
155+
156+ bool MCTypeConvertStringToLongInteger (MCStringRef p_string, integer_t & r_converted)
157+ {
158+ if (!MCStringCanBeNative (p_string))
159+ return false ;
160+
161+ MCAutoStringRefAsCString t_cstring;
162+ t_cstring . Lock (p_string);
163+
164+ bool t_done;
165+ uindex_t t_length = strlen (*t_cstring);
166+ r_converted = MCU_strtol (*t_cstring, t_length, ' \0 ' , t_done, false , false );
167+ return t_done;
168+ }
169+
170+ bool MCTypeConvertStringToReal (MCStringRef p_string, real64_t & r_converted, bool p_convert_octals)
171+ {
172+ if (!MCStringCanBeNative (p_string))
173+ return false ;
174+
175+ MCAutoStringRefAsCString t_cstring;
176+ t_cstring . Lock (p_string);
177+
178+ const char *sptr = *t_cstring;
179+ uindex_t l = strlen (sptr);
180+ bool done;
181+ integer_t i = MCU_strtol (sptr, l, ' \0 ' , done, false , p_convert_octals);
182+ if (done)
183+ {
184+ r_converted = i;
185+ return l == 0 ;
186+ }
187+ sptr = *t_cstring;
188+ l = MCMin (R8L - 1U , strlen (sptr));
189+ MCU_skip_spaces (sptr, l);
190+ // bugs in MSL means we need to check these things
191+ // MW-2006-04-21: [[ Purify ]] This was incorrect - we need to ensure l > 1 before running most
192+ // of these tests.
193+ if (l == 0 || (l > 1 && (((MCNativeCharFold ((uint8_t )sptr[1 ]) == ' x' && (l == 2 || !isxdigit ((uint8_t )sptr[2 ])))
194+ || (sptr[1 ] == ' +' || sptr[1 ] == ' -' )))))
195+ return false ;
196+ char buff[R8L];
197+ memcpy (buff, sptr, l);
198+ buff[l] = ' \0 ' ;
199+ const char *newptr;
200+ r_converted = strtod ((char *)buff, (char **)&newptr);
201+ if (newptr == buff)
202+ return false ;
203+ l = buff + l - newptr;
204+ MCU_skip_spaces (newptr, l);
205+ if (l != 0 )
206+ return false ;
207+ return true ;
208+ }
209+
210+ bool MCTypeConvertStringToBool (MCStringRef p_string, bool & r_converted)
211+ {
212+ if (MCStringIsEqualTo (p_string, kMCTrueString , kMCStringOptionCompareCaseless ))
213+ {
214+ r_converted = true ;
215+ return true ;
216+ }
217+
218+ if (MCStringIsEqualTo (p_string, kMCFalseString , kMCStringOptionCompareCaseless ))
219+ {
220+ r_converted = false ;
221+ return true ;
222+ }
223+
224+ return false ;
225+ }
0 commit comments