mode.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. var VersionCheck = require('./version-check')
  2. var Regex = require('./regex')
  3. /**
  4. * Numeric mode encodes data from the decimal digit set (0 - 9)
  5. * (byte values 30HEX to 39HEX).
  6. * Normally, 3 data characters are represented by 10 bits.
  7. *
  8. * @type {Object}
  9. */
  10. exports.NUMERIC = {
  11. id: 'Numeric',
  12. bit: 1 << 0,
  13. ccBits: [10, 12, 14]
  14. }
  15. /**
  16. * Alphanumeric mode encodes data from a set of 45 characters,
  17. * i.e. 10 numeric digits (0 - 9),
  18. * 26 alphabetic characters (A - Z),
  19. * and 9 symbols (SP, $, %, *, +, -, ., /, :).
  20. * Normally, two input characters are represented by 11 bits.
  21. *
  22. * @type {Object}
  23. */
  24. exports.ALPHANUMERIC = {
  25. id: 'Alphanumeric',
  26. bit: 1 << 1,
  27. ccBits: [9, 11, 13]
  28. }
  29. /**
  30. * In byte mode, data is encoded at 8 bits per character.
  31. *
  32. * @type {Object}
  33. */
  34. exports.BYTE = {
  35. id: 'Byte',
  36. bit: 1 << 2,
  37. ccBits: [8, 16, 16]
  38. }
  39. /**
  40. * The Kanji mode efficiently encodes Kanji characters in accordance with
  41. * the Shift JIS system based on JIS X 0208.
  42. * The Shift JIS values are shifted from the JIS X 0208 values.
  43. * JIS X 0208 gives details of the shift coded representation.
  44. * Each two-byte character value is compacted to a 13-bit binary codeword.
  45. *
  46. * @type {Object}
  47. */
  48. exports.KANJI = {
  49. id: 'Kanji',
  50. bit: 1 << 3,
  51. ccBits: [8, 10, 12]
  52. }
  53. /**
  54. * Mixed mode will contain a sequences of data in a combination of any of
  55. * the modes described above
  56. *
  57. * @type {Object}
  58. */
  59. exports.MIXED = {
  60. bit: -1
  61. }
  62. /**
  63. * Returns the number of bits needed to store the data length
  64. * according to QR Code specifications.
  65. *
  66. * @param {Mode} mode Data mode
  67. * @param {Number} version QR Code version
  68. * @return {Number} Number of bits
  69. */
  70. exports.getCharCountIndicator = function getCharCountIndicator (mode, version) {
  71. if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)
  72. if (!VersionCheck.isValid(version)) {
  73. throw new Error('Invalid version: ' + version)
  74. }
  75. if (version >= 1 && version < 10) return mode.ccBits[0]
  76. else if (version < 27) return mode.ccBits[1]
  77. return mode.ccBits[2]
  78. }
  79. /**
  80. * Returns the most efficient mode to store the specified data
  81. *
  82. * @param {String} dataStr Input data string
  83. * @return {Mode} Best mode
  84. */
  85. exports.getBestModeForData = function getBestModeForData (dataStr) {
  86. if (Regex.testNumeric(dataStr)) return exports.NUMERIC
  87. else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC
  88. else if (Regex.testKanji(dataStr)) return exports.KANJI
  89. else return exports.BYTE
  90. }
  91. /**
  92. * Return mode name as string
  93. *
  94. * @param {Mode} mode Mode object
  95. * @returns {String} Mode name
  96. */
  97. exports.toString = function toString (mode) {
  98. if (mode && mode.id) return mode.id
  99. throw new Error('Invalid mode')
  100. }
  101. /**
  102. * Check if input param is a valid mode object
  103. *
  104. * @param {Mode} mode Mode object
  105. * @returns {Boolean} True if valid mode, false otherwise
  106. */
  107. exports.isValid = function isValid (mode) {
  108. return mode && mode.bit && mode.ccBits
  109. }
  110. /**
  111. * Get mode object from its name
  112. *
  113. * @param {String} string Mode name
  114. * @returns {Mode} Mode object
  115. */
  116. function fromString (string) {
  117. if (typeof string !== 'string') {
  118. throw new Error('Param is not a string')
  119. }
  120. var lcStr = string.toLowerCase()
  121. switch (lcStr) {
  122. case 'numeric':
  123. return exports.NUMERIC
  124. case 'alphanumeric':
  125. return exports.ALPHANUMERIC
  126. case 'kanji':
  127. return exports.KANJI
  128. case 'byte':
  129. return exports.BYTE
  130. default:
  131. throw new Error('Unknown mode: ' + string)
  132. }
  133. }
  134. /**
  135. * Returns mode from a value.
  136. * If value is not a valid mode, returns defaultValue
  137. *
  138. * @param {Mode|String} value Encoding mode
  139. * @param {Mode} defaultValue Fallback value
  140. * @return {Mode} Encoding mode
  141. */
  142. exports.from = function from (value, defaultValue) {
  143. if (exports.isValid(value)) {
  144. return value
  145. }
  146. try {
  147. return fromString(value)
  148. } catch (e) {
  149. return defaultValue
  150. }
  151. }