View Javadoc
1   /*
2     (C) Copyright IBM Corp. 2006, 2009
3   
4     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
5     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
6     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7   
8     You can obtain a current copy of the Eclipse Public License from
9     http://www.opensource.org/licenses/eclipse-1.0.php
10  
11    @author : Endre Bak, ebak@de.ibm.com
12   * 
13   * Flag       Date        Prog         Description
14   * -------------------------------------------------------------------------------
15   * 1565892    2006-11-05  ebak         Make SBLIM client JSR48 compliant
16   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
17   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
18   * 2763216    2009-04-14  blaschke-oss Code cleanup: visible spelling/grammar errors
19   */
20  
21  package org.metricshub.wbem.sblim.cimclient.internal.uri;
22  
23  /*-
24   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
25   * WBEM Java Client
26   * ჻჻჻჻჻჻
27   * Copyright 2023 - 2025 MetricsHub
28   * ჻჻჻჻჻჻
29   * Licensed under the Apache License, Version 2.0 (the "License");
30   * you may not use this file except in compliance with the License.
31   * You may obtain a copy of the License at
32   *
33   *      http://www.apache.org/licenses/LICENSE-2.0
34   *
35   * Unless required by applicable law or agreed to in writing, software
36   * distributed under the License is distributed on an "AS IS" BASIS,
37   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38   * See the License for the specific language governing permissions and
39   * limitations under the License.
40   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
41   */
42  
43  import java.util.regex.Matcher;
44  import java.util.regex.Pattern;
45  
46  /**
47   * Class URIString is responsible for wrapping the WBEM-URI string. It has
48   * methods which help in parsing.
49   */
50  public class URIString implements CharSequence {
51  
52  	/**
53  	 * Ctor.
54  	 *
55  	 * @param pCharArray
56  	 * @param pStart
57  	 * @param pEnd
58  	 */
59  	public URIString(char[] pCharArray, int pStart, int pEnd) {
60  		if (pEnd < pStart) throw new IndexOutOfBoundsException("end:" + pEnd + " < start:" + pStart);
61  		if (pEnd > pCharArray.length) throw new IndexOutOfBoundsException(
62  			"charArray.length:" +
63  			pCharArray.length +
64  			", start:" +
65  			pStart +
66  			", end:" +
67  			pEnd +
68  			"\n" +
69  			"end:" +
70  			pEnd +
71  			" > charArray.length:" +
72  			pCharArray.length
73  		);
74  		this.iCA = pCharArray;
75  		this.iInitStart = this.iStart = pStart;
76  		this.iEnd = pEnd;
77  	}
78  
79  	/**
80  	 * Ctor.
81  	 *
82  	 * @param pCharArray
83  	 */
84  	public URIString(char[] pCharArray) {
85  		this(pCharArray, 0, pCharArray.length);
86  	}
87  
88  	/**
89  	 * Ctor.
90  	 *
91  	 * @param pStr
92  	 */
93  	public URIString(String pStr) {
94  		this(pStr.toCharArray());
95  	}
96  
97  	/**
98  	 * Ctor.
99  	 *
100 	 * @param pUriStr
101 	 */
102 	public URIString(URIString pUriStr) {
103 		set(pUriStr);
104 	}
105 
106 	/**
107 	 * set
108 	 *
109 	 * @param pUriStr
110 	 */
111 	public void set(URIString pUriStr) {
112 		this.iCA = pUriStr.iCA;
113 		this.iStart = pUriStr.iStart;
114 		this.iEnd = pUriStr.iEnd;
115 	}
116 
117 	/**
118 	 * deepCopy
119 	 *
120 	 * @return <code>URIString</code> instance
121 	 */
122 	public URIString deepCopy() {
123 		return new URIString(this);
124 	}
125 
126 	/**
127 	 * find
128 	 *
129 	 * @param pChar
130 	 * @return Position of <code>pChar</code> or -1 if not found.
131 	 */
132 	public int find(char pChar) {
133 		for (int i = 0; i < length(); i++) if (charAt(i) == pChar) return i;
134 		return -1;
135 	}
136 
137 	/**
138 	 * @see java.lang.CharSequence#charAt(int)
139 	 */
140 	public char charAt(int pIdx) {
141 		return this.iCA[this.iStart + pIdx];
142 	}
143 
144 	/**
145 	 * @see java.lang.CharSequence#length()
146 	 */
147 	public int length() {
148 		return this.iEnd - this.iStart;
149 	}
150 
151 	/**
152 	 * @see java.lang.CharSequence#subSequence(int, int)
153 	 */
154 	public CharSequence subSequence(int pStart, int pEnd) {
155 		return new URIString(this.iCA, this.iStart + pStart, this.iStart + pEnd);
156 	}
157 
158 	/**
159 	 * @see java.lang.Object#toString()
160 	 */
161 	@Override
162 	public String toString() {
163 		return new String(this.iCA, this.iStart, length());
164 	}
165 
166 	/**
167 	 * toInitString
168 	 *
169 	 * @return The String which was used for initializing this instance.
170 	 */
171 	public String toInitString() {
172 		return new String(this.iCA, this.iInitStart, this.iEnd - this.iInitStart);
173 	}
174 
175 	/**
176 	 * getPos
177 	 *
178 	 * @return The position of parsing.
179 	 */
180 	public int getPos() {
181 		return this.iStart - this.iInitStart;
182 	}
183 
184 	/**
185 	 * markPosition
186 	 *
187 	 * @return a String which marks the position of parsing.
188 	 */
189 	public String markPosition() {
190 		return markPosition(getPos());
191 	}
192 
193 	/**
194 	 * markPosition
195 	 *
196 	 * @param pPos
197 	 * @return a String which marks position pPos.
198 	 */
199 	public String markPosition(int pPos) {
200 		StringBuffer buf = new StringBuffer();
201 		buf.append(toInitString() + '\n');
202 		for (int i = 0; i < pPos; i++) buf.append(' ');
203 		buf.append("^\n");
204 		return buf.toString();
205 	}
206 
207 	/**
208 	 * Returns a new string that is a substring of this string. The substring
209 	 * begins at the specified pBeginIdx and extends to the character at index
210 	 * pEndIdx - 1. Thus the length of the substring is pEndIdx-pBeginIdx.
211 	 *
212 	 * @param pBeginIdx
213 	 * @param pEndIdx
214 	 * @return String
215 	 */
216 	public String substring(int pBeginIdx, int pEndIdx) {
217 		return new String(this.iCA, this.iStart + pBeginIdx, pEndIdx - pBeginIdx);
218 	}
219 
220 	/**
221 	 * startsWith
222 	 *
223 	 * @param pC
224 	 * @return <code>true</code> if the first character is <code>pC</code>.
225 	 */
226 	public boolean startsWith(char pC) {
227 		if (length() == 0) return false;
228 		return charAt(0) == pC;
229 	}
230 
231 	/**
232 	 * Cuts out the first character.
233 	 */
234 	public void cutStarting() {
235 		cutStarting(1);
236 	}
237 
238 	/**
239 	 * Cuts out the first character if it is <code>pC</code>.
240 	 *
241 	 * @param pC
242 	 * @return <code>true</code> if cut is done.
243 	 */
244 	public boolean cutStarting(char pC) {
245 		if (startsWith(pC)) {
246 			++this.iStart;
247 			return true;
248 		}
249 		return false;
250 	}
251 
252 	/**
253 	 * Cuts out <code>pSeq</code> from the beginning if it is there.
254 	 *
255 	 * @param pSeq
256 	 * @return <code>true</code> if cut is done.
257 	 */
258 	public boolean cutStarting(CharSequence pSeq) {
259 		if (pSeq.length() > length()) return false;
260 		for (int i = 0; i < pSeq.length(); i++) if (charAt(i) != pSeq.charAt(i)) return false;
261 		this.iStart += pSeq.length();
262 		return true;
263 	}
264 
265 	/**
266 	 * Cuts out <code>pStr</code> from the beginning if it is there.
267 	 *
268 	 * @param pStr
269 	 * @param pIgnoreCase
270 	 * @return <code>true</code> if cut is done.
271 	 */
272 	public boolean cutStarting(String pStr, boolean pIgnoreCase) {
273 		if (pStr.length() > length()) return false;
274 		String subStr = substring(0, pStr.length());
275 		if (pIgnoreCase ? pStr.equalsIgnoreCase(subStr) : pStr.equals(subStr)) {
276 			this.iStart += pStr.length();
277 			return true;
278 		}
279 		return false;
280 	}
281 
282 	/**
283 	 * Cuts out pChars pieces of characters from the beginning.
284 	 *
285 	 * @param pChars
286 	 */
287 	public void cutStarting(int pChars) {
288 		if (pChars > length()) throw new IndexOutOfBoundsException("chars:" + pChars + " > length()" + length());
289 		this.iStart += pChars;
290 	}
291 
292 	/**
293 	 * Removes the beginning of the string till the first occurrence of pChar or
294 	 * removes the whole string if it doesn't contain pChar and pMustFound is
295 	 * false.
296 	 *
297 	 * @param pChar
298 	 * @param pRemoveChar
299 	 *            if <code>true pChar</code> will be removed too
300 	 * @param pMustFound
301 	 * @return the removed substring or <code>null</code> if <code>pChar</code>
302 	 *         not found and <code>pMustFound</code> is <code>true</code>
303 	 */
304 	public String removeTill(char pChar, boolean pRemoveChar, boolean pMustFound) {
305 		int pos = find(pChar);
306 		if (pos < 0) {
307 			if (pMustFound) return null;
308 			pos = length();
309 			pRemoveChar = false;
310 		}
311 		String strVal = substring(0, pos);
312 		cutStarting(pRemoveChar ? pos + 1 : pos);
313 		return strVal;
314 	}
315 
316 	/**
317 	 * removeTill(pChar, pRemoveChar, false);
318 	 *
319 	 * @param pChar
320 	 * @param pRemoveChar
321 	 * @return String
322 	 * @see #removeTill(char, boolean, boolean)
323 	 */
324 	public String removeTill(char pChar, boolean pRemoveChar) {
325 		return removeTill(pChar, pRemoveChar, false);
326 	}
327 
328 	/**
329 	 * removeTill(pChar, false, false);
330 	 *
331 	 * @param pChar
332 	 * @return String
333 	 * @see #removeTill(char, boolean, boolean)
334 	 */
335 	public String removeTill(char pChar) {
336 		return removeTill(pChar, false);
337 	}
338 
339 	/**
340 	 * Matches pattern <code>pPat</code> and cuts out the beginning till the end
341 	 * of matcher group <code>pGroup</code>.
342 	 *
343 	 * @param pPat
344 	 * @param pGroup
345 	 * @return <code>true</code> if pattern is matched and cut was done.
346 	 */
347 	public boolean matchAndCut(Pattern pPat, int pGroup) {
348 		this.iM = pPat.matcher(new URIString(this));
349 		if (this.iM.matches()) {
350 			this.iStart += this.iM.end(pGroup);
351 			return true;
352 		}
353 		return false;
354 	}
355 
356 	/**
357 	 * @param pI
358 	 * @return pI'th matcher group
359 	 */
360 	public String group(int pI) {
361 		return this.iM.group(pI);
362 	}
363 
364 	private char[] iCA;
365 
366 	private int iInitStart, iStart, iEnd;
367 
368 	private Matcher iM;
369 }