Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 47e0916

Browse files
author
runrevali
committed
Implement basic type conversion
1 parent d94cdc0 commit 47e0916

File tree

10 files changed

+375
-26
lines changed

10 files changed

+375
-26
lines changed

engine/src/bitmapeffect.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static Exec_stat MCBitmapEffectSetCardinalProperty(uint4 p_bound, MCStringRef p_
289289
static Exec_stat MCBitmapEffectSetBooleanProperty(MCStringRef p_data, bool p_current_value, bool& r_new_value, Boolean& r_dirty)
290290
{
291291
bool t_value;
292-
if (!MCU_stob(p_data, t_value))
292+
if (!MCTypeConvertStringToBool(p_data, t_value))
293293
{
294294
MCeerror -> add(EE_BITMAPEFFECT_BADBOOLEAN, 0, 0, p_data);
295295
return ES_ERROR;

engine/src/exec-files.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,7 @@ void MCFilesExecWriteToStream(MCExecContext& ctxt, IO_handle p_stream, MCStringR
22152215
MCAutoStringRef s;
22162216
/* UNCHECKED */ MCStringCopySubstring(p_data, MCRangeMake(t_start_pos, t_data_pos - t_start_pos), &s);
22172217
real8 n;
2218-
if (!MCU_stor8(*s, n))
2218+
if (!MCTypeConvertStringToReal(*s, n))
22192219
{
22202220
ctxt . LegacyThrow(EE_FUNCTION_NAN);
22212221
r_stat = IO_ERROR;

engine/src/exec-interface-object.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ struct MCInterfaceShadow
801801

802802
static void MCInterfaceShadowParse(MCExecContext& ctxt, MCStringRef p_input, MCInterfaceShadow& r_output)
803803
{
804-
if (MCU_stob(p_input, r_output . flag))
804+
if (MCTypeConvertStringToBool(p_input, r_output . flag))
805805
r_output . is_flag = true;
806806
else if (MCU_stoi2(p_input, r_output . shadow))
807807
r_output . is_flag = false;
@@ -921,7 +921,7 @@ void MCInterfaceTriStateParse(MCExecContext& ctxt, MCStringRef p_input, MCInterf
921921
r_output . type = kMCInterfaceTriStateMixed;
922922
}
923923

924-
if (MCU_stob(p_input, r_output . state))
924+
if (MCTypeConvertStringToBool(p_input, r_output . state))
925925
{
926926
r_output . type = kMCInterfaceTriStateBoolean;
927927
return;

engine/src/exec-interface-scrollbar.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ void MCScrollbar::GetThumbPos(MCExecContext& ctxt, double& r_pos)
148148
// AL-2014-07-22: [[ Bug 12843 ]] Round thumbpos according to scrollbar number format
149149
MCAutoStringRef t_formatted_thumbpos;
150150
if (MCU_r8tos(thumbpos, nffw, nftrailing, nfforce, &t_formatted_thumbpos) &&
151-
MCU_stor8(*t_formatted_thumbpos, r_pos))
151+
MCTypeConvertStringToReal(*t_formatted_thumbpos, r_pos))
152152
return;
153153

154154
ctxt . Throw();
@@ -236,7 +236,7 @@ void MCScrollbar::SetStartValue(MCExecContext& ctxt, MCStringRef p_value)
236236
return;
237237
}
238238

239-
if (!MCU_stor8(p_value, startvalue))
239+
if (!MCTypeConvertStringToReal(p_value, startvalue))
240240
{
241241
ctxt . LegacyThrow(EE_OBJECT_NAN);
242242
return;
@@ -268,7 +268,7 @@ void MCScrollbar::SetEndValue(MCExecContext& ctxt, MCStringRef p_value)
268268
return;
269269
}
270270

271-
if (!MCU_stor8(p_value, endvalue))
271+
if (!MCTypeConvertStringToReal(p_value, endvalue))
272272
{
273273
ctxt . LegacyThrow(EE_OBJECT_NAN);
274274
return;

engine/src/exec-legacy.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ void MCLegacyEvalStackSpace(MCExecContext& ctxt, integer_t& r_bytes)
178178
void MCLegacyEvalIsNumber(MCExecContext& ctxt, MCStringRef p_string, bool& r_bool)
179179
{
180180
real64_t t_real;
181-
r_bool = MCU_stor8(p_string, t_real);
181+
r_bool = MCTypeConvertStringToReal(p_string, t_real);
182182
}
183183

184184
////////////////////////////////////////////////////////////////////////////////

engine/src/exec.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ bool MCExecContext::ConvertToNumber(MCValueRef p_value, MCNumberRef& r_number)
126126
if (MCStringGetLength(MCNameGetString((MCNameRef)p_value)) != 0 &&
127127
!MCStringGetNumericValue(MCNameGetString((MCNameRef)p_value), t_number))
128128
{
129-
if (!MCU_stor8(MCNameGetString((MCNameRef)p_value), t_number, m_convertoctals))
129+
if (!MCTypeConvertStringToReal(MCNameGetString((MCNameRef)p_value), t_number, m_convertoctals))
130130
break;
131131

132132
// Converting to octals doesn't generate the 10-based number stored in the string
@@ -144,7 +144,7 @@ bool MCExecContext::ConvertToNumber(MCValueRef p_value, MCNumberRef& r_number)
144144
// Fetches the numeric value in case it exists, or stores the one therefore computed otherwise
145145
if (MCStringGetLength((MCStringRef)p_value) != 0 && !MCStringGetNumericValue((MCStringRef)p_value, t_number))
146146
{
147-
if (!MCU_stor8((MCStringRef)p_value, t_number, m_convertoctals))
147+
if (!MCTypeConvertStringToReal((MCStringRef)p_value, t_number, m_convertoctals))
148148
break;
149149

150150
// Converting to octals doesn't generate the 10-based number stored in the string
@@ -1401,7 +1401,7 @@ static bool MCPropertyParseDoubleList(MCStringRef p_input, char_t p_delimiter, u
14011401
t_success = MCStringCopySubstring(p_input, MCRangeMake(t_old_offset, t_new_offset - t_old_offset), &t_double_string);
14021402

14031403
if (t_success)
1404-
t_success = MCU_stor8(*t_double_string, t_d);
1404+
t_success = MCTypeConvertStringToReal(*t_double_string, t_d);
14051405

14061406
if (t_success)
14071407
t_success = t_list . Push(t_d);

libfoundation/include/foundation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,5 +2418,12 @@ bool MCPickleRead(MCStreamRef stream, MCPickleRecordInfo *info, MCValueRef*& r_v
24182418
bool MCPickleWrite(MCStreamRef stream, MCPickleRecordInfo *info, MCValueRef *value_pool, uindex_t value_pool_size, void* record);
24192419

24202420
////////////////////////////////////////////////////////////////////////////////
2421+
//
2422+
// TYPE CONVERSION
2423+
//
2424+
2425+
bool MCTypeConvertStringToLongInteger(MCStringRef p_string, integer_t& r_converted);
2426+
bool MCTypeConvertStringToReal(MCStringRef p_string, real64_t& r_converted, bool p_convert_octals = false);
2427+
bool MCTypeConvertStringToBool(MCStringRef p_string, bool& r_converted);
24212428

24222429
#endif
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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

Comments
 (0)