encoder.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package code39
  2. import (
  3. "errors"
  4. "github.com/boombuler/barcode"
  5. "strings"
  6. )
  7. type encodeInfo struct {
  8. value int
  9. data []bool
  10. }
  11. var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{
  12. '0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}},
  13. '1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}},
  14. '2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
  15. '3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}},
  16. '4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}},
  17. '5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}},
  18. '6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}},
  19. '7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}},
  20. '8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}},
  21. '9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}},
  22. 'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}},
  23. 'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}},
  24. 'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}},
  25. 'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}},
  26. 'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}},
  27. 'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}},
  28. 'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}},
  29. 'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}},
  30. 'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}},
  31. 'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}},
  32. 'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}},
  33. 'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}},
  34. 'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}},
  35. 'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}},
  36. 'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}},
  37. 'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}},
  38. 'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}},
  39. 'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}},
  40. 'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}},
  41. 'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}},
  42. 'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}},
  43. 'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}},
  44. 'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}},
  45. 'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}},
  46. 'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}},
  47. 'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}},
  48. '-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}},
  49. '.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}},
  50. ' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}},
  51. '$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}},
  52. '/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}},
  53. '+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}},
  54. '%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}},
  55. '*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
  56. }
  57. func getChecksum(content string) string {
  58. sum := 0
  59. for _, r := range content {
  60. info, ok := encodeTable[r]
  61. if !ok || info.value < 0 {
  62. return "#"
  63. }
  64. sum += info.value
  65. }
  66. sum = sum % 43
  67. for r, v := range encodeTable {
  68. if v.value == sum {
  69. return string(r)
  70. }
  71. }
  72. return "#"
  73. }
  74. // encodes the given string as a code39 barcode
  75. // if includeChecksum is set to true, a checksum character is calculated and added to the content
  76. func Encode(content string, includeChecksum bool) (barcode.Barcode, error) {
  77. if strings.ContainsRune(content, '*') {
  78. return nil, errors.New("invalid data")
  79. }
  80. data := "*" + content
  81. if includeChecksum {
  82. data += getChecksum(content)
  83. }
  84. data += "*"
  85. cd := newCode()
  86. for i, r := range data {
  87. if i != 0 {
  88. cd.AddBit(false)
  89. }
  90. info, ok := encodeTable[r]
  91. if !ok {
  92. return nil, errors.New("invalid data")
  93. }
  94. for _, bit := range info.data {
  95. cd.AddBit(bit)
  96. }
  97. }
  98. return cd, nil
  99. }