...
1
2 package code128
3
4 import (
5 "fmt"
6 "strings"
7 "unicode/utf8"
8
9 "github.com/boombuler/barcode"
10 "github.com/boombuler/barcode/utils"
11 )
12
13 func strToRunes(str string) []rune {
14 result := make([]rune, utf8.RuneCountInString(str))
15 i := 0
16 for _, r := range str {
17 result[i] = r
18 i++
19 }
20 return result
21 }
22
23 func shouldUseCTable(nextRunes []rune, curEncoding byte) bool {
24 requiredDigits := 4
25 if curEncoding == startCSymbol {
26 requiredDigits = 2
27 }
28 if len(nextRunes) < requiredDigits {
29 return false
30 }
31 for i := 0; i < requiredDigits; i++ {
32 if i%2 == 0 && nextRunes[i] == FNC1 {
33 requiredDigits++
34 if len(nextRunes) < requiredDigits {
35 return false
36 }
37 continue
38 }
39 if nextRunes[i] < '0' || nextRunes[i] > '9' {
40 return false
41 }
42 }
43 return true
44 }
45
46 func tableContainsRune(table string, r rune) bool {
47 return strings.ContainsRune(table, r) || r == FNC1 || r == FNC2 || r == FNC3 || r == FNC4
48 }
49
50 func shouldUseATable(nextRunes []rune, curEncoding byte) bool {
51 nextRune := nextRunes[0]
52 if !tableContainsRune(bTable, nextRune) || curEncoding == startASymbol {
53 return tableContainsRune(aTable, nextRune)
54 }
55 if curEncoding == 0 {
56 for _, r := range nextRunes {
57 if tableContainsRune(abTable, r) {
58 continue
59 }
60 if strings.ContainsRune(aOnlyTable, r) {
61 return true
62 }
63 break
64 }
65 }
66 return false
67 }
68
69 func getCodeIndexList(content []rune) *utils.BitList {
70 result := new(utils.BitList)
71 curEncoding := byte(0)
72 for i := 0; i < len(content); i++ {
73 if shouldUseCTable(content[i:], curEncoding) {
74 if curEncoding != startCSymbol {
75 if curEncoding == byte(0) {
76 result.AddByte(startCSymbol)
77 } else {
78 result.AddByte(codeCSymbol)
79 }
80 curEncoding = startCSymbol
81 }
82 if content[i] == FNC1 {
83 result.AddByte(102)
84 } else {
85 idx := (content[i] - '0') * 10
86 i++
87 idx = idx + (content[i] - '0')
88 result.AddByte(byte(idx))
89 }
90 } else if shouldUseATable(content[i:], curEncoding) {
91 if curEncoding != startASymbol {
92 if curEncoding == byte(0) {
93 result.AddByte(startASymbol)
94 } else {
95 result.AddByte(codeASymbol)
96 }
97 curEncoding = startASymbol
98 }
99 var idx int
100 switch content[i] {
101 case FNC1:
102 idx = 102
103 break
104 case FNC2:
105 idx = 97
106 break
107 case FNC3:
108 idx = 96
109 break
110 case FNC4:
111 idx = 101
112 break
113 default:
114 idx = strings.IndexRune(aTable, content[i])
115 break
116 }
117 if idx < 0 {
118 return nil
119 }
120 result.AddByte(byte(idx))
121 } else {
122 if curEncoding != startBSymbol {
123 if curEncoding == byte(0) {
124 result.AddByte(startBSymbol)
125 } else {
126 result.AddByte(codeBSymbol)
127 }
128 curEncoding = startBSymbol
129 }
130 var idx int
131 switch content[i] {
132 case FNC1:
133 idx = 102
134 break
135 case FNC2:
136 idx = 97
137 break
138 case FNC3:
139 idx = 96
140 break
141 case FNC4:
142 idx = 100
143 break
144 default:
145 idx = strings.IndexRune(bTable, content[i])
146 break
147 }
148
149 if idx < 0 {
150 return nil
151 }
152 result.AddByte(byte(idx))
153 }
154 }
155 return result
156 }
157
158
159 func Encode(content string) (barcode.BarcodeIntCS, error) {
160 contentRunes := strToRunes(content)
161 if len(contentRunes) <= 0 || len(contentRunes) > 80 {
162 return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes))
163 }
164 idxList := getCodeIndexList(contentRunes)
165
166 if idxList == nil {
167 return nil, fmt.Errorf("\"%s\" could not be encoded", content)
168 }
169
170 result := new(utils.BitList)
171 sum := 0
172 for i, idx := range idxList.GetBytes() {
173 if i == 0 {
174 sum = int(idx)
175 } else {
176 sum += i * int(idx)
177 }
178 result.AddBit(encodingTable[idx]...)
179 }
180 sum = sum % 103
181 result.AddBit(encodingTable[sum]...)
182 result.AddBit(encodingTable[stopSymbol]...)
183 return utils.New1DCodeIntCheckSum(barcode.TypeCode128, content, result, sum), nil
184 }
185
186 func EncodeWithoutChecksum(content string) (barcode.Barcode, error) {
187 contentRunes := strToRunes(content)
188 if len(contentRunes) <= 0 || len(contentRunes) > 80 {
189 return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes))
190 }
191 idxList := getCodeIndexList(contentRunes)
192
193 if idxList == nil {
194 return nil, fmt.Errorf("\"%s\" could not be encoded", content)
195 }
196
197 result := new(utils.BitList)
198 for _, idx := range idxList.GetBytes() {
199 result.AddBit(encodingTable[idx]...)
200 }
201 result.AddBit(encodingTable[stopSymbol]...)
202 return utils.New1DCode(barcode.TypeCode128, content, result), nil
203 }
204
View as plain text