efada887e44524b0f39340c3166c86438917382f
[platform/framework/web/crosswalk-tizen.git] /
1 'use strict';
2
3 var common = require('../common');
4 var Type   = require('../type');
5
6 function isHexCode(c) {
7   return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
8          ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
9          ((0x61/* a */ <= c) && (c <= 0x66/* f */));
10 }
11
12 function isOctCode(c) {
13   return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
14 }
15
16 function isDecCode(c) {
17   return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
18 }
19
20 function resolveYamlInteger(data) {
21   if (null === data) {
22     return false;
23   }
24
25   var max = data.length,
26       index = 0,
27       hasDigits = false,
28       ch;
29
30   if (!max) { return false; }
31
32   ch = data[index];
33
34   // sign
35   if (ch === '-' || ch === '+') {
36     ch = data[++index];
37   }
38
39   if (ch === '0') {
40     // 0
41     if (index+1 === max) { return true; }
42     ch = data[++index];
43
44     // base 2, base 8, base 16
45
46     if (ch === 'b') {
47       // base 2
48       index++;
49
50       for (; index < max; index++) {
51         ch = data[index];
52         if (ch === '_') { continue; }
53         if (ch !== '0' && ch !== '1') {
54           return false;
55         }
56         hasDigits = true;
57       }
58       return hasDigits;
59     }
60
61
62     if (ch === 'x') {
63       // base 16
64       index++;
65
66       for (; index < max; index++) {
67         ch = data[index];
68         if (ch === '_') { continue; }
69         if (!isHexCode(data.charCodeAt(index))) {
70           return false;
71         }
72         hasDigits = true;
73       }
74       return hasDigits;
75     }
76
77     // base 8
78     for (; index < max; index++) {
79       ch = data[index];
80       if (ch === '_') { continue; }
81       if (!isOctCode(data.charCodeAt(index))) {
82         return false;
83       }
84       hasDigits = true;
85     }
86     return hasDigits;
87   }
88
89   // base 10 (except 0) or base 60
90
91   for (; index < max; index++) {
92     ch = data[index];
93     if (ch === '_') { continue; }
94     if (ch === ':') { break; }
95     if (!isDecCode(data.charCodeAt(index))) {
96       return false;
97     }
98     hasDigits = true;
99   }
100
101   if (!hasDigits) { return false; }
102
103   // if !base60 - done;
104   if (ch !== ':') { return true; }
105
106   // base60 almost not used, no needs to optimize
107   return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
108 }
109
110 function constructYamlInteger(data) {
111   var value = data, sign = 1, ch, base, digits = [];
112
113   if (value.indexOf('_') !== -1) {
114     value = value.replace(/_/g, '');
115   }
116
117   ch = value[0];
118
119   if (ch === '-' || ch === '+') {
120     if (ch === '-') { sign = -1; }
121     value = value.slice(1);
122     ch = value[0];
123   }
124
125   if ('0' === value) {
126     return 0;
127   }
128
129   if (ch === '0') {
130     if (value[1] === 'b') {
131       return sign * parseInt(value.slice(2), 2);
132     }
133     if (value[1] === 'x') {
134       return sign * parseInt(value, 16);
135     }
136     return sign * parseInt(value, 8);
137
138   }
139
140   if (value.indexOf(':') !== -1) {
141     value.split(':').forEach(function (v) {
142       digits.unshift(parseInt(v, 10));
143     });
144
145     value = 0;
146     base = 1;
147
148     digits.forEach(function (d) {
149       value += (d * base);
150       base *= 60;
151     });
152
153     return sign * value;
154
155   }
156
157   return sign * parseInt(value, 10);
158 }
159
160 function isInteger(object) {
161   return ('[object Number]' === Object.prototype.toString.call(object)) &&
162          (0 === object % 1 && !common.isNegativeZero(object));
163 }
164
165 module.exports = new Type('tag:yaml.org,2002:int', {
166   kind: 'scalar',
167   resolve: resolveYamlInteger,
168   construct: constructYamlInteger,
169   predicate: isInteger,
170   represent: {
171     binary:      function (object) { return '0b' + object.toString(2); },
172     octal:       function (object) { return '0'  + object.toString(8); },
173     decimal:     function (object) { return        object.toString(10); },
174     hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); }
175   },
176   defaultStyle: 'decimal',
177   styleAliases: {
178     binary:      [ 2,  'bin' ],
179     octal:       [ 8,  'oct' ],
180     decimal:     [ 10, 'dec' ],
181     hexadecimal: [ 16, 'hex' ]
182   }
183 });