1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution,
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: WCMatcher.java,v 1.1.1.1 2004/05/09 16:57:56 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.util;
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2002
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectabstract class WCMatcher
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static WCMatcher compile (final String pattern)
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (pattern == null) throw new IllegalArgumentException ("null input: pattern");
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final char [] chars = pattern.toCharArray (); // is this faster than using charAt()?
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final int charsLength = chars.length;
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (charsLength == 0)
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return EMPTY_MATCHER; // TODO: should be an EMPTY_MATCHER
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int patternLength = 0, starCount = 0, questionCount = 0;
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            boolean star = false;
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int c = 0; c < charsLength; ++ c)
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final char ch = chars [c];
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (ch == '*')
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (! star)
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        star = true;
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        ++ starCount;
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        chars [patternLength ++] = '*';
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    star = false;
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (ch == '?') ++ questionCount;
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    chars [patternLength ++] = ch;
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // [assertion: patternLength > 0]
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((starCount == 1) && (questionCount == 0))
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (patternLength == 1)
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    return ALL_MATCHER;
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else if (chars [0] == '*')
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    return new EndsWithMatcher (chars, patternLength);
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else if (chars [patternLength - 1] == '*')
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    return new StartsWithMatcher (chars, patternLength);
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return new PatternMatcher (chars, patternLength);
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public abstract boolean matches (String s);
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public abstract boolean matches (char [] chars);
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//    private boolean matches (int pi, int si, final char [] string)
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//    {
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        System.out.println ("pi = " + pi + ", si = " + si);
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        if (pi == m_pattern.length)
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            return si == string.length;
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        else
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        {
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            switch (m_pattern [pi])
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            {
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                case '?':
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                {
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    return (si < string.length) && matches (pi + 1, si + 1, string);
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                }
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                case '*':
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                {
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    return matches (pi + 1, si, string) || ((si < string.length) && matches (pi, si + 1, string));
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                }
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                default:
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                {
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                    return (si < string.length) && (m_pattern [pi] == string [si]) && matches (pi + 1, si + 1, string);
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//                }
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//            } // end of switch
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//        }
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//    }
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    WCMatcher () {}
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class AllMatcher extends WCMatcher
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final String s)
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (s == null) throw new IllegalArgumentException  ("null input: s");
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return true;
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final char [] chars)
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (chars == null) throw new IllegalArgumentException  ("null input: chars");
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return true;
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class EmptyMatcher extends WCMatcher
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final String s)
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (s == null) throw new IllegalArgumentException  ("null input: s");
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return false;
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final char [] chars)
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (chars == null) throw new IllegalArgumentException  ("null input: chars");
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return chars.length == 0;
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class StartsWithMatcher extends WCMatcher
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final String s)
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (s == null) throw new IllegalArgumentException  ("null input: s");
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return s.startsWith (m_prefix);
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final char [] chars)
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (chars == null) throw new IllegalArgumentException  ("null input: chars");
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final char [] prefixChars = m_prefixChars;
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int prefixLength = prefixChars.length - 1;
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (chars.length < prefixLength) return false;
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int c = 0; c < prefixLength; ++ c)
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (chars [c] != prefixChars [c]) return false;
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return true;
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        StartsWithMatcher (final char [] pattern, final int patternLength)
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_prefixChars = pattern;
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_prefix = new String (pattern, 0, patternLength - 1);
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final char [] m_prefixChars;
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final String m_prefix;
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class EndsWithMatcher extends WCMatcher
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final String s)
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (s == null) throw new IllegalArgumentException  ("null input: s");
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return s.endsWith (m_suffix);
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final char [] chars)
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (chars == null) throw new IllegalArgumentException  ("null input: chars");
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final char [] suffixChars = m_suffixChars;
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int suffixLength = suffixChars.length - 1;
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int charsLength = chars.length;
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (charsLength < suffixLength) return false;
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int c = 0; c < suffixLength; ++ c)
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (chars [charsLength - 1 - c] != suffixChars [suffixLength - c]) return false;
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return true;
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        EndsWithMatcher (final char [] pattern, final int patternLength)
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_suffixChars = pattern;
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_suffix = new String (pattern, 1, patternLength - 1);
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final char [] m_suffixChars;
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final String m_suffix;
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class PatternMatcher extends WCMatcher
232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final String s)
234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (s == null) throw new IllegalArgumentException  ("null input: s");
236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final char [] string = s.toCharArray (); // implies an array copy; is this faster than using charAt()?
238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int stringLength = string.length;
239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final char [] pattern = m_pattern;
241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int patternLength = m_patternLength;
242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // [assertion: patternLength > 0]
244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int si = 0, pi = 0;
246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            boolean star = false;
247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      next: while (true)
250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                //System.out.println ("pi = " + pi + ", si = " + si);
252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                int i = 0;
254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for ( ; pi + i < patternLength; ++ i)
255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final char patternChar = pattern [pi + i];
257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (patternChar == '*')
259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        si += i;
261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        pi += (i + 1);
262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        star = true;
264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        continue next;
265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final int si_i = si + i;
268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (si_i == stringLength) return false;
270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (patternChar != string [si_i])
272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (patternChar == '?') continue;
274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (! star) return false;
276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        ++ si;
277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        continue next;
279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                } // end of for
282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (si + i == stringLength) return true;
284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (! star) return false;
286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                ++ si;
287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // [continue next;]
289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public final boolean matches (final char [] string)
294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (string == null) throw new IllegalArgumentException  ("null input: string");
296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int stringLength = string.length;
298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final char [] pattern = m_pattern;
300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int patternLength = m_patternLength;
301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // [assertion: patternLength > 0]
303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int si = 0, pi = 0;
305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            boolean star = false;
306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project      next: while (true)
309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                //System.out.println ("pi = " + pi + ", si = " + si);
311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                int i = 0;
313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for ( ; pi + i < patternLength; ++ i)
314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final char patternChar = pattern [pi + i];
316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (patternChar == '*')
318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        si += i;
320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        pi += (i + 1);
321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        star = true;
323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        continue next;
324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final int si_i = si + i;
327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (si_i == stringLength) return false;
329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (patternChar != string [si_i])
331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (patternChar == '?') continue;
333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (! star) return false;
335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        ++ si;
336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        continue next;
338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                } // end of for
341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (si + i == stringLength) return true;
343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (! star) return false;
345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                ++ si;
346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // [continue next;]
348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        PatternMatcher (final char [] pattern, final int patternLength)
352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_pattern = pattern;
354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_patternLength = patternLength;
355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final char [] m_pattern;
359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final int m_patternLength;
360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final WCMatcher ALL_MATCHER = new AllMatcher ();
365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final WCMatcher EMPTY_MATCHER = new EmptyMatcher ();
366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------