index.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*!
  2. * bytes
  3. * Copyright(c) 2012-2014 TJ Holowaychuk
  4. * Copyright(c) 2015 Jed Watson
  5. * MIT Licensed
  6. */
  7. 'use strict';
  8. /**
  9. * Module exports.
  10. * @public
  11. */
  12. module.exports = bytes;
  13. module.exports.format = format;
  14. module.exports.parse = parse;
  15. /**
  16. * Module variables.
  17. * @private
  18. */
  19. var map = {
  20. b: 1,
  21. kb: 1 << 10,
  22. mb: 1 << 20,
  23. gb: 1 << 30,
  24. tb: ((1 << 30) * 1024)
  25. };
  26. /**
  27. *Convert the given value in bytes into a string or parse to string to an integer in bytes.
  28. *
  29. * @param {string|number} value
  30. * @param {{
  31. * case: [string],
  32. * decimalPlaces: [number]
  33. * fixedDecimals: [boolean]
  34. * thousandsSeparator: [string]
  35. * }} [options] bytes options.
  36. *
  37. * @returns {string|number|null}
  38. */
  39. function bytes(value, options) {
  40. if (typeof value === 'string') {
  41. return parse(value);
  42. }
  43. if (typeof value === 'number') {
  44. return format(value, options);
  45. }
  46. return null;
  47. }
  48. /**
  49. * Format the given value in bytes into a string.
  50. *
  51. * If the value is negative, it is kept as such. If it is a float,
  52. * it is rounded.
  53. *
  54. * @param {number} value
  55. * @param {object} [options]
  56. * @param {number} [options.decimalPlaces=2]
  57. * @param {number} [options.fixedDecimals=false]
  58. * @param {string} [options.thousandsSeparator=]
  59. * @public
  60. */
  61. function format(value, options) {
  62. if (typeof value !== 'number') {
  63. return null;
  64. }
  65. var mag = Math.abs(value);
  66. var thousandsSeparator = (options && options.thousandsSeparator) || '';
  67. var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
  68. var fixedDecimals = Boolean(options && options.fixedDecimals);
  69. var unit = 'B';
  70. if (mag >= map.tb) {
  71. unit = 'TB';
  72. } else if (mag >= map.gb) {
  73. unit = 'GB';
  74. } else if (mag >= map.mb) {
  75. unit = 'MB';
  76. } else if (mag >= map.kb) {
  77. unit = 'kB';
  78. }
  79. var val = value / map[unit.toLowerCase()];
  80. var str = val.toFixed(decimalPlaces);
  81. if (!fixedDecimals) {
  82. str = str.replace(/(?:\.0*|(\.[^0]+)0+)$/, '$1');
  83. }
  84. if (thousandsSeparator) {
  85. str = str.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
  86. }
  87. return str + unit;
  88. }
  89. /**
  90. * Parse the string value into an integer in bytes.
  91. *
  92. * If no unit is given, it is assumed the value is in bytes.
  93. *
  94. * @param {number|string} val
  95. * @public
  96. */
  97. function parse(val) {
  98. if (typeof val === 'number' && !isNaN(val)) {
  99. return val;
  100. }
  101. if (typeof val !== 'string') {
  102. return null;
  103. }
  104. // Test if the string passed is valid
  105. var results = val.match(/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb)$/i);
  106. var floatValue;
  107. var unit = 'b';
  108. if (!results) {
  109. // Nothing could be extracted from the given string
  110. floatValue = parseInt(val);
  111. unit = 'b'
  112. } else {
  113. // Retrieve the value and the unit
  114. floatValue = parseFloat(results[1]);
  115. unit = results[4].toLowerCase();
  116. }
  117. return map[unit] * floatValue;
  118. }