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(); |
201 | 243 |
202 const intptr_t len = value.Length(); | 244 double double_value; |
| 245 bool ok = CStringToDouble(cstr, number_string->Length(), &double_value); |
| 246 ASSERT(ok); |
203 | 247 |
204 // The native function only accepts one-byte strings. The Dart side converts | 248 if (!is_positive) { |
205 // other types of strings to one-byte strings, if necessary. | 249 double_value = -double_value; |
206 if ((!value.IsOneByteString() && !value.IsExternalOneByteString()) | 250 } |
207 || (len == 0)) { | 251 return Double::New(double_value); |
208 return Object::null(); | |
209 } | 252 } |
210 | 253 |
211 double double_value; | 254 if (Scanner::IsValidLiteral(tokens, |
212 const char* cstr = value.ToCString(); | 255 Token::kINTEGER, |
213 ASSERT(cstr != NULL); | 256 &is_positive, |
214 if (CStringToDouble(cstr, len, &double_value)) { | 257 &number_string)) { |
215 return Double::New(double_value); | 258 Integer& res = Integer::Handle(Integer::New(*number_string)); |
216 } else { | 259 if (is_positive) { |
217 return Object::null(); | 260 return Double::New(res.AsDoubleValue()); |
| 261 } |
| 262 return Double::New(-res.AsDoubleValue()); |
218 } | 263 } |
| 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(); |
219 } | 285 } |
220 | 286 |
221 | 287 |
222 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { | 288 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) { |
223 // The boundaries are exclusive. | 289 // The boundaries are exclusive. |
224 static const double kLowerBoundary = -1e21; | 290 static const double kLowerBoundary = -1e21; |
225 static const double kUpperBoundary = 1e21; | 291 static const double kUpperBoundary = 1e21; |
226 | 292 |
227 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 293 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
228 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); | 294 GET_NON_NULL_NATIVE_ARGUMENT(Smi, fraction_digits, arguments->NativeArgAt(1)); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 | 356 |
291 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { | 357 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 1) { |
292 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); | 358 const Double& arg = Double::CheckedHandle(arguments->NativeArgAt(0)); |
293 // Include negative zero, infinity. | 359 // Include negative zero, infinity. |
294 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); | 360 return Bool::Get(signbit(arg.value()) && !isnan(arg.value())); |
295 } | 361 } |
296 | 362 |
297 // Add here only functions using/referring to old-style casts. | 363 // Add here only functions using/referring to old-style casts. |
298 | 364 |
299 } // namespace dart | 365 } // namespace dart |
OLD | NEW |