-
- assert(SvMAGICAL(bigstr));
- mg = mg_find(bigstr, PERL_MAGIC_study);
- assert(mg);
- assert(SvTYPE(littlestr) == SVt_PVMG);
- assert(SvVALID(littlestr));
-
- if (mg->mg_private == 1) {
- const U8 *const screamfirst = (U8 *)mg->mg_ptr;
- const U8 *const screamnext = screamfirst + 256;
-
- screamnext_raw = (const void *)screamnext;
-
- pos = *old_posp == -1
- ? screamfirst[BmRARE(littlestr)] : screamnext[*old_posp];
- cant_find = pos == (U8)~0;
- } else if (mg->mg_private == 2) {
- const U16 *const screamfirst = (U16 *)mg->mg_ptr;
- const U16 *const screamnext = screamfirst + 256;
-
- screamnext_raw = (const void *)screamnext;
-
- pos = *old_posp == -1
- ? screamfirst[BmRARE(littlestr)] : screamnext[*old_posp];
- cant_find = pos == (U16)~0;
- } else if (mg->mg_private == 4) {
- const U32 *const screamfirst = (U32 *)mg->mg_ptr;
- const U32 *const screamnext = screamfirst + 256;
-
- screamnext_raw = (const void *)screamnext;
-
- pos = *old_posp == -1
- ? screamfirst[BmRARE(littlestr)] : screamnext[*old_posp];
- cant_find = pos == (U32)~0;
- } else
- Perl_croak(aTHX_ "panic: unknown study size %u", mg->mg_private);
-
- if (cant_find) {
- cant_find:
- if ( BmRARE(littlestr) == '\n'
- && BmPREVIOUS(littlestr) == SvCUR(littlestr) - 1) {
- little = (const unsigned char *)(SvPVX_const(littlestr));
- littleend = little + SvCUR(littlestr);
- first = *little++;
- goto check_tail;
- }
- return NULL;
- }
-
- little = (const unsigned char *)(SvPVX_const(littlestr));
- littleend = little + SvCUR(littlestr);
- first = *little++;
- /* The value of pos we can start at: */
- previous = BmPREVIOUS(littlestr);
- big = (const unsigned char *)(SvPVX_const(bigstr));
- /* The value of pos we can stop at: */
- stop_pos = SvCUR(bigstr) - end_shift - (SvCUR(littlestr) - 1 - previous);
- if (previous + start_shift > stop_pos) {
-/*
- stop_pos does not include SvTAIL in the count, so this check is incorrect
- (I think) - see [ID 20010618.006] and t/op/study.t. HVDS 2001/06/19
-*/
-#if 0
- if (previous + start_shift == stop_pos + 1) /* A fake '\n'? */
- goto check_tail;
-#endif
- return NULL;
- }
- if (mg->mg_private == 1) {
- const U8 *const screamnext = (const U8 *const) screamnext_raw;
- while ((I32)pos < previous + start_shift) {
- pos = screamnext[pos];
- if (pos == (U8)~0)
- goto cant_find;
- }
- } else if (mg->mg_private == 2) {
- const U16 *const screamnext = (const U16 *const) screamnext_raw;
- while ((I32)pos < previous + start_shift) {
- pos = screamnext[pos];
- if (pos == (U16)~0)
- goto cant_find;
- }
- } else if (mg->mg_private == 4) {
- const U32 *const screamnext = (const U32 *const) screamnext_raw;
- while ((I32)pos < previous + start_shift) {
- pos = screamnext[pos];
- if (pos == (U32)~0)
- goto cant_find;
- }
- }
- big -= previous;
- while (1) {
- if ((I32)pos >= stop_pos) break;
- if (big[pos] == first) {
- const unsigned char *s = little;
- const unsigned char *x = big + pos + 1;
- while (s < littleend) {
- if (*s != *x++)
- break;
- ++s;
- }
- if (s == littleend) {
- *old_posp = (I32)pos;
- if (!last) return (char *)(big+pos);
- found = TRUE;
- }
- }
- if (mg->mg_private == 1) {
- pos = ((const U8 *const)screamnext_raw)[pos];
- if (pos == (U8)~0)
- break;
- } else if (mg->mg_private == 2) {
- pos = ((const U16 *const)screamnext_raw)[pos];
- if (pos == (U16)~0)
- break;
- } else if (mg->mg_private == 4) {
- pos = ((const U32 *const)screamnext_raw)[pos];
- if (pos == (U32)~0)
- break;
- }
- };
- if (last && found)
- return (char *)(big+(*old_posp));
- check_tail:
- if (!SvTAIL(littlestr) || (end_shift > 0))
- return NULL;
- /* Ignore the trailing "\n". This code is not microoptimized */
- big = (const unsigned char *)(SvPVX_const(bigstr) + SvCUR(bigstr));
- stop_pos = littleend - little; /* Actual littlestr len */
- if (stop_pos == 0)
- return (char*)big;
- big -= stop_pos;
- if (*big == first
- && ((stop_pos == 1) ||
- memEQ((char *)(big + 1), (char *)little, stop_pos - 1)))
- return (char*)big;