(Regexp[] array, int flags)
| 362 | // A(B[CD]|EF)|BC[XY] |
| 363 | // |
| 364 | private Regexp[] factor(Regexp[] array, int flags) { |
| 365 | if (array.length < 2) { |
| 366 | return array; |
| 367 | } |
| 368 | |
| 369 | // The following code is subtle, because it's a literal Java |
| 370 | // translation of code that makes clever use of Go "slices". |
| 371 | // A slice is a triple (array, offset, length), and the Go |
| 372 | // implementation uses two slices, |sub| and |out| backed by the |
| 373 | // same array. In Java, we have to be explicit about all of these |
| 374 | // variables, so: |
| 375 | // |
| 376 | // Go Java |
| 377 | // sub (array, s, lensub) |
| 378 | // out (array, 0, lenout) // (always a prefix of |array|) |
| 379 | // |
| 380 | // In the comments we'll use the logical notation of go slices, e.g. sub[i] |
| 381 | // even though the Java code will read array[s + i]. |
| 382 | |
| 383 | int s = 0; // offset of first |sub| within array. |
| 384 | int lensub = array.length; // = len(sub) |
| 385 | int lenout = 0; // = len(out) |
| 386 | |
| 387 | // Round 1: Factor out common literal prefixes. |
| 388 | // Note: (str, strlen) and (istr, istrlen) are like Go slices |
| 389 | // onto a prefix of some Regexp's runes array (hence offset=0). |
| 390 | int[] str = null; |
| 391 | int strlen = 0; |
| 392 | int strflags = 0; |
| 393 | int start = 0; |
| 394 | for (int i = 0; i <= lensub; i++) { |
| 395 | // Invariant: the Regexps that were in sub[0:start] have been |
| 396 | // used or marked for reuse, and the slice space has been reused |
| 397 | // for out (len <= start). |
| 398 | // |
| 399 | // Invariant: sub[start:i] consists of regexps that all begin |
| 400 | // with str as modified by strflags. |
| 401 | int[] istr = null; |
| 402 | int istrlen = 0; |
| 403 | int iflags = 0; |
| 404 | if (i < lensub) { |
| 405 | // NB, we inlined Go's leadingString() since Java has no pair return. |
| 406 | Regexp re = array[s + i]; |
| 407 | if (re.op == Regexp.Op.CONCAT && re.subs.length > 0) { |
| 408 | re = re.subs[0]; |
| 409 | } |
| 410 | if (re.op == Regexp.Op.LITERAL) { |
| 411 | istr = re.runes; |
| 412 | istrlen = re.runes.length; |
| 413 | iflags = re.flags & RE2.FOLD_CASE; |
| 414 | } |
| 415 | // istr is the leading literal string that re begins with. |
| 416 | // The string refers to storage in re or its children. |
| 417 | |
| 418 | if (iflags == strflags) { |
| 419 | int same = 0; |
| 420 | while (same < strlen && same < istrlen && str[same] == istr[same]) { |
| 421 | same++; |
no test coverage detected