All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.github.dockerjava.core.GoLangFileMatch Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/**
 * Copyright (C) 2014 SignalFuse, Inc.
 */
package com.fitbur.github.dockerjava.core;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.fitbur.apache.com.fitburmons.lang.StringUtils;

/**
 * Implementation of golang's file.Match
 *
 * Match returns true if name matches the shell file name pattern. The pattern syntax is:
 *
 * 
 *  pattern:
 *          { term }
 *   term:
 *       '*'         matches any sequence of non-Separator characters
 *      '?'         matches any single non-Separator character
 *       '[' [ '^' ] { character-range } ']'
 *                  character class (must be non-empty)
 *       c           matches character c (c != '*', '?', '\\', '[')
 *       '\\' c      matches character c
 * 
 *   character-range:
 *       c           matches character c (c != '\\', '-', ']')
 *       '\\' c      matches character c
 *       lo '-' hi   matches character c for lo <= c <= hi
 * 
 *  Match requires pattern to match all of name, not just a substring.
 *  The only possible returned error is ErrBadPattern, when pattern
 *  is malformed.
 * 
 * On Windows, escaping is disabled. Instead, '\\' is treated as
 *  path separator.
 * 
* * @author tedo * */ public class GoLangFileMatch { public static final boolean IS_WINDOWS = File.separatorChar == '\\'; public static boolean match(List patterns, File file) { return !match(patterns, file.getPath()).isEmpty(); } public static boolean match(String pattern, File file) { return match(pattern, file.getPath()); } /** * Returns the matching patterns for the given string */ public static List match(List patterns, String name) { List matches = new ArrayList(); for (String pattern : patterns) { if (match(pattern, name)) { matches.add(pattern); } } return matches; } public static boolean match(String pattern, String name) { Pattern: while (!pattern.isEmpty()) { ScanResult scanResult = scanChunk(pattern); pattern = scanResult.pattern; if (scanResult.star && StringUtils.isEmpty(scanResult.chunk)) { // Trailing * matches rest of string unless it has a /. return name.indexOf(File.separatorChar) < 0; } // Look for match at current position. String matchResult = matchChunk(scanResult.chunk, name); // if we're the last chunk, make sure we've exhausted the name // otherwise we'll give a false result even if we could still match // using the star if (matchResult != null && (matchResult.isEmpty() || !pattern.isEmpty())) { name = matchResult; continue; } if (scanResult.star) { for (int i = 0; i < name.length() && name.charAt(i) != File.separatorChar; i++) { matchResult = matchChunk(scanResult.chunk, name.substring(i + 1)); if (matchResult != null) { // if we're the last chunk, make sure we exhausted the name if (pattern.isEmpty() && !matchResult.isEmpty()) { continue; } name = matchResult; continue Pattern; } } } return false; } return name.isEmpty(); } static ScanResult scanChunk(String pattern) { boolean star = false; if (!pattern.isEmpty() && pattern.charAt(0) == '*') { pattern = pattern.substring(1); star = true; } boolean inRange = false; int i; Scan: for (i = 0; i < pattern.length(); i++) { switch (pattern.charAt(i)) { case '\\': { if (!IS_WINDOWS && i + 1 < pattern.length()) { i++; } break; } case '[': inRange = true; break; case ']': inRange = false; break; case '*': if (!inRange) { break Scan; } } } return new ScanResult(star, pattern.substring(0, i), pattern.substring(i)); } static String matchChunk(String chunk, String s) { int chunkLength = chunk.length(); int chunkOffset = 0; int sLength = s.length(); int sOffset = 0; char r; while (chunkOffset < chunkLength) { if (sOffset == sLength) { return null; } switch (chunk.charAt(chunkOffset)) { case '[': r = s.charAt(sOffset); sOffset++; chunkOffset++; // We can't end right after '[', we're expecting at least // a closing bracket and possibly a caret. if (chunkOffset == chunkLength) { throw new GoLangFileMatchException(); } // possibly negated boolean negated = chunk.charAt(chunkOffset) == '^'; if (negated) { chunkOffset++; } // parse all ranges boolean match = false; int nrange = 0; while (true) { if (chunkOffset < chunkLength && chunk.charAt(chunkOffset) == ']' && nrange > 0) { chunkOffset++; break; } GetEscResult result = getEsc(chunk, chunkOffset, chunkLength); char lo = result.lo; char hi = lo; chunkOffset = result.chunkOffset; if (chunk.charAt(chunkOffset) == '-') { result = getEsc(chunk, ++chunkOffset, chunkLength); chunkOffset = result.chunkOffset; hi = result.lo; } if (lo <= r && r <= hi) { match = true; } nrange++; } if (match == negated) { return null; } break; case '?': if (s.charAt(sOffset) == File.separatorChar) { return null; } sOffset++; chunkOffset++; break; case '\\': if (!IS_WINDOWS) { chunkOffset++; if (chunkOffset == chunkLength) { throw new GoLangFileMatchException(); } } // fallthrough com.fitburfault: if (chunk.charAt(chunkOffset) != s.charAt(sOffset)) { return null; } sOffset++; chunkOffset++; } } return s.substring(sOffset); } static GetEscResult getEsc(String chunk, int chunkOffset, int chunkLength) { if (chunkOffset == chunkLength) { throw new GoLangFileMatchException(); } char r = chunk.charAt(chunkOffset); if (r == '-' || r == ']') { throw new GoLangFileMatchException(); } if (r == '\\' && !IS_WINDOWS) { chunkOffset++; if (chunkOffset == chunkLength) { throw new GoLangFileMatchException(); } } r = chunk.charAt(chunkOffset); chunkOffset++; if (chunkOffset == chunkLength) { throw new GoLangFileMatchException(); } return new GetEscResult(r, chunkOffset); } private static final class ScanResult { public boolean star; public String chunk; public String pattern; public ScanResult(boolean star, String chunk, String pattern) { this.star = star; this.chunk = chunk; this.pattern = pattern; } } private static final class GetEscResult { public char lo; public int chunkOffset; public GetEscResult(char lo, int chunkOffset) { this.lo = lo; this.chunkOffset = chunkOffset; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy