git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/barcode/qr/alphanumeric.go (about) 1 package qr 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "git.sr.ht/~pingoo/stdx/barcode/utils" 9 ) 10 11 const charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" 12 13 func stringToAlphaIdx(content string) <-chan int { 14 result := make(chan int) 15 go func() { 16 for _, r := range content { 17 idx := strings.IndexRune(charSet, r) 18 result <- idx 19 if idx < 0 { 20 break 21 } 22 } 23 close(result) 24 }() 25 26 return result 27 } 28 29 func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { 30 31 contentLenIsOdd := len(content)%2 == 1 32 contentBitCount := (len(content) / 2) * 11 33 if contentLenIsOdd { 34 contentBitCount += 6 35 } 36 vi := findSmallestVersionInfo(ecl, alphaNumericMode, contentBitCount) 37 if vi == nil { 38 return nil, nil, errors.New("To much data to encode") 39 } 40 41 res := new(utils.BitList) 42 res.AddBits(int(alphaNumericMode), 4) 43 res.AddBits(len(content), vi.charCountBits(alphaNumericMode)) 44 45 encoder := stringToAlphaIdx(content) 46 47 for idx := 0; idx < len(content)/2; idx++ { 48 c1 := <-encoder 49 c2 := <-encoder 50 if c1 < 0 || c2 < 0 { 51 return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) 52 } 53 res.AddBits(c1*45+c2, 11) 54 } 55 if contentLenIsOdd { 56 c := <-encoder 57 if c < 0 { 58 return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) 59 } 60 res.AddBits(c, 6) 61 } 62 63 addPaddingAndTerminator(res, vi) 64 65 return res, vi, nil 66 }