encoder.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Package twooffive can create interleaved and standard "2 of 5" barcodes.
  2. package twooffive
  3. import (
  4. "errors"
  5. "fmt"
  6. "github.com/boombuler/barcode"
  7. "github.com/boombuler/barcode/utils"
  8. )
  9. const patternWidth = 5
  10. type pattern [patternWidth]bool
  11. type encodeInfo struct {
  12. start []bool
  13. end []bool
  14. widths map[bool]int
  15. }
  16. var (
  17. encodingTable = map[rune]pattern{
  18. '0': pattern{false, false, true, true, false},
  19. '1': pattern{true, false, false, false, true},
  20. '2': pattern{false, true, false, false, true},
  21. '3': pattern{true, true, false, false, false},
  22. '4': pattern{false, false, true, false, true},
  23. '5': pattern{true, false, true, false, false},
  24. '6': pattern{false, true, true, false, false},
  25. '7': pattern{false, false, false, true, true},
  26. '8': pattern{true, false, false, true, false},
  27. '9': pattern{false, true, false, true, false},
  28. }
  29. modes = map[bool]encodeInfo{
  30. false: encodeInfo{ // non-interleaved
  31. start: []bool{true, true, false, true, true, false, true, false},
  32. end: []bool{true, true, false, true, false, true, true},
  33. widths: map[bool]int{
  34. true: 3,
  35. false: 1,
  36. },
  37. },
  38. true: encodeInfo{ // interleaved
  39. start: []bool{true, false, true, false},
  40. end: []bool{true, true, false, true},
  41. widths: map[bool]int{
  42. true: 3,
  43. false: 1,
  44. },
  45. },
  46. }
  47. nonInterleavedSpace = pattern{false, false, false, false, false}
  48. )
  49. // AddCheckSum calculates the correct check-digit and appends it to the given content.
  50. func AddCheckSum(content string) (string, error) {
  51. if content == "" {
  52. return "", errors.New("content is empty")
  53. }
  54. even := len(content)%2 == 1
  55. sum := 0
  56. for _, r := range content {
  57. if _, ok := encodingTable[r]; ok {
  58. value := utils.RuneToInt(r)
  59. if even {
  60. sum += value * 3
  61. } else {
  62. sum += value
  63. }
  64. even = !even
  65. } else {
  66. return "", fmt.Errorf("can not encode \"%s\"", content)
  67. }
  68. }
  69. return content + string(utils.IntToRune(sum%10)), nil
  70. }
  71. // Encode creates a codabar barcode for the given content
  72. func Encode(content string, interleaved bool) (barcode.Barcode, error) {
  73. if content == "" {
  74. return nil, errors.New("content is empty")
  75. }
  76. if interleaved && len(content)%2 == 1 {
  77. return nil, errors.New("can only encode even number of digits in interleaved mode")
  78. }
  79. mode := modes[interleaved]
  80. resBits := new(utils.BitList)
  81. resBits.AddBit(mode.start...)
  82. var lastRune *rune
  83. for _, r := range content {
  84. var a, b pattern
  85. if interleaved {
  86. if lastRune == nil {
  87. lastRune = new(rune)
  88. *lastRune = r
  89. continue
  90. } else {
  91. var o1, o2 bool
  92. a, o1 = encodingTable[*lastRune]
  93. b, o2 = encodingTable[r]
  94. if !o1 || !o2 {
  95. return nil, fmt.Errorf("can not encode \"%s\"", content)
  96. }
  97. lastRune = nil
  98. }
  99. } else {
  100. var ok bool
  101. a, ok = encodingTable[r]
  102. if !ok {
  103. return nil, fmt.Errorf("can not encode \"%s\"", content)
  104. }
  105. b = nonInterleavedSpace
  106. }
  107. for i := 0; i < patternWidth; i++ {
  108. for x := 0; x < mode.widths[a[i]]; x++ {
  109. resBits.AddBit(true)
  110. }
  111. for x := 0; x < mode.widths[b[i]]; x++ {
  112. resBits.AddBit(false)
  113. }
  114. }
  115. }
  116. resBits.AddBit(mode.end...)
  117. if interleaved {
  118. return utils.New1DCode(barcode.Type2of5Interleaved, content, resBits), nil
  119. } else {
  120. return utils.New1DCode(barcode.Type2of5, content, resBits), nil
  121. }
  122. }