| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- package strftime
- import "unicode/utf8"
- type parser struct {
- format func(spec, flag byte) error
- literal func(byte) error
- }
- func (p *parser) parse(fmt string) error {
- const (
- initial = iota
- percent
- flagged
- modified
- )
- var flag, modifier byte
- var err error
- state := initial
- start := 0
- for i, b := range []byte(fmt) {
- switch state {
- default:
- if b == '%' {
- state = percent
- start = i
- continue
- }
- err = p.literal(b)
- case percent:
- if b == '-' || b == ':' {
- state = flagged
- flag = b
- continue
- }
- if b == 'E' || b == 'O' {
- state = modified
- modifier = b
- flag = 0
- continue
- }
- err = p.format(b, 0)
- state = initial
- case flagged:
- if b == 'E' || b == 'O' {
- state = modified
- modifier = b
- continue
- }
- err = p.format(b, flag)
- state = initial
- case modified:
- if okModifier(modifier, b) {
- err = p.format(b, flag)
- } else {
- err = p.literals(fmt[start : i+1])
- }
- state = initial
- }
- if err != nil {
- if err, ok := err.(formatError); ok {
- err.setDirective(fmt, start, i)
- return err
- }
- return err
- }
- }
- if state != initial {
- return p.literals(fmt[start:])
- }
- return nil
- }
- func (p *parser) literals(literal string) error {
- for _, b := range []byte(literal) {
- if err := p.literal(b); err != nil {
- return err
- }
- }
- return nil
- }
- type literalErr string
- func (e literalErr) Error() string {
- return "strftime: unsupported literal: " + string(e)
- }
- type formatError struct {
- message string
- directive string
- }
- func (e formatError) Error() string {
- return "strftime: unsupported directive: " + e.directive + " " + e.message
- }
- func (e *formatError) setDirective(str string, i, j int) {
- _, n := utf8.DecodeRuneInString(str[j:])
- e.directive = str[i : j+n]
- }
|