1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.icu.util.regex; 18 19 import libcore.api.IntraCoreApi; 20 import libcore.util.NativeAllocationRegistry; 21 22 /** 23 * Stores the states when matching an input text with a regular expression pattern 24 * {@link PatternNative}. 25 * 26 * @hide 27 */ 28 @IntraCoreApi 29 public class MatcherNative { 30 31 private static final NativeAllocationRegistry REGISTRY = NativeAllocationRegistry 32 .createMalloced(MatcherNative.class.getClassLoader(), getNativeFinalizer()); 33 34 private final PatternNative nativePattern; 35 @dalvik.annotation.optimization.ReachabilitySensitive 36 private final long address; 37 38 /** 39 * Create a {@link MatcherNative} instance from {@link PatternNative}. 40 * 41 * @hide 42 */ 43 @IntraCoreApi create(PatternNative pattern)44 public static MatcherNative create(PatternNative pattern) { 45 return new MatcherNative(pattern); 46 } 47 MatcherNative(PatternNative pattern)48 private MatcherNative(PatternNative pattern) { 49 nativePattern = pattern; 50 address = pattern.openMatcher(); 51 REGISTRY.registerNativeAllocation(this, address); 52 } 53 54 /** 55 * Returns the index of the named group. 56 * 57 * @param groupName the group name 58 * 59 * @hide 60 */ 61 @IntraCoreApi getMatchedGroupIndex(String groupName)62 public int getMatchedGroupIndex(String groupName) { 63 return nativePattern.getMatchedGroupIndex(groupName); 64 } 65 66 /** 67 * Attempts to match the input string starting from {@code startIndex}. 68 * 69 * @param offsets an output argument storing the starting and ending indices of the matched 70 * groups. This has to be pre-allocated with the size of 71 * ({@link #groupCount()} + 1) * 2. The elements at index 0 and 1 are the 72 * starting and ending indices of the 0th group and 0th group is the entire 73 * match. The index can be -1 when a match is found, but the group is not found. 74 * @return true if a match is found. 75 * 76 * 77 * @hide 78 */ 79 @IntraCoreApi find(int startIndex, int[] offsets)80 public boolean find(int startIndex, int[] offsets) { 81 return findImpl(address, startIndex, offsets); 82 } 83 84 /** 85 * Attempts to find the next match. 86 * 87 * @param offsets an output argument storing the starting and ending indices of the matched 88 * groups. This has to be pre-allocated with the size of 89 * ({@link #groupCount()} + 1) * 2. The elements at index 0 and 1 are the 90 * starting and ending indices of the 0th group and 0th group is the entire 91 * match. The index can be -1 when a match is found, but the group is not found. 92 * @return true if a match is found. 93 * 94 * 95 * @hide 96 */ 97 @IntraCoreApi findNext(int[] offsets)98 public boolean findNext(int[] offsets) { 99 return findNextImpl(address, offsets); 100 } 101 102 /** 103 * Returns the number of named-capturing groups provided in the pattern. 104 * 105 * @hide 106 */ 107 @IntraCoreApi groupCount()108 public int groupCount() { 109 return groupCountImpl(address); 110 } 111 112 /** 113 * Returns true if the matcher has hit the end of the input string in the last match. 114 * 115 * @hide 116 */ 117 @IntraCoreApi hitEnd()118 public boolean hitEnd() { 119 return hitEndImpl(address); 120 } 121 122 /** 123 * Attempts to match the prefix of the input string. 124 * 125 * @param offsets an output argument storing the starting and ending indices of the matched 126 * groups. This has to be pre-allocated with the size of 127 * ({@link #groupCount()} + 1) * 2. The elements at index 0 and 1 are the 128 * starting and ending indices of the 0th group and 0th group is the entire 129 * match. The index can be -1 when a match is found, but the group is not found. 130 * @return true if it matches the prefix of the input string. 131 * 132 * @hide 133 */ 134 @IntraCoreApi lookingAt(int[] offsets)135 public boolean lookingAt(int[] offsets) { 136 return lookingAtImpl(address, offsets); 137 } 138 139 /** 140 * Attempts to match the entire input string. 141 * 142 * 143 * @param offsets an output argument storing the starting and ending indices of the matched 144 * groups. This has to be pre-allocated with the size of 145 * ({@link #groupCount()} + 1) * 2. The elements at index 0 and 1 are the 146 * starting and ending indices of the 0th group and 0th group is the entire 147 * match. The index can be -1 when a match is found, but the group is not found. 148 * @return true if it matches the entire input string. 149 * 150 * @hide 151 */ 152 @IntraCoreApi matches(int[] offsets)153 public boolean matches(int[] offsets) { 154 return matchesImpl(address, offsets); 155 } 156 157 /** 158 * Returns true if the most recent match succeeded and additional input could cause it to fail. 159 * 160 * @hide 161 */ 162 @IntraCoreApi requireEnd()163 public boolean requireEnd() { 164 return requireEndImpl(address); 165 } 166 167 /** 168 * Set the input string. 169 * 170 * @param start the starting index at which to begin matching 171 * @param end the ending index at which to end matching 172 * 173 * @hide 174 */ 175 @IntraCoreApi setInput(String input, int start, int end)176 public void setInput(String input, int start, int end) { 177 setInputImpl(address, input, start, end); 178 } 179 180 /** 181 * Set whether using the anchoring bounds. 182 * 183 * Anchoring bounds allow the input string boundary to be matched by constructs ^ and $. 184 * 185 * @hide 186 */ 187 @IntraCoreApi useAnchoringBounds(boolean value)188 public void useAnchoringBounds(boolean value) { 189 useAnchoringBoundsImpl(address, value); 190 } 191 192 /** 193 * Set whether using transparent bounds. 194 * 195 * Transparent bounds makes the boundary of the input string transparent to the lookahead, 196 * lookbehind, and boundary constructs. 197 * 198 * @hide 199 */ 200 @IntraCoreApi useTransparentBounds(boolean value)201 public void useTransparentBounds(boolean value) { 202 useTransparentBoundsImpl(address, value); 203 } 204 findImpl(long addr, int startIndex, int[] offsets)205 private static native boolean findImpl(long addr, int startIndex, int[] offsets); findNextImpl(long addr, int[] offsets)206 private static native boolean findNextImpl(long addr, int[] offsets); groupCountImpl(long addr)207 private static native int groupCountImpl(long addr); hitEndImpl(long addr)208 private static native boolean hitEndImpl(long addr); lookingAtImpl(long addr, int[] offsets)209 private static native boolean lookingAtImpl(long addr, int[] offsets); matchesImpl(long addr, int[] offsets)210 private static native boolean matchesImpl(long addr, int[] offsets); requireEndImpl(long addr)211 private static native boolean requireEndImpl(long addr); setInputImpl(long addr, String input, int start, int end)212 private static native void setInputImpl(long addr, String input, int start, int end); useAnchoringBoundsImpl(long addr, boolean value)213 private static native void useAnchoringBoundsImpl(long addr, boolean value); useTransparentBoundsImpl(long addr, boolean value)214 private static native void useTransparentBoundsImpl(long addr, boolean value); 215 216 /** 217 * @return address of a native function of type <code>void f(void* nativePtr)</code> 218 * used to free this kind of native allocation 219 */ getNativeFinalizer()220 private static native long getNativeFinalizer(); 221 222 } 223