| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:string_scanner/string_scanner.dart'; | |
| /// An HTTP token. | |
| final token = RegExp(r'[^()<>@,;:"\\/[\]?={} \t\x00-\x1F\x7F]+'); | |
| /// Linear whitespace. | |
| final _lws = RegExp(r'(?:\r\n)?[ \t]+'); | |
| /// A quoted string. | |
| /// | |
| /// [RFC-2616 2.2](https://datatracker.ietf.org/doc/html/rfc2616#section-2.2) | |
| /// defines the `quoted-string` production. This expression is identical to | |
| /// the RFC definition expect that, in this regex, `qdtext` is not allowed to | |
| /// contain `"\"`. | |
| final _quotedString = RegExp(r'"(?:[^"\x00-\x1F\x7F\\]|\\.)*"'); | |
| /// A quoted pair. | |
| final _quotedPair = RegExp(r'\\(.)'); | |
| /// A character that is *not* a valid HTTP token. | |
| final nonToken = RegExp(r'[()<>@,;:"\\/\[\]?={} \t\x00-\x1F\x7F]'); | |
| /// A regular expression matching any number of [_lws] productions in a row. | |
| final whitespace = RegExp('(?:${_lws.pattern})*'); | |
| /// Parses a list of elements, as in `1#element` in the HTTP spec. | |
| /// | |
| /// [scanner] is used to parse the elements, and [parseElement] is used to parse | |
| /// each one individually. The values returned by [parseElement] are collected | |
| /// in a list and returned. | |
| /// | |
| /// Once this is finished, [scanner] will be at the next non-LWS character in | |
| /// the string, or the end of the string. | |
| List<T> parseList<T>(StringScanner scanner, T Function() parseElement) { | |
| final result = <T>[]; | |
| // Consume initial empty values. | |
| while (scanner.scan(',')) { | |
| scanner.scan(whitespace); | |
| } | |
| result.add(parseElement()); | |
| scanner.scan(whitespace); | |
| while (scanner.scan(',')) { | |
| scanner.scan(whitespace); | |
| // Empty elements are allowed, but excluded from the results. | |
| if (scanner.matches(',') || scanner.isDone) continue; | |
| result.add(parseElement()); | |
| scanner.scan(whitespace); | |
| } | |
| return result; | |
| } | |
| /// Parses a double quoted string, and returns its contents. | |
| /// | |
| /// If [name] is passed, it's used to describe the expected value if it's not | |
| /// found. | |
| String expectQuotedString( | |
| StringScanner scanner, { | |
| String name = 'quoted string', | |
| }) { | |
| scanner.expect(_quotedString, name: name); | |
| final string = scanner.lastMatch![0]!; | |
| return string | |
| .substring(1, string.length - 1) | |
| .replaceAllMapped(_quotedPair, (match) => match[1]!); | |
| } |