8272f0fdc6bc2002e684152ade21a76186dfde98c35b1a22ffd72eab31fa9d61ee05381896867ae44ddb302008e41a0a728da3e4c9a05a1d4a5d9cd2a92334 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. 'use strict';
  2. var common = require('../common');
  3. var Type = require('../type');
  4. var YAML_FLOAT_PATTERN = new RegExp(
  5. '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' +
  6. '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' +
  7. '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
  8. '|[-+]?\\.(?:inf|Inf|INF)' +
  9. '|\\.(?:nan|NaN|NAN))$');
  10. function resolveYamlFloat(data) {
  11. if (data === null) return false;
  12. if (!YAML_FLOAT_PATTERN.test(data)) return false;
  13. return true;
  14. }
  15. function constructYamlFloat(data) {
  16. var value, sign, base, digits;
  17. value = data.replace(/_/g, '').toLowerCase();
  18. sign = value[0] === '-' ? -1 : 1;
  19. digits = [];
  20. if ('+-'.indexOf(value[0]) >= 0) {
  21. value = value.slice(1);
  22. }
  23. if (value === '.inf') {
  24. return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
  25. } else if (value === '.nan') {
  26. return NaN;
  27. } else if (value.indexOf(':') >= 0) {
  28. value.split(':').forEach(function (v) {
  29. digits.unshift(parseFloat(v, 10));
  30. });
  31. value = 0.0;
  32. base = 1;
  33. digits.forEach(function (d) {
  34. value += d * base;
  35. base *= 60;
  36. });
  37. return sign * value;
  38. }
  39. return sign * parseFloat(value, 10);
  40. }
  41. var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
  42. function representYamlFloat(object, style) {
  43. var res;
  44. if (isNaN(object)) {
  45. switch (style) {
  46. case 'lowercase': return '.nan';
  47. case 'uppercase': return '.NAN';
  48. case 'camelcase': return '.NaN';
  49. }
  50. } else if (Number.POSITIVE_INFINITY === object) {
  51. switch (style) {
  52. case 'lowercase': return '.inf';
  53. case 'uppercase': return '.INF';
  54. case 'camelcase': return '.Inf';
  55. }
  56. } else if (Number.NEGATIVE_INFINITY === object) {
  57. switch (style) {
  58. case 'lowercase': return '-.inf';
  59. case 'uppercase': return '-.INF';
  60. case 'camelcase': return '-.Inf';
  61. }
  62. } else if (common.isNegativeZero(object)) {
  63. return '-0.0';
  64. }
  65. res = object.toString(10);
  66. // JS stringifier can build scientific format without dots: 5e-100,
  67. // while YAML requres dot: 5.e-100. Fix it with simple hack
  68. return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
  69. }
  70. function isFloat(object) {
  71. return (Object.prototype.toString.call(object) === '[object Number]') &&
  72. (object % 1 !== 0 || common.isNegativeZero(object));
  73. }
  74. module.exports = new Type('tag:yaml.org,2002:float', {
  75. kind: 'scalar',
  76. resolve: resolveYamlFloat,
  77. construct: constructYamlFloat,
  78. predicate: isFloat,
  79. represent: representYamlFloat,
  80. defaultStyle: 'lowercase'
  81. });