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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 #endif | 191 #endif |
192 | 192 |
193 DEFINE_NATIVE_ENTRY(Double_toInt, 1) { | 193 DEFINE_NATIVE_ENTRY(Double_toInt, 1) { |
194 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 194 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
195 return DoubleToInteger(arg.value(), "Infinity or NaN toInt"); | 195 return DoubleToInteger(arg.value(), "Infinity or NaN toInt"); |
196 } | 196 } |
197 | 197 |
198 | 198 |
199 DEFINE_NATIVE_ENTRY(Double_parse, 1) { | 199 DEFINE_NATIVE_ENTRY(Double_parse, 1) { |
200 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); | 200 GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0)); |
201 if (value.IsOneByteString()) { | |
202 // Quick conversion for unpadded doubles in strings. | |
203 const intptr_t len = value.Length(); | |
204 if (len > 0) { | |
205 const char* cstr = value.ToCString(); | |
206 ASSERT(cstr != NULL); | |
207 // Dart differences from strtod: | |
208 // a) '5.' is not a valid double (no digit after period). | |
209 // b) '+5.0' is not a valid double (leading plus). | |
210 if (cstr[0] != '+') { | |
211 bool dot_ok = true; | |
212 const char* tmp = cstr; | |
213 while (*tmp != '\0') { | |
214 const char ch = *tmp++; | |
215 if (ch == '.') { | |
216 const char nextCh = *tmp; | |
217 dot_ok = ('0' <= nextCh) && (nextCh <= '9'); | |
218 break; | |
219 } | |
220 } | |
221 if (dot_ok) { | |
222 double double_value; | |
223 if (CStringToDouble(cstr, len, &double_value)) { | |
224 return Double::New(double_value); | |
225 } | |
226 } | |
227 } | |
228 } | |
229 } | |
230 Scanner scanner(value, Symbols::Empty()); | |
231 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | |
232 String* number_string; | |
233 bool is_positive; | |
234 if (Scanner::IsValidLiteral(tokens, | |
235 Token::kDOUBLE, | |
236 &is_positive, | |
237 &number_string)) { | |
238 // Even if original string was two byte string the scanner should produce | |
239 // literal value that is represented as a one byte string because all | |
240 // characters in the double literal are Latin-1. | |
241 ASSERT(number_string->IsOneByteString()); | |
242 const char* cstr = number_string->ToCString(); | |
243 | 201 |
244 double double_value; | 202 const intptr_t len = value.Length(); |
245 bool ok = CStringToDouble(cstr, number_string->Length(), &double_value); | |
246 ASSERT(ok); | |
247 | 203 |
248 if (!is_positive) { | 204 // The native function only accepts one-byte strings. The Dart side converts |
249 double_value = -double_value; | 205 // other types of strings to one-byte strings, if necessary. |
250 } | 206 if ((!value.IsOneByteString() && !value.IsExternalOneByteString()) |
251 return Double::New(double_value); | 207 || (len == 0)) { |
| 208 return Object::null(); |
252 } | 209 } |
253 | 210 |
254 if (Scanner::IsValidLiteral(tokens, | 211 double double_value; |
255 Token::kINTEGER, | 212 const char* cstr = value.ToCString(); |
256 &is_positive, | 213 ASSERT(cstr != NULL); |
257 &number_string)) { | 214 if (CStringToDouble(cstr, len, &double_value)) { |
258 Integer& res = Integer::Handle(Integer::New(*number_string)); | 215 return Double::New(double_value); |
259 if (is_positive) { | 216 } else { |
260 return Double::New(res.AsDoubleValue()); | 217 return Object::null(); |
261 } | |
262 return Double::New(-res.AsDoubleValue()); | |
263 } | 218 } |
264 | |
265 // Infinity and nan. | |
266 if (Scanner::IsValidLiteral(tokens, | |
267 Token::kIDENT, | |
268 &is_positive, | |
269 &number_string)) { | |
270 if (number_string->Equals("NaN")) { | |
271 return Double::New(NAN); | |
272 } | |
273 if (number_string->Equals("Infinity")) { | |
274 if (is_positive) { | |
275 return Double::New(INFINITY); | |
276 } | |
277 return Double::New(-INFINITY); | |
278 } | |
279 } | |
280 | |
281 const Array& args = Array::Handle(Array::New(1)); | |
282 args.SetAt(0, value); | |
283 Exceptions::ThrowByType(Exceptions::kFormat, args); | |
284 return Object::null(); | |
285 } | 219 } |
286 | 220 |
287 | 221 |
288 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { | 222 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { |
289 // The boundaries are exclusive. | 223 // The boundaries are exclusive. |
290 static const double kLowerBoundary = -1e21; | 224 static const double kLowerBoundary = -1e21; |
291 static const double kUpperBoundary = 1e21; | 225 static const double kUpperBoundary = 1e21; |
292 | 226 |
293 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 227 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
294 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); | 228 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 | 290 |
357 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { | 291 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { |
358 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 292 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
359 // Include negative zero, infinity. | 293 // Include negative zero, infinity. |
360 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); | 294 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); |
361 } | 295 } |
362 | 296 |
363 // Add here only functions using/referring to old-style casts. | 297 // Add here only functions using/referring to old-style casts. |
364 | 298 |
365 } // namespace dart | 299 } // namespace dart |
OLD | NEW |