converter.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. 'use strict';
  2. /**
  3. * Converter
  4. *
  5. * @param {string|Array} srcAlphabet
  6. * @param {string|Array} dstAlphabet
  7. * @constructor
  8. */
  9. function Converter(srcAlphabet, dstAlphabet) {
  10. if (!srcAlphabet || !dstAlphabet || !srcAlphabet.length || !dstAlphabet.length) {
  11. throw new Error('Bad alphabet');
  12. }
  13. this.srcAlphabet = srcAlphabet;
  14. this.dstAlphabet = dstAlphabet;
  15. }
  16. /**
  17. * Convert number from source alphabet to destination alphabet
  18. *
  19. * @param {string|Array} number - number represented as a string or array of points
  20. *
  21. * @returns {string|Array}
  22. */
  23. Converter.prototype.convert = function(number) {
  24. var i, divide, newlen,
  25. numberMap = {},
  26. fromBase = this.srcAlphabet.length,
  27. toBase = this.dstAlphabet.length,
  28. length = number.length,
  29. result = typeof number === 'string' ? '' : [];
  30. if (!this.isValid(number)) {
  31. throw new Error('Number "' + number + '" contains of non-alphabetic digits (' + this.srcAlphabet + ')');
  32. }
  33. if (this.srcAlphabet === this.dstAlphabet) {
  34. return number;
  35. }
  36. for (i = 0; i < length; i++) {
  37. numberMap[i] = this.srcAlphabet.indexOf(number[i]);
  38. }
  39. do {
  40. divide = 0;
  41. newlen = 0;
  42. for (i = 0; i < length; i++) {
  43. divide = divide * fromBase + numberMap[i];
  44. if (divide >= toBase) {
  45. numberMap[newlen++] = parseInt(divide / toBase, 10);
  46. divide = divide % toBase;
  47. } else if (newlen > 0) {
  48. numberMap[newlen++] = 0;
  49. }
  50. }
  51. length = newlen;
  52. result = this.dstAlphabet.slice(divide, divide + 1).concat(result);
  53. } while (newlen !== 0);
  54. return result;
  55. };
  56. /**
  57. * Valid number with source alphabet
  58. *
  59. * @param {number} number
  60. *
  61. * @returns {boolean}
  62. */
  63. Converter.prototype.isValid = function(number) {
  64. var i = 0;
  65. for (; i < number.length; ++i) {
  66. if (this.srcAlphabet.indexOf(number[i]) === -1) {
  67. return false;
  68. }
  69. }
  70. return true;
  71. };
  72. module.exports = Converter;