Line data Source code
1 : // Copyright (c) 2014, 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 'core_matchers.dart';
6 : import 'interfaces.dart';
7 :
8 : typedef bool _Predicate<T>(T value);
9 :
10 : /// A [Map] between whitespace characters and their escape sequences.
11 : const _escapeMap = const {
12 : '\n': r'\n',
13 : '\r': r'\r',
14 : '\f': r'\f',
15 : '\b': r'\b',
16 : '\t': r'\t',
17 : '\v': r'\v',
18 : '\x7F': r'\x7F', // delete
19 : };
20 :
21 : /// A [RegExp] that matches whitespace characters that should be escaped.
22 : final _escapeRegExp = new RegExp(
23 : "[\\x00-\\x07\\x0E-\\x1F${_escapeMap.keys.map(_getHexLiteral).join()}]");
24 :
25 : /// Useful utility for nesting match states.
26 : void addStateInfo(Map matchState, Map values) {
27 1 : var innerState = new Map.from(matchState);
28 1 : matchState.clear();
29 1 : matchState['state'] = innerState;
30 1 : matchState.addAll(values);
31 : }
32 :
33 : /// Takes an argument and returns an equivalent [Matcher].
34 : ///
35 : /// If the argument is already a matcher this does nothing,
36 : /// else if the argument is a function, it generates a predicate
37 : /// function matcher, else it generates an equals matcher.
38 : Matcher wrapMatcher(x) {
39 5 : if (x is Matcher) {
40 : return x;
41 1 : } else if (x is _Predicate<Object>) {
42 : // x is already a predicate that can handle anything
43 0 : return predicate(x);
44 1 : } else if (x is _Predicate<Null>) {
45 : // x is a unary predicate, but expects a specific type
46 : // so wrap it.
47 0 : return predicate((a) => (x as dynamic)(a));
48 : } else {
49 1 : return equals(x);
50 : }
51 : }
52 :
53 : /// Returns [str] with all whitespace characters represented as their escape
54 : /// sequences.
55 : ///
56 : /// Backslash characters are escaped as `\\`
57 : String escape(String str) {
58 0 : str = str.replaceAll('\\', r'\\');
59 0 : return str.replaceAllMapped(_escapeRegExp, (match) {
60 0 : var mapped = _escapeMap[match[0]];
61 : if (mapped != null) return mapped;
62 0 : return _getHexLiteral(match[0]);
63 : });
64 : }
65 :
66 : /// Given single-character string, return the hex-escaped equivalent.
67 : String _getHexLiteral(String input) {
68 0 : int rune = input.runes.single;
69 0 : return r'\x' + rune.toRadixString(16).toUpperCase().padLeft(2, '0');
70 : }
|