1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code, released
17 : * March 31, 1998.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * the Mozilla Foundation.
21 : * Portions created by the Initial Developer are Copyright (C) 2011
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef jsnuminlines_h___
41 : #define jsnuminlines_h___
42 :
43 : #include "vm/Unicode.h"
44 :
45 : #include "jsstrinlines.h"
46 :
47 :
48 : namespace js {
49 :
50 : template<typename T> struct NumberTraits { };
51 : template<> struct NumberTraits<int32_t> {
52 0 : static JS_ALWAYS_INLINE int32_t NaN() { return 0; }
53 0 : static JS_ALWAYS_INLINE int32_t toSelfType(int32_t i) { return i; }
54 0 : static JS_ALWAYS_INLINE int32_t toSelfType(double d) { return js_DoubleToECMAUint32(d); }
55 : };
56 : template<> struct NumberTraits<double> {
57 300366 : static JS_ALWAYS_INLINE double NaN() { return js_NaN; }
58 : static JS_ALWAYS_INLINE double toSelfType(int32_t i) { return i; }
59 412290 : static JS_ALWAYS_INLINE double toSelfType(double d) { return d; }
60 : };
61 :
62 : template<typename T>
63 : static JS_ALWAYS_INLINE bool
64 712656 : StringToNumberType(JSContext *cx, JSString *str, T *result)
65 : {
66 712656 : size_t length = str->length();
67 712656 : const jschar *chars = str->getChars(NULL);
68 712656 : if (!chars)
69 0 : return false;
70 :
71 712656 : if (length == 1) {
72 100507 : jschar c = chars[0];
73 100507 : if ('0' <= c && c <= '9') {
74 73841 : *result = NumberTraits<T>::toSelfType(T(c - '0'));
75 73841 : return true;
76 : }
77 26666 : if (unicode::IsSpace(c)) {
78 27 : *result = NumberTraits<T>::toSelfType(T(0));
79 27 : return true;
80 : }
81 26639 : *result = NumberTraits<T>::NaN();
82 26639 : return true;
83 : }
84 :
85 612149 : const jschar *end = chars + length;
86 612149 : const jschar *bp = SkipSpace(chars, end);
87 :
88 : /* ECMA doesn't allow signed hex numbers (bug 273467). */
89 612149 : if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) {
90 : /* Looks like a hex number. */
91 : const jschar *endptr;
92 : double d;
93 189 : if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) || SkipSpace(endptr, end) != end) {
94 0 : *result = NumberTraits<T>::NaN();
95 0 : return true;
96 : }
97 189 : *result = NumberTraits<T>::toSelfType(d);
98 189 : return true;
99 : }
100 :
101 : /*
102 : * Note that ECMA doesn't treat a string beginning with a '0' as
103 : * an octal number here. This works because all such numbers will
104 : * be interpreted as decimal by js_strtod. Also, any hex numbers
105 : * that have made it here (which can only be negative ones) will
106 : * be treated as 0 without consuming the 'x' by js_strtod.
107 : */
108 : const jschar *ep;
109 : double d;
110 611960 : if (!js_strtod(cx, bp, end, &ep, &d) || SkipSpace(ep, end) != end) {
111 273727 : *result = NumberTraits<T>::NaN();
112 273727 : return true;
113 : }
114 338233 : *result = NumberTraits<T>::toSelfType(d);
115 338233 : return true;
116 : }
117 :
118 : } // namespace js
119 :
120 : #endif /* jsnuminlines_h___ */
|