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.class2greylist;
18 
19 /**
20  * Utility class to simplify parsing of signatures.
21  */
22 public class StringCursor {
23 
24     private final String mString;
25     private int mCursor;
26 
StringCursor(String str)27     public StringCursor(String str) {
28         mString = str;
29         mCursor = 0;
30     }
31 
32     /**
33      * Position of cursor in string.
34      *
35      * @return Current position of cursor in string.
36      */
position()37     public int position() {
38         return mCursor;
39     }
40 
41     /**
42      * Peek current cursor position.
43      *
44      * @return The character at the current cursor position.
45      */
peek()46     public char peek() {
47         return mString.charAt(mCursor);
48     }
49 
50     /**
51      * Peek several characters at the current cursor position without moving the cursor.
52      *
53      * @param n The number of characters to peek.
54      * @return A string with x characters from the cursor position. If n is -1, return the whole
55      *        rest of the string.
56      */
peek(int n)57     public String peek(int n) throws StringCursorOutOfBoundsException {
58         if (n == -1) {
59             return mString.substring(mCursor);
60         }
61         if (n < 0 || (n + mCursor) >= mString.length()) {
62             throw new StringCursorOutOfBoundsException();
63         }
64         return mString.substring(mCursor, mCursor + n);
65     }
66 
67     /**
68      * Consume the character at the current cursor position and move the cursor forwards.
69      *
70      * @return The character at the current cursor position.
71      */
next()72     public char next() throws StringCursorOutOfBoundsException {
73         if (!hasNext()) {
74             throw new StringCursorOutOfBoundsException();
75         }
76         return mString.charAt(mCursor++);
77     }
78 
79     /**
80      * Consume several characters at the current cursor position and move the cursor further along.
81      *
82      * @param n The number of characters to consume.
83      * @return A string with x characters from the cursor position. If n is -1, return the whole
84      *         rest of the string.
85      */
next(int n)86     public String next(int n) throws StringCursorOutOfBoundsException {
87         if (n == -1) {
88             String restOfString = mString.substring(mCursor);
89             mCursor = mString.length();
90             return restOfString;
91         }
92         if (n < 0) {
93             throw new StringCursorOutOfBoundsException();
94         }
95         mCursor += n;
96         return mString.substring(mCursor - n, mCursor);
97     }
98 
99     /**
100      * Search for the first occurrence of a character beyond the current cursor position.
101      *
102      * @param c The character to search for.
103      * @return The offset of the first occurrence of c in the string beyond the cursor position.
104      * If the character does not exist, return -1.
105      */
find(char c)106     public int find(char c) {
107         int firstIndex = mString.indexOf(c, mCursor);
108         if (firstIndex == -1) {
109             return -1;
110         }
111         return firstIndex - mCursor;
112     }
113 
114     /**
115      * Check if cursor has reached end of string.
116      *
117      * @return Cursor has reached end of string.
118      */
hasNext()119     public boolean hasNext() {
120         return mCursor < mString.length();
121     }
122 
123     @Override
toString()124     public String toString() {
125         return mString.substring(mCursor);
126     }
127 
getOriginalString()128     public String getOriginalString() {
129         return mString;
130     }
131 }