github.com/seh/gb@v0.4.4-0.20160724065125-065d2b2b1ba1/internal/importer/util.go (about)

     1  package importer
     2  
     3  import (
     4  	"errors"
     5  	"unicode"
     6  )
     7  
     8  // splitQuoted splits the string s around each instance of one or more consecutive
     9  // white space characters while taking into account quotes and escaping, and
    10  // returns an array of substrings of s or an empty list if s contains only white space.
    11  // Single quotes and double quotes are recognized to prevent splitting within the
    12  // quoted region, and are removed from the resulting substrings. If a quote in s
    13  // isn't closed err will be set and r will have the unclosed argument as the
    14  // last element.  The backslash is used for escaping.
    15  //
    16  // For example, the following string:
    17  //
    18  //     a b:"c d" 'e''f'  "g\""
    19  //
    20  // Would be parsed as:
    21  //
    22  //     []string{"a", "b:c d", "ef", `g"`}
    23  //
    24  func splitQuoted(s string) (r []string, err error) {
    25  	var args []string
    26  	arg := make([]rune, len(s))
    27  	escaped := false
    28  	quoted := false
    29  	quote := '\x00'
    30  	i := 0
    31  	for _, rune := range s {
    32  		switch {
    33  		case escaped:
    34  			escaped = false
    35  		case rune == '\\':
    36  			escaped = true
    37  			continue
    38  		case quote != '\x00':
    39  			if rune == quote {
    40  				quote = '\x00'
    41  				continue
    42  			}
    43  		case rune == '"' || rune == '\'':
    44  			quoted = true
    45  			quote = rune
    46  			continue
    47  		case unicode.IsSpace(rune):
    48  			if quoted || i > 0 {
    49  				quoted = false
    50  				args = append(args, string(arg[:i]))
    51  				i = 0
    52  			}
    53  			continue
    54  		}
    55  		arg[i] = rune
    56  		i++
    57  	}
    58  	if quoted || i > 0 {
    59  		args = append(args, string(arg[:i]))
    60  	}
    61  	if quote != 0 {
    62  		err = errors.New("unclosed quote")
    63  	} else if escaped {
    64  		err = errors.New("unfinished escaping")
    65  	}
    66  	return args, err
    67  }