OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <math.h> | 5 #include <math.h> |
6 | 6 |
7 #include "vm/bootstrap_natives.h" | 7 #include "vm/bootstrap_natives.h" |
8 | 8 |
9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
10 #include "vm/code_generator.h" // DartModulo. | 10 #include "vm/code_generator.h" // DartModulo. |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 #endif | 193 #endif |
194 | 194 |
195 DEFINE_NATIVE_ENTRY(Double_toInt, 1) { | 195 DEFINE_NATIVE_ENTRY(Double_toInt, 1) { |
196 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 196 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
197 return DoubleToInteger(arg.value(), "Infinity or NaN toInt"); | 197 return DoubleToInteger(arg.value(), "Infinity or NaN toInt"); |
198 } | 198 } |
199 | 199 |
200 | 200 |
201 DEFINE_NATIVE_ENTRY(Double_parse, 1) { | 201 DEFINE_NATIVE_ENTRY(Double_parse, 1) { |
202 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); | 202 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); |
203 if (value.IsOneByteString()) { | |
204 // Quick conversion for unpadded doubles in strings. | |
205 const intptr_t len = value.Length(); | |
206 if (len > 0) { | |
207 const char* cstr = value.ToCString(); | |
208 ASSERT(cstr != NULL); | |
209 // Dart differences from strtod: | |
210 // a) '5.' is not a valid double (no digit after period). | |
211 // b) '+5.0' is not a valid double (leading plus). | |
212 if (cstr[0] != '+') { | |
213 bool dot_ok = true; | |
214 const char* tmp = cstr; | |
215 while (*tmp != '\0') { | |
216 const char ch = *tmp++; | |
217 if (ch == '.') { | |
218 const char nextCh = *tmp; | |
219 dot_ok = ('0' <= nextCh) && (nextCh <= '9'); | |
220 break; | |
221 } | |
222 } | |
223 if (dot_ok) { | |
224 double double_value; | |
225 if (CStringToDouble(cstr, len, &double_value)) { | |
226 return Double::New(double_value); | |
227 } | |
228 } | |
229 } | |
230 } | |
231 } | |
232 Scanner scanner(value, Symbols::Empty()); | |
233 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | |
234 String* number_string; | |
235 bool is_positive; | |
236 if (Scanner::IsValidLiteral(tokens, | |
237 Token::kDOUBLE, | |
238 &is_positive, | |
239 &number_string)) { | |
240 // Even if original string was two byte string the scanner should produce | |
241 // literal value that is represented as a one byte string because all | |
242 // characters in the double literal are Latin-1. | |
243 ASSERT(number_string->IsOneByteString()); | |
244 const char* cstr = number_string->ToCString(); | |
245 | 203 |
246 double double_value; | 204 const intptr_t len = value.Length(); |
247 bool ok = CStringToDouble(cstr, number_string->Length(), &double_value); | |
248 ASSERT(ok); | |
249 | 205 |
250 if (!is_positive) { | 206 if (!value.IsOneByteString() || len == 0) { |
Ivan Posva
2013/05/18 00:45:43
What about an external one byte string? Or an exte
floitsch
2013/05/20 13:15:29
They would have been converted to OneByteStrings i
Ivan Posva
2013/05/20 16:00:23
A comment to that effect would be great.
On a sep
floitsch
2013/05/21 14:39:31
Done.
| |
251 double_value = -double_value; | 207 return Object::null(); |
252 } | |
253 return Double::New(double_value); | |
254 } | 208 } |
255 | 209 |
256 if (Scanner::IsValidLiteral(tokens, | 210 double double_value; |
257 Token::kINTEGER, | 211 const char* cstr = value.ToCString(); |
258 &is_positive, | 212 ASSERT(cstr != NULL); |
259 &number_string)) { | 213 if (CStringToDouble(cstr, len, &double_value)) { |
260 Integer& res = Integer::Handle(Integer::New(*number_string)); | 214 return Double::New(double_value); |
261 if (is_positive) { | 215 } else { |
262 return Double::New(res.AsDoubleValue()); | 216 return Object::null(); |
263 } | |
264 return Double::New(-res.AsDoubleValue()); | |
265 } | 217 } |
266 | |
267 // Infinity and nan. | |
268 if (Scanner::IsValidLiteral(tokens, | |
269 Token::kIDENT, | |
270 &is_positive, | |
271 &number_string)) { | |
272 if (number_string->Equals("NaN")) { | |
273 return Double::New(NAN); | |
274 } | |
275 if (number_string->Equals("Infinity")) { | |
276 if (is_positive) { | |
277 return Double::New(INFINITY); | |
278 } | |
279 return Double::New(-INFINITY); | |
280 } | |
281 } | |
282 | |
283 const Array& args = Array::Handle(Array::New(1)); | |
284 args.SetAt(0, value); | |
285 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
286 return Object::null(); | |
287 } | 218 } |
288 | 219 |
289 | 220 |
290 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { | 221 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { |
291 // The boundaries are exclusive. | 222 // The boundaries are exclusive. |
292 static const double kLowerBoundary = -1e21; | 223 static const double kLowerBoundary = -1e21; |
293 static const double kUpperBoundary = 1e21; | 224 static const double kUpperBoundary = 1e21; |
294 | 225 |
295 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 226 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
296 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); | 227 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 | 289 |
359 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { | 290 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { |
360 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 291 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
361 // Include negative zero, infinity. | 292 // Include negative zero, infinity. |
362 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); | 293 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); |
363 } | 294 } |
364 | 295 |
365 // Add here only functions using/referring to old-style casts. | 296 // Add here only functions using/referring to old-style casts. |
366 | 297 |
367 } // namespace dart | 298 } // namespace dart |
OLD | NEW |