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  }