View Javadoc
1   /*
2    * Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.ignore.internal;
11  
12  import static org.eclipse.jgit.ignore.internal.Strings.getPathSeparator;
13  
14  /**
15   * Matcher built from patterns for file names (single path segments). This class
16   * is immutable and thread safe.
17   */
18  public class NameMatcher extends AbstractMatcher {
19  
20  	final boolean beginning;
21  
22  	final char slash;
23  
24  	final String subPattern;
25  
26  	NameMatcher(String pattern, Character pathSeparator, boolean dirOnly,
27  			boolean deleteBackslash) {
28  		super(pattern, dirOnly);
29  		slash = getPathSeparator(pathSeparator);
30  		if (deleteBackslash) {
31  			pattern = Strings.deleteBackslash(pattern);
32  		}
33  		beginning = pattern.length() == 0 ? false : pattern.charAt(0) == slash;
34  		if (!beginning) {
35  			this.subPattern = pattern;
36  		} else {
37  			this.subPattern = pattern.substring(1);
38  		}
39  	}
40  
41  	/** {@inheritDoc} */
42  	@Override
43  	public boolean matches(String path, boolean assumeDirectory,
44  			boolean pathMatch) {
45  		// A NameMatcher's pattern does not contain a slash.
46  		int start = 0;
47  		int stop = path.length();
48  		if (stop > 0 && path.charAt(0) == slash) {
49  			start++;
50  		}
51  		if (pathMatch) {
52  			// Can match only after the last slash
53  			int lastSlash = path.lastIndexOf(slash, stop - 1);
54  			if (lastSlash == stop - 1) {
55  				// Skip trailing slash
56  				lastSlash = path.lastIndexOf(slash, lastSlash - 1);
57  				stop--;
58  			}
59  			boolean match;
60  			if (lastSlash < start) {
61  				match = matches(path, start, stop);
62  			} else {
63  				// Can't match if the path contains a slash if the pattern is
64  				// anchored at the beginning
65  				match = !beginning
66  						&& matches(path, lastSlash + 1, stop);
67  			}
68  			if (match && dirOnly) {
69  				match = assumeDirectory;
70  			}
71  			return match;
72  		}
73  		while (start < stop) {
74  			int end = path.indexOf(slash, start);
75  			if (end < 0) {
76  				end = stop;
77  			}
78  			if (end > start && matches(path, start, end)) {
79  				// make sure the directory matches: either if we are done with
80  				// segment and there is next one, or if the directory is assumed
81  				return !dirOnly || assumeDirectory || end < stop;
82  			}
83  			if (beginning) {
84  				break;
85  			}
86  			start = end + 1;
87  		}
88  		return false;
89  	}
90  
91  	/** {@inheritDoc} */
92  	@Override
93  	public boolean matches(String segment, int startIncl, int endExcl) {
94  		// faster local access, same as in string.indexOf()
95  		String s = subPattern;
96  		int length = s.length();
97  		if (length != (endExcl - startIncl)) {
98  			return false;
99  		}
100 		for (int i = 0; i < length; i++) {
101 			char c1 = s.charAt(i);
102 			char c2 = segment.charAt(i + startIncl);
103 			if (c1 != c2) {
104 				return false;
105 			}
106 		}
107 		return true;
108 	}
109 
110 }