parseOpts parses the options from name and adds them to the values. The parsing code is based on conninfo_parse from libpq's fe-connect.c
(name string, o values)
| 163 | // |
| 164 | // The parsing code is based on conninfo_parse from libpq's fe-connect.c |
| 165 | func parseOpts(name string, o values) error { |
| 166 | s := newScanner(name) |
| 167 | |
| 168 | for { |
| 169 | var ( |
| 170 | keyRunes, valRunes []rune |
| 171 | r rune |
| 172 | ok bool |
| 173 | ) |
| 174 | |
| 175 | if r, ok = s.SkipSpaces(); !ok { |
| 176 | break |
| 177 | } |
| 178 | |
| 179 | // Scan the key |
| 180 | for !unicode.IsSpace(r) && r != '=' { |
| 181 | keyRunes = append(keyRunes, r) |
| 182 | if r, ok = s.Next(); !ok { |
| 183 | break |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | // Skip any whitespace if we're not at the = yet |
| 188 | if r != '=' { |
| 189 | r, ok = s.SkipSpaces() |
| 190 | } |
| 191 | |
| 192 | // The current character should be = |
| 193 | if r != '=' || !ok { |
| 194 | return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes)) |
| 195 | } |
| 196 | |
| 197 | // Skip any whitespace after the = |
| 198 | if r, ok = s.SkipSpaces(); !ok { |
| 199 | // If we reach the end here, the last value is just an empty string as per libpq. |
| 200 | o.Set(string(keyRunes), "") |
| 201 | break |
| 202 | } |
| 203 | |
| 204 | if r != '\'' { |
| 205 | for !unicode.IsSpace(r) { |
| 206 | if r == '\\' { |
| 207 | if r, ok = s.Next(); !ok { |
| 208 | return fmt.Errorf(`missing character after backslash`) |
| 209 | } |
| 210 | } |
| 211 | valRunes = append(valRunes, r) |
| 212 | |
| 213 | if r, ok = s.Next(); !ok { |
| 214 | break |
| 215 | } |
| 216 | } |
| 217 | } else { |
| 218 | quote: |
| 219 | for { |
| 220 | if r, ok = s.Next(); !ok { |
| 221 | return fmt.Errorf(`unterminated quoted string literal in connection string`) |
| 222 | } |
no test coverage detected
searching dependent graphs…