001package Torello.Java; 002 003import java.util.function.Consumer; 004import java.util.function.Predicate; 005import java.util.Vector; 006 007import Torello.JavaDoc.StaticFunctional; 008import Torello.JavaDoc.Excuse; 009 010/** 011 * Class String-Compare provides an exhaustive-combinatoric suite of methods that extend the 012 * basic Java <CODE>String</CODE> methods <CODE>equals, contains, startsWith</CODE> and 013 * <CODE>endsWith</CODE>. 014 * 015 * <EMBED CLASS='external-html' DATA-FILE-ID=STR_CMPR> 016 */ 017@StaticFunctional(Excused={"DEBUG", "DEBUG_LOG"}, Excuses={Excuse.DEBUGGING, Excuse.DEBUGGING}) 018public class StrCmpr 019{ 020 private StrCmpr() { } 021 022 /** 023 * Utility field. You may choose to set this variable to true, and the following 024 * {@code String} commands will print to an internally stored {@code Consumer<String> DEBUG_LOG} 025 * class that may be set. This is generally a very minor drain on code-efficiency. When this 026 * flag is set to {@code FALSE}, a short {@code if-statement evaluation} <I>still occurs even 027 * when the flag is false</I> on each occasion that the string-comparison loops identify and 028 * return a match. This is very minor performance loss, and does provide quite a lot of help 029 * to those trying to identify difficult to notice problems with partial-{@code String} 030 * comparisons. 031 * 032 * <BR /><BR /><B CLASS=JDDescLabel>Required Setting:</B> 033 * 034 * <BR />In order to use this minor Debugging Feature, it is necessary to provide a 035 * {@code Consumer<String>} to public field {@link #DEBUG_LOG}! This field is a {@code public} 036 * and {@code static} field, which will be used by any invocation of the methods in this class. 037 * This {@code String}-consumer may do anything you would like it to do with the provided 038 * Debug-{@code String} data. 039 * 040 * <BR /><BR /><B CLASS=JDDescLabel>String-Format:</B> 041 * 042 * <BR />The {@code String} that is ultimately sent to the {@code Consumer<String>} you provide 043 * will be formatted, as below, in the following Code-Snippet: 044 * 045 * <BR /><DIV CLASS=SNIP>{@code 046 * private static void PRNT(String methodName, String srcStr, String compareStr) 047 * { DEBUG_LOG.accept(methodName + "-MATCH[" + srcStr + ", " + compareStr + "] "); } 048 * }</DIV> 049 * 050 * <BR /><BR />Generally, you would assign a writer that looks like something the Lambda-Target 051 * / Function-Pointer assignment in the snippet below: 052 * 053 * <BR /><DIV CLASS=SNIP>{@code 054 * StrCmpr.DEBUG_LOG = (String logInfoStr) -> System.out.println(logInfoStr); 055 * }</DIV> 056 * 057 * <BR /><BR />Finally, if you are using this field, please note that any of the methods whose 058 * name ends with the phrase "IgnoreCase" <I>will not print to the {@link #DEBUG_LOG}</I>. 059 * This is primarily because these are all <I>single-argument comparisons</I>, and logging 060 * would be of only minor benefit. 061 * 062 * <BR /><BR />The primary value of a debug-log is the ability to identify whether / when a 063 * particular substring from a list of substrings actually matched. 064 */ 065 public static boolean DEBUG = false; 066 067 /** 068 * This object reference <I><B>cannot remain null when the field {@link #DEBUG} is set to 069 * {@code TRUE}</B></I>. If you have turned {@link #DEBUG} on (by setting the field to 070 * {@code TRUE}), and this is null, then a {@code NullPointerException} will be thrown on the 071 * very next invocation of any of the methods in this class. 072 * 073 * <BR /><BR /><B CLASS=JDDescLabel>DEBUG_LOG is not Thread-Safe:</B> 074 * 075 * <BR />No attempt has been made to ensure that this debugging "feature" will operate 076 * perfectly in a multi-threaded environment. The two reasons for this are: 077 * 078 * <BR /><BR /><OL CLASS=JDOL> 079 * <LI> The primary purpose of this LOG is for debugging code, not putting details about 080 * string-match information into an 'on-line' or production environment. 081 * <BR /><BR /> 082 * </LI> 083 * 084 * <LI> This is a best-efforts string-comparison package that would sacrifice quite a bit of its 085 * utility if it were expected to maintain multiple instances of this class just to have 086 * {@code StrCmpr} debug operations work in multiple-threads. Code readability necessitates 087 * keeping this a class with only <B><I>static methods.</I></B> 088 * <BR /><BR /> 089 * </LI> 090 * 091 * <LI> Two threads making calls to this class {@code StrCmpr} might see log-writes that, sadly, 092 * look like they 'interlaced' (crashed), but even when this occasions, reading the log 093 * wouldn't be that difficult anyway. 094 * </LI> 095 * </OL> 096 */ 097 public static Consumer<String> DEBUG_LOG = null; 098 099 private static void PRNT(String methodName, String srcStr, String compareStr) 100 { DEBUG_LOG.accept(methodName + srcStr + ", " + compareStr + "] "); } 101 102 /** 103 * This performs the internal AND. It expects a comparison {@code Predicate} in order for the 104 * comparison to work. 105 * @param methodName If printing-debug information is expected, by the DEBUG global-variable, 106 * this {@code String} is used. 107 * @param srcStr This is the same source-string parameter from all the methods in this class. 108 * @param compareStr This is the same var-args string array from all the methods in this class. 109 * @param pred This is the comparison {@code Predicate} provided by the methods in this class 110 * that call this method. 111 * @return The AND of these {@code String's}, using the provided {@code Predicate}. 112 * @throws StrCmprException This exception shall throw if there are any invalid 113 * {@code String's} in the compare-string parameter array. 114 * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that 115 * would cause this exception to throw should remind the reader that <I><B>each and every 116 * method here</I></B> will throw exception 'StrCmprException' if invalid input has been 117 * passed to the "Compare String" Variable-Arguments {@code String...} Parameter. 118 */ 119 protected static boolean AND 120 (String methodName, String srcStr, String[] compareStr, Predicate<String> pred) 121 { 122 StrCmprException.check(compareStr); 123 124 for (String cmp: compareStr) 125 126 if (! pred.test(cmp)) 127 { 128 if (DEBUG) PRNT(methodName + "-MATCHFAIL", srcStr, cmp); 129 return false; 130 } 131 132 return true; 133 } 134 135 /** 136 * This performs the internal NAND. It expects a comparison {@code Predicate} in order for the 137 * comparison to work. 138 * @param methodName If printing-debug information is expected, by the DEBUG global-variable, 139 * this {@code String} is used. 140 * @param srcStr This is the same source-string parameter from all the methods in this class. 141 * @param compareStr This is the same var-args string array from all the methods in this class. 142 * @param pred This is the comparison {@code Predicate} provided by the methods in this class 143 * that call this method. 144 * @return The NAND of these {@code String's}, using the provided {@code Predicate}. 145 * @throws StrCmprException This exception shall throw if there are any invalid 146 * {@code String's} in the compare-string parameter array. 147 * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that 148 * would cause this exception to throw should remind the reader that <I><B>each and every 149 * method here</I></B> will throw exception 'StrCmprException' if invalid input has been passed 150 * to the "Compare String" Variable-Arguments {@code String...} Parameter. 151 */ 152 protected static boolean NAND 153 (String methodName, String srcStr, String[] compareStr, Predicate<String> pred) 154 { 155 StrCmprException.check(compareStr); 156 157 for (String cmp: compareStr) 158 159 if (pred.test(cmp)) 160 { 161 if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp); 162 return false; 163 } 164 165 return true; 166 } 167 168 /** 169 * This performs the internal OR. It expects a comparison {@code Predicate} in order for the 170 * comparison to work. 171 * @param methodName If printing-debug information is expected, by the DEBUG global-variable, 172 * this {@code String} is used. 173 * @param srcStr This is the same source-string parameter from all the methods in this class. 174 * @param compareStr This is the same var-args string array from all the methods in this class. 175 * @param pred This is the comparison {@code Predicate} provided by the methods in this class 176 * that call this method. 177 * @return The OR of these {@code String's}, using the provided {@code Predicate}. 178 * @throws StrCmprException This exception shall throw if there are any invalid 179 * {@code String's} in the compare-string parameter array. 180 * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that 181 * would cause this exception to throw should remind the reader that <I><B>each and every 182 * method here</I></B> will throw exception 'StrCmprException' if invalid input has been passed 183 * to the "Compare String" Variable-Arguments {@code String...} Parameter. 184 */ 185 protected static boolean OR 186 (String methodName, String srcStr, String[] compareStr, Predicate<String> pred) 187 { 188 StrCmprException.check(compareStr); 189 190 for (String cmp: compareStr) 191 192 if (pred.test(cmp)) 193 { 194 if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp); 195 return true; 196 } 197 198 return false; 199 } 200 201 /** 202 * This performs the internal XOR. It expects a comparison {@code Predicate} in order for the 203 * comparison to work. 204 * @param methodName If printing-debug information is expected, by the DEBUG global-variable, 205 * this {@code String} is used. 206 * @param srcStr This is the same source-string parameter from all the methods in this class. 207 * @param compareStr This is the same var-args string array from all the methods in this class. 208 * @param pred This is the comparison {@code Predicate} provided by the methods in this class 209 * that call this method. 210 * @return The XOR of these {@code String's}, using the provided {@code Predicate}. 211 * @throws StrCmprException This exception shall throw if there are any invalid 212 * {@code String's} in the compare-string parameter array. 213 * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that 214 * would cause this exception to throw should remind the reader that <I><B>each and every 215 * method here</I></B> will throw exception 'StrCmprException' if invalid 216 * input has been passed to the "Compare String" Variable-Arguments {@code String...} 217 * Parameter. 218 */ 219 protected static boolean XOR 220 (String methodName, String srcStr, String[] compareStr, Predicate<String> pred) 221 { 222 StrCmprException.check(compareStr); 223 224 int count=0; 225 226 for (String cmp: compareStr) 227 228 if (pred.test(cmp)) 229 230 if (++count > 1) 231 { 232 if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp); 233 return false; 234 } 235 236 return count == 1; 237 } 238 239 240 241 // ******************************************************************************************** 242 // ******************************************************************************************** 243 // ******************************************************************************************** 244 // ******************************************************************************************** 245 // ******************************************************************************************** 246 // StrCmpr Main Section #1 247 // ******************************************************************************************** 248 // ******************************************************************************************** 249 // ******************************************************************************************** 250 // ******************************************************************************************** 251 // ******************************************************************************************** 252 253 254 255 // ******************************************************************************************** 256 // ******************************************************************************************** 257 // EQUALS 258 // ******************************************************************************************** 259 // ******************************************************************************************** 260 261 262 /** 263 * <EMBED CLASS=defs DATA-DESC='equals exactly one' DATA-CI='is'> 264 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 265 * @param srcStr Any non-null instance of a {@code java.lang.String} 266 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 267 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 268 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 269 * @see #XOR(String, String, String[], Predicate) 270 */ 271 public static boolean equalsXOR(String srcStr, String... compareStr) 272 { return XOR("equalsXOR", srcStr, compareStr, cmp -> srcStr.equals(cmp)); } 273 274 /** 275 * <EMBED CLASS=defs DATA-DESC='does not equal any' DATA-CI='is'> 276 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 277 * @param srcStr Any non-null instance of a {@code java.lang.String} 278 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 279 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 280 * @see #NAND(String, String, String[], Predicate) 281 */ 282 public static boolean equalsNAND(String srcStr, String... compareStr) 283 { return NAND("equalsNAND", srcStr, compareStr, cmp -> srcStr.equals(cmp)); } 284 285 /** 286 * <EMBED CLASS=defs DATA-DESC='equals exactly one' DATA-CI='is not'> 287 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 288 * @param srcStr Any non-null instance of a {@code java.lang.String} 289 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 290 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 291 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 292 * @see #XOR(String, String, String[], Predicate) 293 */ 294 public static boolean equalsXOR_CI(String srcStr, String... compareStr) 295 { return XOR("equalsXOR_CI", srcStr, compareStr, cmp -> srcStr.equalsIgnoreCase(cmp)); } 296 297 /** 298 * <EMBED CLASS=defs DATA-DESC='does not equal any' DATA-CI='is not'> 299 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 300 * @param srcStr Any non-null instance of a {@code java.lang.String} 301 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 302 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 303 * @see #NAND(String, String, String[], Predicate) 304 */ 305 public static boolean equalsNAND_CI(String srcStr, String... compareStr) 306 { return NAND("equalsNAND_CI", srcStr, compareStr, cmp -> srcStr.equalsIgnoreCase(cmp)); } 307 308 309 // ******************************************************************************************** 310 // ******************************************************************************************** 311 // CONTAINS 312 // ******************************************************************************************** 313 // ******************************************************************************************** 314 315 316 /** 317 * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'> 318 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 319 * @param srcStr Any non-null instance of a {@code java.lang.String} 320 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 321 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 322 * @see #CONTAINS(boolean, byte, String, String[]) 323 */ 324 public static boolean containsOR(String srcStr, String... compareStr) 325 { return CONTAINS(false, OR, srcStr, compareStr); } 326 327 /** 328 * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'> 329 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 330 * @param srcStr Any non-null instance of a {@code java.lang.String} 331 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 332 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 333 * @see #CONTAINS(boolean, byte, String, String[]) 334 */ 335 public static boolean containsAND(String srcStr, String... compareStr) 336 { return CONTAINS(false, AND, srcStr, compareStr); } 337 338 /** 339 * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'> 340 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 341 * @param srcStr Any non-null instance of a {@code java.lang.String} 342 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 343 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 344 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 345 * @see #CONTAINS(boolean, byte, String, String[]) 346 */ 347 public static boolean containsXOR(String srcStr, String... compareStr) 348 { return CONTAINS(false, XOR, srcStr, compareStr); } 349 350 /** 351 * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'> 352 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 353 * @param srcStr Any non-null instance of a {@code java.lang.String} 354 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 355 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 356 * @see #CONTAINS(boolean, byte, String, String[]) 357 */ 358 public static boolean containsNAND(String srcStr, String... compareStr) 359 { return CONTAINS(false, NAND, srcStr, compareStr); } 360 361 /** 362 * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'> 363 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 364 * @param srcStr Any non-null instance of a {@code java.lang.String} 365 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 366 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 367 * @see #CONTAINS(boolean, byte, String, String[]) 368 */ 369 public static boolean containsOR_CI(String srcStr, String... compareStr) 370 { return CONTAINS(true, OR, srcStr, compareStr); } 371 372 /** 373 * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'> 374 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 375 * @param srcStr Any non-null instance of a {@code java.lang.String} 376 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 377 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 378 * @see #CONTAINS(boolean, byte, String, String[]) 379 */ 380 public static boolean containsAND_CI(String srcStr, String... compareStr) 381 { return CONTAINS(true, AND, srcStr, compareStr); } 382 383 /** 384 * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'> 385 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 386 * @param srcStr Any non-null instance of a {@code java.lang.String} 387 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 388 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 389 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 390 * @see #CONTAINS(boolean, byte, String, String[]) 391 */ 392 public static boolean containsXOR_CI(String srcStr, String... compareStr) 393 { return CONTAINS(true, XOR, srcStr, compareStr); } 394 395 /** 396 * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'> 397 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 398 * @param srcStr Any non-null instance of a {@code java.lang.String} 399 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 400 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 401 * @see #CONTAINS(boolean, byte, String, String[]) 402 */ 403 public static boolean containsNAND_CI(String srcStr, String... compareStr) 404 { return CONTAINS(true, NAND, srcStr, compareStr); } 405 406 407 // ******************************************************************************************** 408 // ******************************************************************************************** 409 // STARTS-WITH, ENDS-WITH 410 // ******************************************************************************************** 411 // ******************************************************************************************** 412 413 414 /** 415 * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'> 416 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 417 * @param srcStr Any non-null instance of a {@code java.lang.String} 418 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 419 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 420 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 421 * @see #XOR(String, String, String[], Predicate) 422 */ 423 public static boolean endsWithXOR(String srcStr, String... compareStr) 424 { return XOR("endsWithXOR", srcStr, compareStr, cmp -> srcStr.endsWith(cmp)); } 425 426 /** 427 * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'> 428 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 429 * @param srcStr Any non-null instance of a {@code java.lang.String} 430 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 431 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 432 * @see #NAND(String, String, String[], Predicate) 433 */ 434 public static boolean endsWithNAND(String srcStr, String... compareStr) 435 { return NAND("endsWithNAND", srcStr, compareStr, cmp -> srcStr.endsWith(cmp)); } 436 437 /** 438 * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'> 439 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 440 * @param srcStr Any non-null instance of a {@code java.lang.String} 441 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 442 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 443 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 444 * @see #XOR(String, String, String[], Predicate) 445 */ 446 public static boolean startsWithXOR(String srcStr, String ... compareStr) 447 { return XOR("startsWithXOR", srcStr, compareStr, cmp -> srcStr.startsWith(cmp)); } 448 449 /** 450 * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'> 451 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 452 * @param srcStr Any non-null instance of a {@code java.lang.String} 453 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 454 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 455 * @see #NAND(String, String, String[], Predicate) 456 */ 457 public static boolean startsWithNAND(String srcStr, String ... compareStr) 458 { return NAND("startsWithNAND", srcStr, compareStr, cmp -> srcStr.startsWith(cmp)); } 459 460 461 // ******************************************************************************************** 462 // ******************************************************************************************** 463 // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE 464 // ******************************************************************************************** 465 // ******************************************************************************************** 466 467 468 /** 469 * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'> 470 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 471 * @param srcStr Any non-null instance of a {@code java.lang.String} 472 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 473 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 474 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 475 * @see #endsWithIgnoreCase(String, String) 476 * @see #XOR(String, String, String[], Predicate) 477 */ 478 public static boolean endsWithXOR_CI(String srcStr, String... compareStr) 479 { return XOR("endsWithXOR_CI", srcStr, compareStr, cmp -> endsWithIgnoreCase(srcStr, cmp)); } 480 481 /** 482 * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is not'> 483 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 484 * @param srcStr Any non-null instance of a {@code java.lang.String} 485 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 486 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 487 * @see #endsWithIgnoreCase(String, String) 488 * @see #NAND(String, String, String[], Predicate) 489 */ 490 public static boolean endsWithNAND_CI(String srcStr, String... compareStr) 491 { return NAND("endsWithNAND_CI", srcStr, compareStr, cmp -> endsWithIgnoreCase(srcStr, cmp)); } 492 493 /** 494 * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'> 495 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 496 * @param srcStr Any non-null instance of a {@code java.lang.String} 497 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 498 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 499 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 500 * @see #startsWithIgnoreCase(String, String) 501 * @see #XOR(String, String, String[], Predicate) 502 */ 503 public static boolean startsWithXOR_CI(String srcStr, String ... compareStr) 504 { return XOR("startsWithXOR_CI", srcStr, compareStr, cmp -> startsWithIgnoreCase(srcStr, cmp)); } 505 506 /** 507 * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'> 508 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC> 509 * @param srcStr Any non-null instance of a {@code java.lang.String} 510 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 511 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET> 512 * @see #startsWithIgnoreCase(String, String) 513 * @see #NAND(String, String, String[], Predicate) 514 */ 515 public static boolean startsWithNAND_CI(String srcStr, String ... compareStr) 516 { return NAND("startsWithNAND_CI", srcStr, compareStr, cmp -> startsWithIgnoreCase(srcStr, cmp)); } 517 518 519 // ******************************************************************************************** 520 // ******************************************************************************************** 521 // IGNORE-CASE METHODS 522 // ******************************************************************************************** 523 // ******************************************************************************************** 524 525 526 /** 527 * This performs the exact same comparison as Java's {@code String.startsWith(String)} method. 528 * Java provides an {@code 'equalsIgnoreCase()'} method, but not an 529 * {@code 'startsWithIgnoreCase()'}. This method does just that. 530 * @param srcStr This {@code String} is checked to see if it starts with the {@code compareStr}. 531 * @param compareStr This {@code String} is checked against the {@code srcStr} - specifically, 532 * if {@code srcStr} ends with {@code compareStr} 533 * @return {@code TRUE} if {@code srcStr} starts with {@code compareStr} (ignoring-case), and 534 * {@code FALSE} otherwise. 535 */ 536 public static boolean startsWithIgnoreCase(String srcStr, String compareStr) 537 { return srcStr.regionMatches(true, 0, compareStr, 0, compareStr.length()); } 538 539 /** 540 * This performs the exact same comparison as Java's {@code String.endsWith(String)} method. 541 * Java provides an {@code 'equalsIgnoreCase()'} method, but not an 542 * {@code 'endsWithIgnoreCase()'}. This method does just that. 543 * @param srcStr This {@code String} is checked to see if it ends with the {@code compareStr}. 544 * @param compareStr This {@code String} is checked against the {@code srcStr} - specifically, 545 * if {@code srcStr} ends with {@code compareStr} 546 * @return {@code TRUE} if {@code srcStr} ends with {@code compareStr} (ignoring-case), 547 * and {@code FALSE} otherwise. 548 */ 549 public static boolean endsWithIgnoreCase(String srcStr, String compareStr) 550 { 551 int compareStrLen = compareStr.length(); 552 int srcStrLen = srcStr.length(); 553 554 return srcStr.regionMatches(true, srcStrLen - compareStrLen, compareStr, 0, compareStrLen); 555 } 556 557 /** 558 * This performs the exact same comparison as Java's {@code String.contains(String)} method. 559 * Java provides an {@code 'equalsIgnoreCase()'} method, but not a 560 * {@code 'containsIgnoreCase()'}. This method does just that. 561 * @param srcStr This {@code String} is checked to see if it contains the {@code compareStr} 562 * @param compareStr This {@code String} is checked against the {@code srcStr} - specifically, 563 * if {@code compareStr} is contained by {@code srcStr} 564 * @return {@code TRUE} if {@code compareStr} is a substring of {@code srcStr} (ignoring-case), 565 * and {@code FALSE} otherwise. 566 * @see #containsIgnoreCase(String, LV, String) 567 */ 568 public static boolean containsIgnoreCase(String srcStr, String compareStr) 569 { return containsIgnoreCase(srcStr, new LV(srcStr, 0, srcStr.length()), compareStr); } 570 571 572 573 // ******************************************************************************************** 574 // ******************************************************************************************** 575 // ******************************************************************************************** 576 // ******************************************************************************************** 577 // ******************************************************************************************** 578 // StrCmpr Main Section #2 579 // ******************************************************************************************** 580 // ******************************************************************************************** 581 // ******************************************************************************************** 582 // ******************************************************************************************** 583 // ******************************************************************************************** 584 585 586 587 // ******************************************************************************************** 588 // ******************************************************************************************** 589 // EQUALS 590 // ******************************************************************************************** 591 // ******************************************************************************************** 592 593 594 /** 595 * <EMBED CLASS=defs DATA-DESC='equals exactly one' DATA-CI='is'> 596 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 597 * @param srcStr Any non-null instance of a {@code java.lang.String} 598 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 599 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 600 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 601 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 602 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 603 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 604 * @see #equals(String, LV, String) 605 * @see #XOR(String, String, String[], Predicate) 606 */ 607 public static boolean equalsXOR(String srcStr, int sPos, int ePos, String... compareStr) 608 { 609 LV l = new LV(srcStr, sPos, ePos); 610 return XOR("equalsXOR", srcStr, compareStr, cmp -> equals(srcStr, l, cmp)); 611 } 612 613 /** 614 * <EMBED CLASS=defs DATA-DESC='does not equal any' DATA-CI='is'> 615 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 616 * @param srcStr Any non-null instance of a {@code java.lang.String} 617 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 618 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 619 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 620 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 621 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 622 * @see #equals(String, LV, String) 623 * @see #NAND(String, String, String[], Predicate) 624 */ 625 public static boolean equalsNAND(String srcStr, int sPos, int ePos, String... compareStr) 626 { 627 LV l = new LV(srcStr, sPos, ePos); 628 return NAND("equalsNAND", srcStr, compareStr, cmp -> equals(srcStr, l, cmp)); 629 } 630 631 /** 632 * <EMBED CLASS=defs DATA-DESC='equals exactly one' DATA-CI='is not'> 633 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 634 * @param srcStr Any non-null instance of a {@code java.lang.String} 635 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 636 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 637 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 638 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 639 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 640 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 641 * @see #equalsIgnoreCase(String, LV, String) 642 * @see #XOR(String, String, String[], Predicate) 643 */ 644 public static boolean equalsXOR_CI(String srcStr, int sPos, int ePos, String... compareStr) 645 { 646 LV l = new LV(srcStr, sPos, ePos); 647 return XOR("equalsXOR_CI", srcStr, compareStr, cmp -> equalsIgnoreCase(srcStr, l, cmp)); 648 } 649 650 /** 651 * <EMBED CLASS=defs DATA-DESC='does not equal any' DATA-CI='is not'> 652 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 653 * @param srcStr Any non-null instance of a {@code java.lang.String} 654 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 655 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 656 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 657 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 658 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 659 * @see #equalsIgnoreCase(String, LV, String) 660 * @see #NAND(String, String, String[], Predicate) 661 */ 662 public static boolean equalsNAND_CI(String srcStr, int sPos, int ePos, String... compareStr) 663 { 664 LV l = new LV(srcStr, sPos, ePos); 665 return NAND("equalsNAND_CI", srcStr, compareStr, cmp -> equalsIgnoreCase(srcStr, l, cmp)); 666 } 667 668 669 // ******************************************************************************************** 670 // ******************************************************************************************** 671 // CONTAINS - This code is redundant 672 // ******************************************************************************************** 673 // ******************************************************************************************** 674 675 676 /** 677 * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'> 678 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 679 * @param srcStr Any non-null instance of a {@code java.lang.String} 680 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 681 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 682 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 683 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 684 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 685 * @see #CONTAINS(boolean, byte, LV, String, String[]) 686 */ 687 public static boolean containsOR(String srcStr, int sPos, int ePos, String... compareStr) 688 { 689 LV l = new LV(srcStr, sPos, ePos); 690 return CONTAINS(false, OR, l, srcStr, compareStr); 691 } 692 693 /** 694 * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'> 695 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 696 * @param srcStr Any non-null instance of a {@code java.lang.String} 697 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 698 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 699 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 700 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 701 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 702 * @see #CONTAINS(boolean, byte, LV, String, String[]) 703 */ 704 public static boolean containsAND(String srcStr, int sPos, int ePos, String... compareStr) 705 { 706 LV l = new LV(srcStr, sPos, ePos); 707 return CONTAINS(false, AND, l, srcStr, compareStr); 708 } 709 710 /** 711 * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'> 712 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 713 * @param srcStr Any non-null instance of a {@code java.lang.String} 714 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 715 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 716 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 717 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 718 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 719 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 720 * @see #CONTAINS(boolean, byte, LV, String, String[]) 721 */ 722 public static boolean containsXOR(String srcStr, int sPos, int ePos, String... compareStr) 723 { 724 LV l = new LV(srcStr, sPos, ePos); 725 return CONTAINS(false, XOR, l, srcStr, compareStr); 726 } 727 728 /** 729 * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'> 730 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 731 * @param srcStr Any non-null instance of a {@code java.lang.String} 732 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 733 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 734 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 735 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 736 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 737 * @see #CONTAINS(boolean, byte, LV, String, String[]) 738 */ 739 public static boolean containsNAND(String srcStr, int sPos, int ePos, String... compareStr) 740 { 741 LV l = new LV(srcStr, sPos, ePos); 742 return CONTAINS(false, NAND, l, srcStr, compareStr); 743 } 744 745 /** 746 * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'> 747 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 748 * @param srcStr Any non-null instance of a {@code java.lang.String} 749 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 750 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 751 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 752 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 753 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 754 * @see #CONTAINS(boolean, byte, LV, String, String[]) 755 */ 756 public static boolean containsOR_CI(String srcStr, int sPos, int ePos, String... compareStr) 757 { 758 LV l = new LV(srcStr, sPos, ePos); 759 return CONTAINS(true, OR, l, srcStr, compareStr); 760 } 761 762 /** 763 * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'> 764 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 765 * @param srcStr Any non-null instance of a {@code java.lang.String} 766 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 767 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 768 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 769 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 770 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 771 * @see #CONTAINS(boolean, byte, LV, String, String[]) 772 */ 773 public static boolean containsAND_CI(String srcStr, int sPos, int ePos, String... compareStr) 774 { 775 LV l = new LV(srcStr, sPos, ePos); 776 return CONTAINS(true, AND, l, srcStr, compareStr); 777 } 778 779 /** 780 * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'> 781 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 782 * @param srcStr Any non-null instance of a {@code java.lang.String} 783 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 784 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 785 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 786 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 787 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 788 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 789 * @see #CONTAINS(boolean, byte, LV, String, String[]) 790 */ 791 public static boolean containsXOR_CI(String srcStr, int sPos, int ePos, String... compareStr) 792 { 793 LV l = new LV(srcStr, sPos, ePos); 794 return CONTAINS(true, XOR, l, srcStr, compareStr); 795 } 796 797 /** 798 * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'> 799 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 800 * @param srcStr Any non-null instance of a {@code java.lang.String} 801 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 802 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 803 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 804 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 805 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 806 * @see #CONTAINS(boolean, byte, LV, String, String[]) 807 */ 808 public static boolean containsNAND_CI(String srcStr, int sPos, int ePos, String... compareStr) 809 { 810 LV l = new LV(srcStr, sPos, ePos); 811 return CONTAINS(true, NAND, l, srcStr, compareStr); 812 } 813 814 815 // ******************************************************************************************** 816 // ******************************************************************************************** 817 // STARTS-WITH, ENDS-WITH 818 // ******************************************************************************************** 819 // ******************************************************************************************** 820 821 822 /** 823 * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'> 824 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 825 * @param srcStr Any non-null instance of a {@code java.lang.String} 826 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 827 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 828 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 829 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 830 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 831 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 832 * @see #endsWith(String, LV, String) 833 * @see #XOR(String, String, String[], Predicate) 834 */ 835 public static boolean endsWithXOR(String srcStr, int sPos, int ePos, String... compareStr) 836 { 837 LV l = new LV(srcStr, sPos, ePos); 838 return XOR("endsWithXOR", srcStr, compareStr, cmp -> endsWith(srcStr, l, cmp)); 839 } 840 841 /** 842 * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'> 843 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 844 * @param srcStr Any non-null instance of a {@code java.lang.String} 845 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 846 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 847 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 848 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 849 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 850 * @see #endsWith(String, LV, String) 851 * @see #NAND(String, String, String[], Predicate) 852 */ 853 public static boolean endsWithNAND(String srcStr, int sPos, int ePos, String... compareStr) 854 { 855 LV l = new LV(srcStr, sPos, ePos); 856 return NAND("endsWithNAND", srcStr, compareStr, cmp -> endsWith(srcStr, l, cmp)); 857 } 858 859 /** 860 * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'> 861 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 862 * @param srcStr Any non-null instance of a {@code java.lang.String} 863 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 864 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 865 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 866 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 867 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 868 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 869 * @see #startsWith(String, LV, String) 870 * @see #XOR(String, String, String[], Predicate) 871 */ 872 public static boolean startsWithXOR(String srcStr, int sPos, int ePos, String ... compareStr) 873 { 874 LV l = new LV(srcStr, sPos, ePos); 875 return XOR("startsWithXOR", srcStr, compareStr, cmp -> startsWith(srcStr, l, cmp)); 876 } 877 878 /** 879 * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'> 880 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 881 * @param srcStr Any non-null instance of a {@code java.lang.String} 882 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 883 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 884 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 885 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 886 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 887 * @see #startsWith(String, LV, String) 888 * @see #NAND(String, String, String[], Predicate) 889 */ 890 public static boolean startsWithNAND(String srcStr, int sPos, int ePos, String ... compareStr) 891 { 892 LV l = new LV(srcStr, sPos, ePos); 893 return NAND("startsWithNAND", srcStr, compareStr, cmp -> startsWith(srcStr, l, cmp)); 894 } 895 896 897 // ******************************************************************************************** 898 // ******************************************************************************************** 899 // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE 900 // ******************************************************************************************** 901 // ******************************************************************************************** 902 903 904 /** 905 * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'> 906 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 907 * @param srcStr Any non-null instance of a {@code java.lang.String} 908 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 909 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 910 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 911 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 912 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 913 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 914 * @see #endsWithIgnoreCase(String, LV, String) 915 * @see #XOR(String, String, String[], Predicate) 916 */ 917 public static boolean endsWithXOR_CI(String srcStr, int sPos, int ePos, String... compareStr) 918 { 919 LV l = new LV(srcStr, sPos, ePos); 920 return XOR("endsWithXOR_CI", srcStr, compareStr, cmp -> endsWithIgnoreCase(srcStr, l, cmp)); 921 } 922 923 /** 924 * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is not'> 925 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 926 * @param srcStr Any non-null instance of a {@code java.lang.String} 927 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 928 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 929 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 930 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 931 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 932 * @see #endsWithIgnoreCase(String, LV, String) 933 * @see #NAND(String, String, String[], Predicate) 934 */ 935 public static boolean endsWithNAND_CI(String srcStr, int sPos, int ePos, String... compareStr) 936 { 937 LV l = new LV(srcStr, sPos, ePos); 938 return NAND("endsWithNAND_CI", srcStr, compareStr, cmp -> endsWithIgnoreCase(srcStr, l, cmp)); 939 } 940 941 /** 942 * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'> 943 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 944 * @param srcStr Any non-null instance of a {@code java.lang.String} 945 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 946 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 947 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 948 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 949 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCXORNOTE> 950 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 951 * @see #startsWithIgnoreCase(String, LV, String) 952 * @see #XOR(String, String, String[], Predicate) 953 */ 954 public static boolean startsWithXOR_CI(String srcStr, int sPos, int ePos, String ... compareStr) 955 { 956 LV l = new LV(srcStr, sPos, ePos); 957 return XOR("startsWithXOR_CI", srcStr, compareStr, cmp -> startsWithIgnoreCase(srcStr, l, cmp)); 958 } 959 960 /** 961 * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'> 962 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_SE> 963 * @param srcStr Any non-null instance of a {@code java.lang.String} 964 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 965 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 966 * @param compareStr The {@code String's} used in the comparison against {@code 'srcStr'} 967 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_SE> 968 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 969 * @see #startsWithIgnoreCase(String, LV, String) 970 * @see #NAND(String, String, String[], Predicate) 971 */ 972 public static boolean startsWithNAND_CI(String srcStr, int sPos, int ePos, String ... compareStr) 973 { 974 LV l = new LV(srcStr, sPos, ePos); 975 return NAND("startsWithNAND_CI", srcStr, compareStr, cmp -> startsWithIgnoreCase(srcStr, l, cmp)); 976 } 977 978 979 // ******************************************************************************************** 980 // ******************************************************************************************** 981 // Single String Methods 982 // ******************************************************************************************** 983 // ******************************************************************************************** 984 985 986 /** 987 * <EMBED CLASS=defs DATA-FUNC='equals' DATA-CI='is'> 988 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 989 * @param srcStr Any non-null instance of a {@code java.lang.String} 990 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 991 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 992 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 993 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 994 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 995 * @see #equals(String, LV, String) 996 */ 997 public static boolean equals(String srcStr, int sPos, int ePos, String compareStr) 998 { return equals(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 999 1000 1001 /** 1002 * <EMBED CLASS=defs DATA-FUNC='equals' DATA-CI='is not'> 1003 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1004 * @param srcStr Any non-null instance of a {@code java.lang.String} 1005 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1006 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1007 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1008 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1009 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1010 * @see #equalsIgnoreCase(String, LV, String) 1011 */ 1012 public static boolean equalsIgnoreCase(String srcStr, int sPos, int ePos, String compareStr) 1013 { return equalsIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1014 1015 1016 /** 1017 * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is'> 1018 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1019 * @param srcStr Any non-null instance of a {@code java.lang.String} 1020 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1021 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1022 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1023 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1024 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1025 * @see #startsWith(String, LV, String) 1026 */ 1027 public static boolean startsWith(String srcStr, int sPos, int ePos, String compareStr) 1028 { return startsWith(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1029 1030 /** 1031 * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is not'> 1032 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1033 * @param srcStr Any non-null instance of a {@code java.lang.String} 1034 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1035 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1036 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1037 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1038 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1039 * @see #startsWithIgnoreCase(String, LV, String) 1040 */ 1041 public static boolean startsWithIgnoreCase(String srcStr, int sPos, int ePos, String compareStr) 1042 { return startsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1043 1044 /** 1045 * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is'> 1046 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1047 * @param srcStr Any non-null instance of a {@code java.lang.String} 1048 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1049 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1050 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1051 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1052 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1053 * @see #endsWith(String, LV, String) 1054 */ 1055 public static boolean endsWith(String srcStr, int sPos, int ePos, String compareStr) 1056 { return endsWith(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1057 1058 /** 1059 * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is not'> 1060 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1061 * @param srcStr Any non-null instance of a {@code java.lang.String} 1062 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1063 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1064 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1065 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1066 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1067 * @see #endsWithIgnoreCase(String, LV, String) 1068 */ 1069 public static boolean endsWithIgnoreCase(String srcStr, int sPos, int ePos, String compareStr) 1070 { return endsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1071 1072 1073 /** 1074 * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is'> 1075 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1076 * @param srcStr Any non-null instance of a {@code java.lang.String} 1077 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1078 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1079 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1080 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1081 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1082 * @see #contains(String, LV, String) 1083 */ 1084 public static boolean contains(String srcStr, int sPos, int ePos, String compareStr) 1085 { return contains(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1086 1087 1088 /** 1089 * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is not'> 1090 * <EMBED CLASS='external-html' DATA-FILE-ID=STRCDESC_1C> 1091 * @param srcStr Any non-null instance of a {@code java.lang.String} 1092 * @param compareStr The {@code String} used in the comparison against {@code 'srcStr'} 1093 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR> 1094 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR> 1095 * @return <EMBED CLASS='external-html' DATA-FILE-ID=STRCRET_1C> 1096 * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX> 1097 * @see #containsIgnoreCase(String, LV, String) 1098 */ 1099 public static boolean containsIgnoreCase(String srcStr, int sPos, int ePos, String compareStr) 1100 { return containsIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), compareStr); } 1101 1102 1103 // ******************************************************************************************** 1104 // ******************************************************************************************** 1105 // PROTECTED METHODS 1106 // ******************************************************************************************** 1107 // ******************************************************************************************** 1108 1109 1110 /** 1111 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1112 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1113 */ 1114 protected static boolean equals(String srcStr, LV l, String compareStr) 1115 { 1116 return ((l.end - l.start) == compareStr.length()) 1117 && srcStr.regionMatches(l.start, compareStr, 0, compareStr.length()); 1118 } 1119 1120 /** 1121 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1122 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1123 */ 1124 protected static boolean equalsIgnoreCase(String srcStr, LV l, String compareStr) 1125 { 1126 return ((l.end - l.start) == compareStr.length()) 1127 && srcStr.regionMatches(true, l.start, compareStr, 0, compareStr.length()); 1128 } 1129 1130 /** 1131 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1132 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1133 */ 1134 protected static boolean startsWith(String srcStr, LV l, String compareStr) 1135 { 1136 return ((l.end - l.start) >= compareStr.length()) 1137 && srcStr.regionMatches(l.start, compareStr, 0, compareStr.length()); 1138 } 1139 1140 /** 1141 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1142 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1143 */ 1144 protected static boolean startsWithIgnoreCase(String srcStr, LV l, String compareStr) 1145 { 1146 return ((l.end - l.start) >= compareStr.length()) 1147 && srcStr.regionMatches(true, l.start, compareStr, 0, compareStr.length()); 1148 } 1149 1150 /** 1151 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1152 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1153 */ 1154 protected static boolean endsWith(String srcStr, LV l, String compareStr) 1155 { 1156 int compareStrLen = compareStr.length(); 1157 1158 return ((l.end - l.start) >= compareStrLen) 1159 && srcStr.regionMatches(l.end - compareStrLen, compareStr, 0, compareStrLen); 1160 } 1161 1162 /** 1163 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1164 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1165 */ 1166 protected static boolean endsWithIgnoreCase(String srcStr, LV l, String compareStr) 1167 { 1168 int compareStrLen = compareStr.length(); 1169 1170 return ((l.end - l.start) >= compareStrLen) 1171 && srcStr.regionMatches(true, l.end - compareStrLen, compareStr, 0, compareStrLen); 1172 } 1173 1174 /** 1175 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1176 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1177 */ 1178 protected static boolean contains(String srcStr, LV l, String compareStr) 1179 { 1180 // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) 1181 // Tests if two string regions are equal. A substring of this {@code String} object is 1182 // compared to a substring of the argument other. The result is true if these substrings 1183 // represent character sequences that are the same, ignoring case if and only if ignoreCase 1184 // is true. 1185 1186 int compareStrLen = compareStr.length(); 1187 int loopLen = l.end - compareStrLen; 1188 1189 if ((l.end - l.start) < compareStrLen) return false; 1190 1191 for (int i=l.start; i <= loopLen; i++) 1192 if (srcStr.regionMatches(i, compareStr, 0, compareStrLen)) 1193 return true; 1194 1195 return false; 1196 } 1197 1198 /** 1199 * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control 1200 * Variable Class Version of {@code 'LV'}. It is used internally by the search methods above. 1201 */ 1202 protected static boolean containsIgnoreCase(String srcStr, LV l, String compareStr) 1203 { 1204 // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) 1205 // Tests if two string regions are equal. A substring of this {@code String} object is 1206 // compared to a substring of the argument other. The result is true if these substrings 1207 // represent character sequences that are the same, ignoring case if and only if ignoreCase 1208 // is true. 1209 1210 int compareStrLen = compareStr.length(); 1211 int loopLen = l.end - compareStrLen; 1212 1213 if ((l.end - l.start) < compareStrLen) return false; 1214 1215 for (int i=l.start; i <= loopLen; i++) 1216 if (srcStr.regionMatches(true, i, compareStr, 0, compareStrLen)) 1217 return true; 1218 1219 return false; 1220 } 1221 1222 1223 // ******************************************************************************************** 1224 // ******************************************************************************************** 1225 // CONTAINS OPTIMIZATION 1226 // ******************************************************************************************** 1227 // ******************************************************************************************** 1228 1229 1230 /** 1231 * Signifies that an {@code 'AND'} operation is required, but only for methods that implement 1232 * one of the {@code 'contains'} variants. 1233 */ 1234 protected static final byte AND = 0; 1235 1236 /** 1237 * Signifies that an {@code 'AND'} operation is required, but only for methods that implement 1238 * one of the {@code 'contains'} variants. 1239 */ 1240 protected static final byte OR = 1; 1241 1242 /** 1243 * Signifies that an {@code 'AND'} operation is required, but only for methods that implement 1244 * one of the {@code 'contains'} variants. 1245 */ 1246 protected static final byte NAND = 2; 1247 1248 /** 1249 * Signifies that an {@code 'AND'} operation is required, but only for methods that implement 1250 * one of the {@code 'contains'} variants. 1251 */ 1252 protected static final byte XOR = 3; 1253 1254 // This is sort-of overkill. It is better to error in favor of caution, than to pretend. 1255 // I guess... :) 1256 private static final String CONTAINS_EX = 1257 "The value passed to parameter 'booleanOperation' was [BOOL]." + 1258 "However, this parameter is intended to must be chosen from one of the four boolean " + 1259 "static-constants available in this class. Valid values for this parameter include: " + 1260 "StrCmpr.AND, StrCmpr.OR, StrCmpr.XOR and StrCmpr.NAND."; 1261 1262 /** 1263 * Implementing a 'contains' is more efficient by performing only one loop iteration. 1264 * Therefore, the methods that implement some variant of the {@code String.contains} method 1265 * will use this general-purpose {@code contains}-testing method. 1266 * @param ignoresCase This is used to signify whether to ignore case when performing the 1267 * {@code String}-comparison operations. 1268 * @param booleanOperation This is designed to take one of four values. This method will 1269 * throw an exception if it does not. 1270 * @param l Loop end-point parameter 1271 * @param srcStr Any non-null instance of {@code java.lang.String} 1272 * @param cmpStrs This is one (or many) java {@code String's}, each of which shall be 1273 * compared to the ending of {@code 'srcStr'}. 1274 * @return The appropriate response based on the inputs for boolean logic. 1275 */ 1276 protected static boolean CONTAINS( 1277 boolean ignoresCase, byte booleanOperation, LV l, String srcStr, String[] cmpStrs 1278 ) 1279 { 1280 // Check each of the compare-strs first. It will provide a better exception message 1281 for (String s : cmpStrs) 1282 if (s == null) throw new NullPointerException 1283 ("One of the elements of 'compareStr' was null"); 1284 1285 if ((booleanOperation < 0) || (booleanOperation > 3)) 1286 throw new IllegalArgumentException 1287 (CONTAINS_EX.replace("BOOL", "" + booleanOperation)); 1288 1289 int count = (booleanOperation == XOR) ? 0 : cmpStrs.length; 1290 1291 cmpStrs = cmpStrs.clone(); 1292 1293 // Iterate each character in the String, and use it as the start to "regionMatches" 1294 for (int i=l.start; i < l.end; i++) 1295 1296 INNER: 1297 // Iterate each of the "compareison strings" - each are passed to "regionMatches" 1298 for (int j=0; j < cmpStrs.length; j++) 1299 1300 // The Strings in Compare-Str are sometimes set to null, if they are skip them 1301 if (cmpStrs[j] != null) 1302 1303 if (srcStr.regionMatches(ignoresCase, i, cmpStrs[j], 0, cmpStrs[j].length())) 1304 1305 switch (booleanOperation) 1306 { 1307 case AND : cmpStrs[j]=null; // no need to check for it again 1308 1309 if (--count == 0) return true; 1310 else continue INNER; // test-all cmpStrs 1311 1312 case XOR : cmpStrs[j]=null; // no need to check for it again 1313 1314 if (++count > 1) return false; 1315 else continue INNER; // test-all cmpStrs 1316 1317 case OR : return true; 1318 1319 case NAND : return false; 1320 } 1321 1322 switch(booleanOperation) 1323 { 1324 case AND : return false; 1325 case OR : return false; 1326 case XOR : return count == 1; 1327 case NAND : return true; 1328 } 1329 1330 // Already Checked boolean-operation, there is no way to reach this line of code. 1331 throw new UnreachableError(); 1332 } 1333 1334 /** 1335 * Implementing a 'contains' is more efficient by performing only one loop iteration. 1336 * Therefore, the methods that implement some variant of the {@code String.contains} method 1337 * will use this general-purpose {@code contains}-testing method. 1338 * @param ignoresCase This is used to signify whether to ignore case when performing the 1339 * {@code String}-comparison operations. 1340 * @param booleanOperation This is designed to take one of four values. This method will 1341 * throw an exception if it does not. 1342 * @param srcStr Any non-null instance of {@code java.lang.String} 1343 * @param cmpStrs This is one (or many) java {@code String's}, each of which shall be 1344 * compared to the ending of {@code 'srcStr'}. 1345 * @return The appropriate response based on the inputs for boolean logic. 1346 */ 1347 protected static boolean CONTAINS( 1348 boolean ignoresCase, byte booleanOperation, String srcStr, String[] cmpStrs 1349 ) 1350 { 1351 // Check each of the compare-strs first. It will provide a better exception message 1352 for (String s : cmpStrs) 1353 if (s == null) throw new NullPointerException 1354 ("One of the elements of 'compareStr' was null"); 1355 1356 if ((booleanOperation < 0) || (booleanOperation > 3)) 1357 throw new IllegalArgumentException 1358 (CONTAINS_EX.replace("BOOL", "" + booleanOperation)); 1359 1360 int count = (booleanOperation == XOR) ? 0 : cmpStrs.length; 1361 int len = srcStr.length(); 1362 1363 cmpStrs = cmpStrs.clone(); 1364 1365 // Iterate each character in the String, and use it as the start to "regionMatches" 1366 for (int i=0; i < len; i++) 1367 1368 INNER: 1369 // Iterate each of the "compareison strings" - each are passed to "regionMatches" 1370 for (int j=0; j < cmpStrs.length; j++) 1371 1372 // The Strings in Compare-Str are sometimes set to null, if they are skip them 1373 if (cmpStrs[j] != null) 1374 1375 if (srcStr.regionMatches(ignoresCase, i, cmpStrs[j], 0, cmpStrs[j].length())) 1376 1377 switch (booleanOperation) 1378 { 1379 case AND : cmpStrs[j]=null; // no need to check for it again 1380 1381 if (--count == 0) return true; 1382 else continue INNER; // test-all cmpStrs 1383 1384 case XOR : cmpStrs[j]=null; // no need to check for it again 1385 1386 if (++count > 1) return false; 1387 else continue INNER; // test-all cmpStrs 1388 1389 case OR : return true; 1390 1391 case NAND : return false; 1392 } 1393 1394 switch(booleanOperation) 1395 { 1396 case AND : return false; 1397 case OR : return false; 1398 case XOR : return count == 1; 1399 case NAND : return true; 1400 } 1401 1402 // Already Checked boolean-operation, there is no way to reach this line of code. 1403 throw new UnreachableError(); 1404 } 1405}