github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa5008/structtag.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Copyright 2019 Dominik Honnef. All rights reserved.
     3  
     4  package sa5008
     5  
     6  import "strconv"
     7  
     8  func parseStructTag(tag string) (map[string][]string, error) {
     9  	// FIXME(dh): detect missing closing quote
    10  	out := map[string][]string{}
    11  
    12  	for tag != "" {
    13  		// Skip leading space.
    14  		i := 0
    15  		for i < len(tag) && tag[i] == ' ' {
    16  			i++
    17  		}
    18  		tag = tag[i:]
    19  		if tag == "" {
    20  			break
    21  		}
    22  
    23  		// Scan to colon. A space, a quote or a control character is a syntax error.
    24  		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
    25  		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
    26  		// as it is simpler to inspect the tag's bytes than the tag's runes.
    27  		i = 0
    28  		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
    29  			i++
    30  		}
    31  		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
    32  			break
    33  		}
    34  		name := string(tag[:i])
    35  		tag = tag[i+1:]
    36  
    37  		// Scan quoted string to find value.
    38  		i = 1
    39  		for i < len(tag) && tag[i] != '"' {
    40  			if tag[i] == '\\' {
    41  				i++
    42  			}
    43  			i++
    44  		}
    45  		if i >= len(tag) {
    46  			break
    47  		}
    48  		qvalue := string(tag[:i+1])
    49  		tag = tag[i+1:]
    50  
    51  		value, err := strconv.Unquote(qvalue)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		out[name] = append(out[name], value)
    56  	}
    57  	return out, nil
    58  }