Line data Source code
1 : // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 : // for details. All rights reserved. Use of this source code is governed by a 3 : // BSD-style license that can be found in the LICENSE file. 4 : 5 : import 'package:string_scanner/string_scanner.dart'; 6 : 7 : /// An HTTP token. 8 15 : final token = RegExp(r'[^()<>@,;:"\\/[\]?={} \t\x00-\x1F\x7F]+'); 9 : 10 : /// Linear whitespace. 11 15 : final _lws = RegExp(r'(?:\r\n)?[ \t]+'); 12 : 13 : /// A quoted string. 14 0 : final _quotedString = RegExp(r'"(?:[^"\x00-\x1F\x7F]|\\.)*"'); 15 : 16 : /// A quoted pair. 17 0 : final _quotedPair = RegExp(r'\\(.)'); 18 : 19 : /// A character that is *not* a valid HTTP token. 20 3 : final nonToken = RegExp(r'[()<>@,;:"\\/\[\]?={} \t\x00-\x1F\x7F]'); 21 : 22 : /// A regular expression matching any number of [_lws] productions in a row. 23 30 : final whitespace = RegExp('(?:${_lws.pattern})*'); 24 : 25 : /// Parses a list of elements, as in `1#element` in the HTTP spec. 26 : /// 27 : /// [scanner] is used to parse the elements, and [parseElement] is used to parse 28 : /// each one individually. The values returned by [parseElement] are collected 29 : /// in a list and returned. 30 : /// 31 : /// Once this is finished, [scanner] will be at the next non-LWS character in 32 : /// the string, or the end of the string. 33 0 : List<T> parseList<T>(StringScanner scanner, T Function() parseElement) { 34 0 : final result = <T>[]; 35 : 36 : // Consume initial empty values. 37 0 : while (scanner.scan(',')) { 38 0 : scanner.scan(whitespace); 39 : } 40 : 41 0 : result.add(parseElement()); 42 0 : scanner.scan(whitespace); 43 : 44 0 : while (scanner.scan(',')) { 45 0 : scanner.scan(whitespace); 46 : 47 : // Empty elements are allowed, but excluded from the results. 48 0 : if (scanner.matches(',') || scanner.isDone) continue; 49 : 50 0 : result.add(parseElement()); 51 0 : scanner.scan(whitespace); 52 : } 53 : 54 : return result; 55 : } 56 : 57 : /// Parses a single quoted string, and returns its contents. 58 : /// 59 : /// If [name] is passed, it's used to describe the expected value if it's not 60 : /// found. 61 0 : String expectQuotedString( 62 : StringScanner scanner, { 63 : String name = 'quoted string', 64 : }) { 65 0 : scanner.expect(_quotedString, name: name); 66 0 : final string = scanner.lastMatch![0]!; 67 : return string 68 0 : .substring(1, string.length - 1) 69 0 : .replaceAllMapped(_quotedPair, (match) => match[1]!); 70 : }