func()

in internal/format/parser.go [105:260]


func (p *Parser) Scan() bool {
	p.Status = StatusText
	format := p.format
	end := len(format)
	if p.endPos >= end {
		return false
	}
	afterIndex := false // previous item in format was an index like [3].

	p.startPos = p.endPos
	p.goodArgNum = true
	i := p.startPos
	for i < end && format[i] != '%' {
		i++
	}
	if i > p.startPos {
		p.endPos = i
		return true
	}
	// Process one verb
	i++

	p.Status = StatusSubstitution

	// Do we have flags?
	p.ClearFlags()

simpleFormat:
	for ; i < end; i++ {
		c := p.format[i]
		switch c {
		case '#':
			p.Sharp = true
		case '0':
			p.Zero = !p.Minus // Only allow zero padding to the left.
		case '+':
			p.Plus = true
		case '-':
			p.Minus = true
			p.Zero = false // Do not pad with zeros to the right.
		case ' ':
			p.Space = true
		default:
			// Fast path for common case of ascii lower case simple verbs
			// without precision or width or argument indices.
			if 'a' <= c && c <= 'z' && p.ArgNum < len(p.Args) {
				if c == 'v' {
					// Go syntax
					p.SharpV = p.Sharp
					p.Sharp = false
					// Struct-field syntax
					p.PlusV = p.Plus
					p.Plus = false
				}
				p.Verb = rune(c)
				p.ArgNum++
				p.endPos = i + 1
				return true
			}
			// Format is more complex than simple flags and a verb or is malformed.
			break simpleFormat
		}
	}

	// Do we have an explicit argument index?
	i, afterIndex = p.updateArgNumber(format, i)

	// Do we have width?
	if i < end && format[i] == '*' {
		i++
		p.Width, p.WidthPresent = p.intFromArg()

		if !p.WidthPresent {
			p.Status = StatusBadWidthSubstitution
		}

		// We have a negative width, so take its value and ensure
		// that the minus flag is set
		if p.Width < 0 {
			p.Width = -p.Width
			p.Minus = true
			p.Zero = false // Do not pad with zeros to the right.
		}
		afterIndex = false
	} else {
		p.Width, p.WidthPresent, i = parsenum(format, i, end)
		if afterIndex && p.WidthPresent { // "%[3]2d"
			p.goodArgNum = false
		}
	}

	// Do we have precision?
	if i+1 < end && format[i] == '.' {
		i++
		if afterIndex { // "%[3].2d"
			p.goodArgNum = false
		}
		i, afterIndex = p.updateArgNumber(format, i)
		if i < end && format[i] == '*' {
			i++
			p.Prec, p.PrecPresent = p.intFromArg()
			// Negative precision arguments don't make sense
			if p.Prec < 0 {
				p.Prec = 0
				p.PrecPresent = false
			}
			if !p.PrecPresent {
				p.Status = StatusBadPrecSubstitution
			}
			afterIndex = false
		} else {
			p.Prec, p.PrecPresent, i = parsenum(format, i, end)
			if !p.PrecPresent {
				p.Prec = 0
				p.PrecPresent = true
			}
		}
	}

	if !afterIndex {
		i, afterIndex = p.updateArgNumber(format, i)
	}
	p.HasIndex = afterIndex

	if i >= end {
		p.endPos = i
		p.Status = StatusNoVerb
		return true
	}

	verb, w := utf8.DecodeRuneInString(format[i:])
	p.endPos = i + w
	p.Verb = verb

	switch {
	case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
		p.startPos = p.endPos - 1
		p.Status = StatusText
	case !p.goodArgNum:
		p.Status = StatusBadArgNum
	case p.ArgNum >= len(p.Args): // No argument left over to print for the current verb.
		p.Status = StatusMissingArg
		p.ArgNum++
	case verb == 'v':
		// Go syntax
		p.SharpV = p.Sharp
		p.Sharp = false
		// Struct-field syntax
		p.PlusV = p.Plus
		p.Plus = false
		fallthrough
	default:
		p.ArgNum++
	}
	return true
}