123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- 'use strict';
- var common = require('../common');
- var Type = require('../type');
- var YAML_FLOAT_PATTERN = new RegExp(
- // 2.5e4, 2.5 and integers
- '^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
- // .2e4, .2
- // special case, seems not from spec
- '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
- // 20:59
- '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
- // .inf
- '|[-+]?\\.(?:inf|Inf|INF)' +
- // .nan
- '|\\.(?:nan|NaN|NAN))$');
- function resolveYamlFloat(data) {
- if (data === null) return false;
- if (!YAML_FLOAT_PATTERN.test(data) ||
- // Quick hack to not allow integers end with `_`
- // Probably should update regexp & check speed
- data[data.length - 1] === '_') {
- return false;
- }
- return true;
- }
- function constructYamlFloat(data) {
- var value, sign, base, digits;
- value = data.replace(/_/g, '').toLowerCase();
- sign = value[0] === '-' ? -1 : 1;
- digits = [];
- if ('+-'.indexOf(value[0]) >= 0) {
- value = value.slice(1);
- }
- if (value === '.inf') {
- return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
- } else if (value === '.nan') {
- return NaN;
- } else if (value.indexOf(':') >= 0) {
- value.split(':').forEach(function (v) {
- digits.unshift(parseFloat(v, 10));
- });
- value = 0.0;
- base = 1;
- digits.forEach(function (d) {
- value += d * base;
- base *= 60;
- });
- return sign * value;
- }
- return sign * parseFloat(value, 10);
- }
- var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
- function representYamlFloat(object, style) {
- var res;
- if (isNaN(object)) {
- switch (style) {
- case 'lowercase': return '.nan';
- case 'uppercase': return '.NAN';
- case 'camelcase': return '.NaN';
- }
- } else if (Number.POSITIVE_INFINITY === object) {
- switch (style) {
- case 'lowercase': return '.inf';
- case 'uppercase': return '.INF';
- case 'camelcase': return '.Inf';
- }
- } else if (Number.NEGATIVE_INFINITY === object) {
- switch (style) {
- case 'lowercase': return '-.inf';
- case 'uppercase': return '-.INF';
- case 'camelcase': return '-.Inf';
- }
- } else if (common.isNegativeZero(object)) {
- return '-0.0';
- }
- res = object.toString(10);
- // JS stringifier can build scientific format without dots: 5e-100,
- // while YAML requres dot: 5.e-100. Fix it with simple hack
- return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
- }
- function isFloat(object) {
- return (Object.prototype.toString.call(object) === '[object Number]') &&
- (object % 1 !== 0 || common.isNegativeZero(object));
- }
- module.exports = new Type('tag:yaml.org,2002:float', {
- kind: 'scalar',
- resolve: resolveYamlFloat,
- construct: constructYamlFloat,
- predicate: isFloat,
- represent: representYamlFloat,
- defaultStyle: 'lowercase'
- });
|