github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/lib/stringlib/packsize.go (about) 1 package stringlib 2 3 type packsizer struct { 4 packFormatReader 5 size uint 6 } 7 8 func PackSize(format string) (uint, error) { 9 s := &packsizer{packFormatReader: packFormatReader{ 10 format: format, 11 byteOrder: nativeEndian, 12 maxAlignment: defaultMaxAlignement, 13 }} 14 for s.hasNext() { 15 switch c := s.nextOption(); c { 16 case '<', '>', '=', ' ': 17 // Nothing to do 18 case '!': 19 if s.smallOptSize(defaultMaxAlignement) { 20 s.maxAlignment = s.optSize 21 } 22 case 'b', 'B': 23 _ = s.align(0) && s.inc(1) 24 case 'h', 'H': 25 _ = s.align(2) && s.inc(2) 26 case 'l', 'j', 'L', 'J', 'T', 'd', 'n': 27 _ = s.align(8) && s.inc(8) 28 case 'f': 29 _ = s.align(4) && s.inc(4) 30 case 'i', 'I': 31 _ = s.smallOptSize(8) && s.align(s.optSize) && s.inc(s.optSize) 32 case 'c': 33 _ = s.align(0) && s.mustGetOptSize() && s.inc(s.optSize) 34 case 'x': 35 _ = s.align(0) && s.inc(1) 36 case 'X': 37 s.alignOnly = true 38 case 's', 'z': 39 s.err = errVariableLength 40 default: 41 s.err = errBadFormatString(c) 42 } 43 if s.err != nil { 44 return 0, s.err 45 } 46 } 47 48 return s.size, nil 49 } 50 51 func (s *packsizer) align(n uint) bool { 52 if n != 0 { 53 if n > s.maxAlignment { 54 n = s.maxAlignment 55 } 56 if (n-1)&n != 0 { // (n-1)&n == 0 iff n is a power of 2 (or 0) 57 s.err = errBadAlignment 58 return false 59 } 60 if r := s.size % n; r != 0 { 61 s.size += n - r 62 } 63 } 64 if s.alignOnly { 65 s.alignOnly = false 66 return false 67 } 68 return true 69 70 } 71 72 func (s *packsizer) inc(n uint) bool { 73 s.size += n 74 return true 75 }