iv-phonic 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,6 +21,8 @@ class Conversions {
21
21
  static const std::string kInfinity;
22
22
  static const double DoubleToInt32_Two32;
23
23
  static const double DoubleToInt32_Two31;
24
+ static const char* kHex;
25
+ static const int kMaxDoubleToStringWithRadixBufferSize = 2200;
24
26
  };
25
27
  template<typename T>
26
28
  const double Conversions<T>::kNaN = std::numeric_limits<double>::quiet_NaN();
@@ -33,14 +35,19 @@ const double Conversions<T>::DoubleToInt32_Two32 = 4294967296.0;
33
35
 
34
36
  template<typename T>
35
37
  const double Conversions<T>::DoubleToInt32_Two31 = 2147483648.0;
38
+
39
+ template<typename T>
40
+ const char* Conversions<T>::kHex = "0123456789abcdefghijklmnopqrstuvwxyz";
41
+
36
42
  } // namespace iv::core::detail
37
43
 
38
44
  typedef detail::Conversions<None> Conversions;
39
45
 
40
46
  template<typename Iter>
41
- inline double StringToDouble(Iter it, Iter last) {
47
+ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
42
48
  bool is_decimal = true;
43
49
  bool is_signed = false;
50
+ bool is_sign_found = false;
44
51
  std::size_t pos = 0;
45
52
  int significant_digits = 0;
46
53
  int insignificant_digits = 0;
@@ -48,7 +55,7 @@ inline double StringToDouble(Iter it, Iter last) {
48
55
 
49
56
  // empty string ""
50
57
  if (it == last) {
51
- return 0;
58
+ return (parse_float) ? Conversions::kNaN : 0;
52
59
  }
53
60
 
54
61
  while (it != last &&
@@ -58,15 +65,17 @@ inline double StringToDouble(Iter it, Iter last) {
58
65
 
59
66
  // white space only " "
60
67
  if (it == last) {
61
- return 0;
68
+ return (parse_float) ? Conversions::kNaN : 0;
62
69
  }
63
70
 
64
71
  if (*it == '-') {
65
72
  buffer[pos++] = '-';
66
73
  ++it;
67
74
  is_signed = true;
75
+ is_sign_found = true;
68
76
  } else if (*it == '+') {
69
77
  ++it;
78
+ is_sign_found = true;
70
79
  }
71
80
 
72
81
  if (it == last) {
@@ -79,7 +88,10 @@ inline double StringToDouble(Iter it, Iter last) {
79
88
  if (it == last) {
80
89
  return 0;
81
90
  }
82
- if (*it == 'x' || *it == 'X') {
91
+ if (!parse_float && (*it == 'x' || *it == 'X')) {
92
+ if (is_sign_found) {
93
+ return Conversions::kNaN;
94
+ }
83
95
  is_decimal = false;
84
96
  buffer[pos++] = '0';
85
97
  buffer[pos++] = *it;
@@ -158,7 +170,7 @@ inline double StringToDouble(Iter it, Iter last) {
158
170
  (Chars::IsWhiteSpace(*it) || Chars::IsLineTerminator(*it))) {
159
171
  ++it;
160
172
  }
161
- if (it == last) {
173
+ if (it == last || parse_float) {
162
174
  if (is_signed) {
163
175
  return -std::numeric_limits<double>::infinity();
164
176
  } else {
@@ -213,10 +225,10 @@ inline double StringToDouble(Iter it, Iter last) {
213
225
  ++it;
214
226
  }
215
227
 
216
- if (it == last) {
228
+ if (it == last || parse_float) {
217
229
  if (pos == 0) {
218
230
  // empty
219
- return 0;
231
+ return (parse_float) ? Conversions::kNaN : 0;
220
232
  } else {
221
233
  buffer[pos++] = '\0';
222
234
  return std::strtod(buffer.data(), NULL);
@@ -226,12 +238,12 @@ inline double StringToDouble(Iter it, Iter last) {
226
238
  }
227
239
  }
228
240
 
229
- inline double StringToDouble(const StringPiece& str) {
230
- return StringToDouble(str.begin(), str.end());
241
+ inline double StringToDouble(const StringPiece& str, bool parse_float) {
242
+ return StringToDouble(str.begin(), str.end(), parse_float);
231
243
  }
232
244
 
233
- inline double StringToDouble(const UStringPiece& str) {
234
- return StringToDouble(str.begin(), str.end());
245
+ inline double StringToDouble(const UStringPiece& str, bool parse_float) {
246
+ return StringToDouble(str.begin(), str.end(), parse_float);
235
247
  }
236
248
 
237
249
  inline std::size_t StringToHash(const UStringPiece& x) {
@@ -276,6 +288,16 @@ inline int32_t DoubleToUInt32(double d) {
276
288
  return static_cast<uint32_t>(d);
277
289
  }
278
290
 
291
+ inline double DoubleToInteger(double d) {
292
+ if (std::isnan(d)) {
293
+ return 0;
294
+ }
295
+ if (!std::isfinite(d) || d == 0) {
296
+ return d;
297
+ }
298
+ return std::floor(std::abs(d)) * (std::signbit(d) ? -1 : 1);
299
+ }
300
+
279
301
  inline bool ConvertToUInt32(const UStringPiece& str, uint32_t* value) {
280
302
  uint16_t ch;
281
303
  *value = 0;
@@ -303,6 +325,52 @@ inline bool ConvertToUInt32(const UStringPiece& str, uint32_t* value) {
303
325
  (ch < (std::numeric_limits<uint32_t>::max() % 10))));
304
326
  }
305
327
 
328
+ template<typename T>
329
+ inline std::size_t DoubleToStringWithRadix(double v, int radix, T* buf) {
330
+ static const int kMaxBufSize = 1100;
331
+ std::tr1::array<
332
+ char,
333
+ Conversions::kMaxDoubleToStringWithRadixBufferSize> buffer;
334
+ const bool is_negative = v < 0.0;
335
+ if (is_negative) {
336
+ v = -v;
337
+ }
338
+ double integer = std::floor(v);
339
+ double decimal = v - integer;
340
+
341
+ // integer part
342
+ int integer_pos = kMaxBufSize - 1;
343
+ do {
344
+ buffer[integer_pos--] =
345
+ Conversions::kHex[static_cast<std::size_t>(std::fmod(integer, radix))];
346
+ integer /= radix;
347
+ } while (integer >= 1.0);
348
+ if (is_negative) {
349
+ buffer[integer_pos--] = '-';
350
+ }
351
+ assert(integer_pos >= 0);
352
+
353
+ // decimal part
354
+ int decimal_pos = kMaxBufSize;
355
+ if (decimal) {
356
+ buffer[decimal_pos++] = '.';
357
+ while ((decimal > 0.0) && (decimal_pos < (kMaxBufSize * 2))) {
358
+ decimal *= radix;
359
+ const std::size_t res = static_cast<std::size_t>(std::floor(decimal));
360
+ buffer[decimal_pos++] = Conversions::kHex[res];
361
+ decimal -= res;
362
+ }
363
+ }
364
+ buf->assign(buffer.data() + integer_pos + 1,
365
+ buffer.data() + decimal_pos);
366
+ return decimal_pos - integer_pos - 1; // size
367
+ }
368
+
369
+ inline std::string DoubleToStringWithRadix(double v, int radix) {
370
+ std::string str;
371
+ DoubleToStringWithRadix(v, radix, &str);
372
+ return str;
373
+ }
306
374
 
307
375
  } } // namespace iv::core
308
376
  #endif // IV_CONVERSIONS_H_
@@ -0,0 +1,460 @@
1
+ #ifndef _IV_KEYWORD_H_
2
+ #define _IV_KEYWORD_H_
3
+ #include <cstddef>
4
+ #include "token.h"
5
+ namespace iv {
6
+ namespace core {
7
+
8
+ // tags
9
+ class IdentifyReservedWords { };
10
+ class IgnoreReservedWords { };
11
+ class IgnoreReservedWordsAndIdentifyGetterOrSetter { };
12
+
13
+ namespace detail {
14
+ template<typename LexType>
15
+ class Keyword { };
16
+
17
+ // detect which Identifier is Keyword, FutureReservedWord or not
18
+ // Keyword and FutureReservedWord are defined in ECMA-262 5th.
19
+ //
20
+ // Some words such as :
21
+ // int, short, boolean, byte, long, char, float, double, abstract, volatile,
22
+ // transient, final, throws, goto, native, synchronized
23
+ // were defined as FutureReservedWord in ECMA-262 3rd, but not in 5th.
24
+ // So, Detect interprets them as Identifier.
25
+ template<>
26
+ class Keyword<IdentifyReservedWords> {
27
+ public:
28
+ template<typename Buffer>
29
+ static Token::Type Detect(const Buffer& buf, bool strict) {
30
+ const std::size_t len = buf.size();
31
+ Token::Type token = Token::IDENTIFIER;
32
+ switch (len) {
33
+ case 2:
34
+ // if in do
35
+ if (buf[0] == 'i') {
36
+ if (buf[1] == 'f') {
37
+ token = Token::IF;
38
+ } else if (buf[1] == 'n') {
39
+ token = Token::IN;
40
+ }
41
+ } else if (buf[0] == 'd' && buf[1] == 'o') {
42
+ // do
43
+ token = Token::DO;
44
+ }
45
+ break;
46
+ case 3:
47
+ // for var int new try let
48
+ switch (buf[2]) {
49
+ case 't':
50
+ if (buf[0] == 'l' && buf[1] == 'e' && strict) {
51
+ // let
52
+ token = Token::LET;
53
+ } else if (buf[0] == 'i' && buf[1] == 'n') {
54
+ // int (removed)
55
+ // token = Token::INT;
56
+ }
57
+ break;
58
+ case 'r':
59
+ // for var
60
+ if (buf[0] == 'f' && buf[1] == 'o') {
61
+ // for
62
+ token = Token::FOR;
63
+ } else if (buf[0] == 'v' && buf[1] == 'a') {
64
+ // var
65
+ token = Token::VAR;
66
+ }
67
+ break;
68
+ case 'y':
69
+ // try
70
+ if (buf[0] == 't' && buf[1] == 'r') {
71
+ token = Token::TRY;
72
+ }
73
+ break;
74
+ case 'w':
75
+ // new
76
+ if (buf[0] == 'n' && buf[1] == 'e') {
77
+ token = Token::NEW;
78
+ }
79
+ break;
80
+ }
81
+ break;
82
+ case 4:
83
+ // else case true byte null this
84
+ // void with long enum char goto
85
+ // number 3 character is most duplicated
86
+ switch (buf[3]) {
87
+ case 'e':
88
+ // else case true byte
89
+ if (buf[2] == 's') {
90
+ if (buf[0] == 'e' && buf[1] == 'l') {
91
+ // else
92
+ token = Token::ELSE;
93
+ } else if (buf[0] == 'c' && buf[1] == 'a') {
94
+ // case
95
+ token = Token::CASE;
96
+ }
97
+ } else if (buf[0] == 't' &&
98
+ buf[1] == 'r' && buf[2] == 'u') {
99
+ // true
100
+ token = Token::TRUE_LITERAL;
101
+ } else if (buf[0] == 'b' &&
102
+ buf[1] == 'y' && buf[2] == 't') {
103
+ // byte (removed)
104
+ // token = Token::BYTE;
105
+ }
106
+ break;
107
+ case 'l':
108
+ // null
109
+ if (buf[0] == 'n' &&
110
+ buf[1] == 'u' && buf[2] == 'l') {
111
+ token = Token::NULL_LITERAL;
112
+ }
113
+ break;
114
+ case 's':
115
+ // this
116
+ if (buf[0] == 't' &&
117
+ buf[1] == 'h' && buf[2] == 'i') {
118
+ token = Token::THIS;
119
+ }
120
+ break;
121
+ case 'd':
122
+ // void
123
+ if (buf[0] == 'v' &&
124
+ buf[1] == 'o' && buf[2] == 'i') {
125
+ token = Token::VOID;
126
+ }
127
+ break;
128
+ case 'h':
129
+ // with
130
+ if (buf[0] == 'w' &&
131
+ buf[1] == 'i' && buf[2] == 't') {
132
+ token = Token::WITH;
133
+ }
134
+ break;
135
+ case 'g':
136
+ // long (removed)
137
+ if (buf[0] == 'l' &&
138
+ buf[1] == 'o' && buf[2] == 'n') {
139
+ // token = Token::LONG;
140
+ }
141
+ break;
142
+ case 'm':
143
+ // enum
144
+ if (buf[0] == 'e' &&
145
+ buf[1] == 'n' && buf[2] == 'u') {
146
+ token = Token::ENUM;
147
+ }
148
+ break;
149
+ case 'r':
150
+ // char (removed)
151
+ if (buf[0] == 'c' &&
152
+ buf[1] == 'h' && buf[2] == 'a') {
153
+ // token = Token::CHAR;
154
+ }
155
+ break;
156
+ case 'o':
157
+ // goto (removed)
158
+ if (buf[0] == 'g' &&
159
+ buf[1] == 'o' && buf[2] == 't') {
160
+ // token = Token::GOTO;
161
+ }
162
+ break;
163
+ }
164
+ break;
165
+ case 5:
166
+ // break final float catch super while
167
+ // throw short class const false yield
168
+ // number 3 character is most duplicated
169
+ switch (buf[3]) {
170
+ case 'a':
171
+ // break final float
172
+ if (buf[0] == 'b' && buf[1] == 'r' &&
173
+ buf[2] == 'e' && buf[4] == 'k') {
174
+ // break
175
+ token = Token::BREAK;
176
+ } else if (buf[0] == 'f') {
177
+ if (buf[1] == 'i' &&
178
+ buf[2] == 'n' && buf[4] == 'l') {
179
+ // final (removed)
180
+ // token = Token::FINAL;
181
+ } else if (buf[1] == 'l' &&
182
+ buf[2] == 'o' && buf[4] == 't') {
183
+ // float (removed)
184
+ // token = Token::FLOAT;
185
+ }
186
+ }
187
+ break;
188
+ case 'c':
189
+ if (buf[0] == 'c' && buf[1] == 'a' &&
190
+ buf[2] == 't' && buf[4] == 'h') {
191
+ // catch
192
+ token = Token::CATCH;
193
+ }
194
+ break;
195
+ case 'e':
196
+ if (buf[0] == 's' && buf[1] == 'u' &&
197
+ buf[2] == 'p' && buf[4] == 'r') {
198
+ // super
199
+ token = Token::SUPER;
200
+ }
201
+ break;
202
+ case 'l':
203
+ if (buf[0] == 'w' && buf[1] == 'h' &&
204
+ buf[2] == 'i' && buf[4] == 'e') {
205
+ // while
206
+ token = Token::WHILE;
207
+ } else if (strict &&
208
+ buf[0] == 'y' && buf[1] == 'i' &&
209
+ buf[2] == 'e' && buf[4] == 'd') {
210
+ // yield
211
+ token = Token::YIELD;
212
+ }
213
+ break;
214
+ case 'o':
215
+ if (buf[0] == 't' && buf[1] == 'h' &&
216
+ buf[2] == 'r' && buf[4] == 'w') {
217
+ // throw
218
+ token = Token::THROW;
219
+ }
220
+ break;
221
+ case 'r':
222
+ if (buf[0] == 's' && buf[1] == 'h' &&
223
+ buf[2] == 'o' && buf[4] == 't') {
224
+ // short (removed)
225
+ // token = Token::SHORT;
226
+ }
227
+ break;
228
+ case 's':
229
+ // class const false
230
+ if (buf[0] == 'c') {
231
+ if (buf[1] == 'l' &&
232
+ buf[2] == 'a' && buf[4] == 's') {
233
+ // class
234
+ token = Token::CLASS;
235
+ } else if (buf[1] == 'o' &&
236
+ buf[2] == 'n' && buf[4] == 't') {
237
+ // const
238
+ token = Token::CONST;
239
+ }
240
+ } else if (buf[0] == 'f' && buf[1] == 'a' &&
241
+ buf[2] == 'l' && buf[4] == 'e') {
242
+ // false
243
+ token = Token::FALSE_LITERAL;
244
+ }
245
+ break;
246
+ }
247
+ break;
248
+ case 6:
249
+ // double delete export import native
250
+ // public return static switch typeof throws
251
+ // number 0 character is most duplicated
252
+ switch (buf[0]) {
253
+ case 'd':
254
+ // double delete
255
+ if (buf[5] == 'e' &&
256
+ buf[4] == 'l' && buf[3] == 'b' &&
257
+ buf[2] == 'u' && buf[1] == 'o') {
258
+ // double
259
+ // token = Token::DOUBLE;
260
+ } else if (buf[5] == 'e' &&
261
+ buf[4] == 't' && buf[3] == 'e' &&
262
+ buf[2] == 'l' && buf[1] == 'e') {
263
+ // delete
264
+ token = Token::DELETE;
265
+ }
266
+ break;
267
+ case 'e':
268
+ // export
269
+ token = IsMatch("export", buf, Token::EXPORT);
270
+ break;
271
+ case 'i':
272
+ // import
273
+ token = IsMatch("import", buf, Token::IMPORT);
274
+ break;
275
+ case 'n':
276
+ // native (removed)
277
+ // token = IsMatch("native", buf, Token::NATIVE);
278
+ break;
279
+ case 'p':
280
+ // public
281
+ token = IsMatch("public", buf, Token::PUBLIC, strict);
282
+ break;
283
+ case 'r':
284
+ // return
285
+ token = IsMatch("return", buf, Token::RETURN);
286
+ break;
287
+ case 's':
288
+ // switch static
289
+ if (buf[1] == 'w' &&
290
+ buf[2] == 'i' && buf[3] == 't' &&
291
+ buf[4] == 'c' && buf[5] == 'h') {
292
+ // switch
293
+ token = Token::SWITCH;
294
+ } else if (strict &&
295
+ buf[1] == 't' &&
296
+ buf[2] == 'a' && buf[3] == 't' &&
297
+ buf[4] == 'i' && buf[5] == 'c') {
298
+ // static
299
+ token = Token::STATIC;
300
+ }
301
+ break;
302
+ case 't':
303
+ // typeof throws
304
+ if (buf[5] == 'f' &&
305
+ buf[4] == 'o' && buf[3] == 'e' &&
306
+ buf[2] == 'p' && buf[1] == 'y') {
307
+ // typeof
308
+ token = Token::TYPEOF;
309
+ } else if (buf[5] == 's' &&
310
+ buf[4] == 'w' && buf[3] == 'o' &&
311
+ buf[2] == 'r' && buf[1] == 'h') {
312
+ // throws (removed)
313
+ // token = Token::THROWS;
314
+ }
315
+ break;
316
+ }
317
+ break;
318
+ case 7:
319
+ // boolean default extends finally package private
320
+ // number 0 character is most duplicated
321
+ switch (buf[0]) {
322
+ case 'b':
323
+ // boolean (removed)
324
+ // token = IsMatch("boolean", buf, Token::BOOLEAN);
325
+ break;
326
+ case 'd':
327
+ token = IsMatch("default", buf, Token::DEFAULT);
328
+ break;
329
+ case 'e':
330
+ token = IsMatch("extends", buf, Token::EXTENDS);
331
+ break;
332
+ case 'f':
333
+ token = IsMatch("finally", buf, Token::FINALLY);
334
+ break;
335
+ case 'p':
336
+ if (buf[1] == 'a') {
337
+ token = IsMatch("package", buf, Token::PACKAGE, strict);
338
+ } else if (buf[1] == 'r') {
339
+ token = IsMatch("private", buf, Token::PRIVATE, strict);
340
+ }
341
+ break;
342
+ }
343
+ break;
344
+ case 8:
345
+ // debugger continue abstract volatile function
346
+ // number 4 character is most duplicated
347
+ switch (buf[4]) {
348
+ case 'g':
349
+ token = IsMatch("debugger", buf, Token::DEBUGGER);
350
+ break;
351
+ case 'i':
352
+ token = IsMatch("continue", buf, Token::CONTINUE);
353
+ break;
354
+ case 'r':
355
+ // abstract (removed)
356
+ // token = IsMatch("abstract", buf, Token::ABSTRACT);
357
+ break;
358
+ case 't':
359
+ if (buf[1] == 'o') {
360
+ // token = IsMatch("volatile", buf, Token::VOLATILE);
361
+ } else if (buf[1] == 'u') {
362
+ token = IsMatch("function", buf, Token::FUNCTION);
363
+ }
364
+ break;
365
+ }
366
+ break;
367
+ case 9:
368
+ // interface protected transient
369
+ if (buf[1] == 'n') {
370
+ token = IsMatch("interface", buf, Token::INTERFACE, strict);
371
+ } else if (buf[1] == 'r') {
372
+ if (buf[0] == 'p') {
373
+ token = IsMatch("protected", buf, Token::PROTECTED, strict);
374
+ } else if (buf[0] == 't') {
375
+ // transient (removed)
376
+ // token = IsMatch("transient", buf, Token::TRANSIENT);
377
+ }
378
+ }
379
+ break;
380
+ case 10:
381
+ // instanceof implements
382
+ if (buf[1] == 'n') {
383
+ token = IsMatch("instanceof", buf, Token::INSTANCEOF);
384
+ } else if (buf[1] == 'm') {
385
+ token = IsMatch("implements", buf, Token::IMPLEMENTS, strict);
386
+ }
387
+ break;
388
+ case 12:
389
+ // synchronized (removed)
390
+ // token = IsMatch("synchronized", buf, Token::SYNCHRONIZED);
391
+ token = Token::IDENTIFIER;
392
+ break;
393
+ }
394
+ return token;
395
+ }
396
+
397
+ template<typename Buffer>
398
+ static inline Token::Type IsMatch(char const * keyword,
399
+ const Buffer& buf,
400
+ Token::Type guess,
401
+ bool strict) {
402
+ if (!strict) {
403
+ return Token::IDENTIFIER;
404
+ }
405
+ typename Buffer::const_iterator it = buf.begin();
406
+ const typename Buffer::const_iterator last = buf.end();
407
+ do {
408
+ if (*it++ != *keyword++) {
409
+ return Token::IDENTIFIER;
410
+ }
411
+ } while (it != last);
412
+ return guess;
413
+ }
414
+
415
+ template<typename Buffer>
416
+ static inline Token::Type IsMatch(char const * keyword,
417
+ const Buffer& buf,
418
+ Token::Type guess) {
419
+ typename Buffer::const_iterator it = buf.begin();
420
+ const typename Buffer::const_iterator last = buf.end();
421
+ do {
422
+ if (*it++ != *keyword++) {
423
+ return Token::IDENTIFIER;
424
+ }
425
+ } while (it != last);
426
+ return guess;
427
+ }
428
+ };
429
+
430
+ template<>
431
+ class Keyword<IgnoreReservedWords> {
432
+ public:
433
+ template<typename Buffer>
434
+ static inline Token::Type Detect(const Buffer& buf, bool strict) {
435
+ return Token::IDENTIFIER;
436
+ }
437
+ };
438
+
439
+ template<>
440
+ class Keyword<IgnoreReservedWordsAndIdentifyGetterOrSetter> {
441
+ public:
442
+ template<typename Buffer>
443
+ static inline Token::Type Detect(const Buffer& buf, bool strict) {
444
+ if (buf.size() == 3) {
445
+ if (buf[1] == 'e' && buf[2] == 't') {
446
+ if (buf[0] == 'g') {
447
+ return Token::GET;
448
+ } else if (buf[0] == 's') {
449
+ return Token::SET;
450
+ }
451
+ }
452
+ }
453
+ return Token::IDENTIFIER;
454
+ }
455
+ };
456
+
457
+
458
+
459
+ } } } // namespace iv::core::detail
460
+ #endif // _IV_KEYWORD_H_