1// Copyright 2010 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package edn 6 7import ( 8 "reflect" 9 "strconv" 10 "unicode/utf8" 11) 12 13// getu4 decodes \uXXXX from the beginning of s, returning the hex value, 14// or it returns -1. 15func getu4(s []byte) rune { 16 if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { 17 return -1 18 } 19 r, err := strconv.ParseUint(string(s[2:6]), 16, 64) 20 if err != nil { 21 return -1 22 } 23 return rune(r) 24} 25 26// indirect walks down v allocating pointers as needed, 27// until it gets to a non-pointer. 28// if it encounters an Unmarshaler, indirect stops and returns that. 29// if decodingNull is true, indirect stops at the last pointer so it can be set to nil. 30func (d *Decoder) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) { 31 // If v is a named type and is addressable, 32 // start with its address, so that if the type has pointer methods, 33 // we find them. 34 if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { 35 v = v.Addr() 36 } 37 for { 38 // Load value from interface, but only if the result will be 39 // usefully addressable. 40 if v.Kind() == reflect.Interface && !v.IsNil() { 41 e := v.Elem() 42 if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { 43 v = e 44 continue 45 } 46 } 47 48 if v.Kind() != reflect.Ptr { 49 break 50 } 51 52 if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { 53 break 54 } 55 if v.IsNil() { 56 v.Set(reflect.New(v.Type().Elem())) 57 } 58 if v.Type().NumMethod() > 0 { 59 if u, ok := v.Interface().(Unmarshaler); ok { 60 return u, reflect.Value{} 61 } 62 } 63 v = v.Elem() 64 } 65 return nil, v 66} 67 68// unquote converts a quoted EDN string literal s into an actual string t. 69// The rules are different than for Go, so cannot use strconv.Unquote. 70func unquote(s []byte) (t string, ok bool) { 71 s, ok = unquoteBytes(s) 72 t = string(s) 73 return 74} 75 76func unquoteBytes(s []byte) (t []byte, ok bool) { 77 if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { 78 return 79 } 80 s = s[1 : len(s)-1] 81 82 // Check for unusual characters. If there are none, 83 // then no unquoting is needed, so return a slice of the 84 // original bytes. 85 r := 0 86 for r < len(s) { 87 c := s[r] 88 if c == '\\' || c == '"' { 89 break 90 } 91 if c < utf8.RuneSelf { 92 r++ 93 continue 94 } 95 rr, size := utf8.DecodeRune(s[r:]) 96 if rr == utf8.RuneError && size == 1 { 97 break 98 } 99 r += size 100 } 101 if r == len(s) { 102 return s, true 103 } 104 105 b := make([]byte, len(s)+2*utf8.UTFMax) 106 w := copy(b, s[0:r]) 107 for r < len(s) { 108 // Out of room? Can only happen if s is full of 109 // malformed UTF-8 and we're replacing each 110 // byte with RuneError. 111 if w >= len(b)-2*utf8.UTFMax { 112 nb := make([]byte, (len(b)+utf8.UTFMax)*2) 113 copy(nb, b[0:w]) 114 b = nb 115 } 116 switch c := s[r]; { 117 case c == '\\': 118 r++ 119 if r >= len(s) { 120 return 121 } 122 switch s[r] { 123 default: 124 return 125 case '"', '\\', '/', '\'': 126 b[w] = s[r] 127 r++ 128 w++ 129 case 'b': 130 b[w] = '\b' 131 r++ 132 w++ 133 case 'f': 134 b[w] = '\f' 135 r++ 136 w++ 137 case 'n': 138 b[w] = '\n' 139 r++ 140 w++ 141 case 'r': 142 b[w] = '\r' 143 r++ 144 w++ 145 case 't': 146 b[w] = '\t' 147 r++ 148 w++ 149 case 'u': 150 r-- 151 rr := getu4(s[r:]) 152 if rr < 0 { 153 return 154 } 155 r += 6 156 w += utf8.EncodeRune(b[w:], rr) 157 } 158 159 // Quote is invalid 160 case c == '"': 161 return 162 163 // ASCII 164 case c < utf8.RuneSelf: 165 b[w] = c 166 r++ 167 w++ 168 169 // Coerce to well-formed UTF-8. 170 default: 171 rr, size := utf8.DecodeRune(s[r:]) 172 r += size 173 w += utf8.EncodeRune(b[w:], rr) 174 } 175 } 176 return b[0:w], true 177} 178