l0bsterssg

node.js static responsive blog post generator
Log | Files | Refs | README

int.js (4066B)


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