1 package httpaccept 2 3 import "vimagination.zapto.org/parser" 4 5 const ( 6 alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 7 digit = "0123456789" 8 tchar = "!#$%&'*+-.^_`|~" + digit + alpha 9 ows = " \t" 10 delim = "," 11 weightDelim = ";" 12 qvalPrefix = "q=" 13 ) 14 15 const ( 16 tokenMedia parser.TokenType = iota 17 tokenWeight 18 tokenInvalidWeight 19 ) 20 21 func parseAccept(accept string) *parser.Parser { 22 t := parser.New(parser.NewStringTokeniser(accept)) 23 24 t.TokeniserState(parseList) 25 26 return &t 27 } 28 29 func parseList(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) { 30 for { 31 t.AcceptRun(ows) 32 t.Get() 33 34 if t.Accept(tchar) { 35 t.AcceptRun(tchar) 36 37 if t.Accept("/") && t.Accept(tchar) { 38 t.AcceptRun(tchar) 39 40 return t.Return(tokenMedia, parseQVal) 41 } 42 } else if t.Peek() == -1 { 43 return t.Done() 44 } 45 46 t.ExceptRun(delim) 47 t.Accept(delim) 48 } 49 } 50 51 func parseQVal(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) { 52 t.AcceptRun(ows) 53 t.Get() 54 55 if !t.Accept(weightDelim) { 56 t.ExceptRun(delim) 57 t.Accept(delim) 58 59 return parseList(t) 60 } 61 62 t.AcceptRun(ows) 63 t.Get() 64 65 if t.AcceptString(qvalPrefix, false) == len(qvalPrefix) { 66 t.Get() 67 68 if t.Accept("0") { 69 return parse0(t) 70 } else if t.AcceptString("1.000", false) > 0 { 71 return parseWeightEnd(t) 72 } 73 } 74 75 t.ExceptRun(delim) 76 t.Accept(delim) 77 78 return t.Return(tokenInvalidWeight, parseList) 79 } 80 81 func parse0(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) { 82 if t.Accept(".") { 83 t.Accept(digit) 84 t.Accept(digit) 85 t.Accept(digit) 86 } 87 88 return parseWeightEnd(t) 89 } 90 91 func parseWeightEnd(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) { 92 data := t.Get() 93 94 t.AcceptRun(ows) 95 96 if t.Accept(delim) || t.Peek() == -1 { 97 return parser.Token{Type: tokenWeight, Data: data}, parseList 98 } 99 100 t.ExceptRun(delim) 101 t.Accept(delim) 102 t.Get() 103 104 return t.Return(tokenInvalidWeight, parseList) 105 } 106