STATIC bool
S_isWB(pTHX_ WB_enum previous,
             WB_enum before,
             WB_enum after,
             const U8 * const strbeg,
             const U8 * const curpos,
             const U8 * const strend,
             const bool utf8_target)
{
    /*  Return a boolean as to if the boundary between 'before' and 'after' is
     *  a Unicode word break, using their published algorithm.  Context may be
     *  needed to make this determination.  If the value for the character
     *  before 'before' is known, it is passed as 'previous'; otherwise that
     *  should be set to WB_UNKNOWN.  The other input parameters give the
     *  boundaries and current position in the matching of the string.  That
     *  is, 'curpos' marks the position where the character whose wb value is
     *  'after' begins.  See http://www.unicode.org/reports/tr29/ */

    U8 * before_pos = (U8 *) curpos;
    U8 * after_pos = (U8 *) curpos;

    PERL_ARGS_ASSERT_ISWB;

    /* WB1 and WB2: Break at the start and end of text. */
    if (before == WB_EDGE || after == WB_EDGE) {
        return TRUE;
    }

    /* WB 3: Do not break within CRLF. */
    if (before == WB_CR && after == WB_LF) {
        return FALSE;
    }

    /* WB 3a and WB 3b: Otherwise break before and after Newlines (including CR
     * and LF) */
    if (   before == WB_CR || before == WB_LF || before == WB_Newline
        || after ==  WB_CR || after ==  WB_LF || after ==  WB_Newline)
    {
        return TRUE;
    }

    /* Ignore Format and Extend characters, except when they appear at the
     * beginning of a region of text.
     * WB4.  X (Extend | Format)*  →  X. */

    if (after == WB_Extend || after == WB_Format) {
        return FALSE;
    }

    if (before == WB_Extend || before == WB_Format) {
        before = backup_one_WB(&previous, strbeg, &before_pos, utf8_target);
    }

    switch (WBcase(before, after)) {
            /* Otherwise, break everywhere (including around ideographs).
                WB14.  Any  ÷  Any */
            default:
                return TRUE;

            /* Do not break between most letters.
                WB5.  (ALetter | Hebrew_Letter) × (ALetter | Hebrew_Letter) */
            case WBcase(WB_ALetter, WB_ALetter):
            case WBcase(WB_ALetter, WB_Hebrew_Letter):
            case WBcase(WB_Hebrew_Letter, WB_ALetter):
            case WBcase(WB_Hebrew_Letter, WB_Hebrew_Letter):
                return FALSE;

            /* Do not break letters across certain punctuation.
                WB6.  (ALetter | Hebrew_Letter)
                        × (MidLetter | MidNumLet | Single_Quote) (ALetter
                                                            | Hebrew_Letter) */
            case WBcase(WB_ALetter, WB_MidLetter):
            case WBcase(WB_ALetter, WB_MidNumLet):
            case WBcase(WB_ALetter, WB_Single_Quote):
            case WBcase(WB_Hebrew_Letter, WB_MidLetter):
            case WBcase(WB_Hebrew_Letter, WB_MidNumLet):
            /*case WBcase(WB_Hebrew_Letter, WB_Single_Quote):*/
                after = advance_one_WB(&after_pos, strend, utf8_target);
                return after != WB_ALetter && after != WB_Hebrew_Letter;

            /* WB7.  (ALetter | Hebrew_Letter) (MidLetter | MidNumLet |
             *                    Single_Quote) ×  (ALetter | Hebrew_Letter) */
            case WBcase(WB_MidLetter, WB_ALetter):
            case WBcase(WB_MidLetter, WB_Hebrew_Letter):
            case WBcase(WB_MidNumLet, WB_ALetter):
            case WBcase(WB_MidNumLet, WB_Hebrew_Letter):
            case WBcase(WB_Single_Quote, WB_ALetter):
            case WBcase(WB_Single_Quote, WB_Hebrew_Letter):
                before
                  = backup_one_WB(&previous, strbeg, &before_pos, utf8_target);
                return before != WB_ALetter && before != WB_Hebrew_Letter;

            /* WB7a.  Hebrew_Letter  ×  Single_Quote */
            case WBcase(WB_Hebrew_Letter, WB_Single_Quote):
                return FALSE;

            /* WB7b.  Hebrew_Letter  ×  Double_Quote Hebrew_Letter */
            case WBcase(WB_Hebrew_Letter, WB_Double_Quote):
                return advance_one_WB(&after_pos, strend, utf8_target)
                                                        != WB_Hebrew_Letter;

            /* WB7c.  Hebrew_Letter Double_Quote  ×  Hebrew_Letter */
            case WBcase(WB_Double_Quote, WB_Hebrew_Letter):
                return backup_one_WB(&previous, strbeg, &before_pos, utf8_target)
                                                        != WB_Hebrew_Letter;

            /* Do not break within sequences of digits, or digits adjacent to
             * letters (“3a”, or “A3”).
                WB8.  Numeric  ×  Numeric */
            case WBcase(WB_Numeric, WB_Numeric):
                return FALSE;

            /* WB9.  (ALetter | Hebrew_Letter)  ×  Numeric */
            case WBcase(WB_ALetter, WB_Numeric):
            case WBcase(WB_Hebrew_Letter, WB_Numeric):
                return FALSE;

            /* WB10.  Numeric  ×  (ALetter | Hebrew_Letter) */
            case WBcase(WB_Numeric, WB_ALetter):
            case WBcase(WB_Numeric, WB_Hebrew_Letter):
                return FALSE;

            /* Do not break within sequences, such as “3.2” or “3,456.789”.
                WB11.   Numeric (MidNum | MidNumLet | Single_Quote)  ×  Numeric
             */
            case WBcase(WB_MidNum, WB_Numeric):
            case WBcase(WB_MidNumLet, WB_Numeric):
            case WBcase(WB_Single_Quote, WB_Numeric):
                return backup_one_WB(&previous, strbeg, &before_pos, utf8_target)
                                                               != WB_Numeric;

            /*  WB12.   Numeric  ×  (MidNum | MidNumLet | Single_Quote) Numeric
             *  */
            case WBcase(WB_Numeric, WB_MidNum):
            case WBcase(WB_Numeric, WB_MidNumLet):
            case WBcase(WB_Numeric, WB_Single_Quote):
                return advance_one_WB(&after_pos, strend, utf8_target)
                                                               != WB_Numeric;

            /* Do not break between Katakana.
               WB13.  Katakana  ×  Katakana */
            case WBcase(WB_Katakana, WB_Katakana):
                return FALSE;

            /* Do not break from extenders.
               WB13a.  (ALetter | Hebrew_Letter | Numeric | Katakana |
                                            ExtendNumLet)  ×  ExtendNumLet */
            case WBcase(WB_ALetter, WB_ExtendNumLet):
            case WBcase(WB_Hebrew_Letter, WB_ExtendNumLet):
            case WBcase(WB_Numeric, WB_ExtendNumLet):
            case WBcase(WB_Katakana, WB_ExtendNumLet):
            case WBcase(WB_ExtendNumLet, WB_ExtendNumLet):
                return FALSE;

            /* WB13b.  ExtendNumLet  ×  (ALetter | Hebrew_Letter | Numeric
             *                                                 | Katakana) */
            case WBcase(WB_ExtendNumLet, WB_ALetter):
            case WBcase(WB_ExtendNumLet, WB_Hebrew_Letter):
            case WBcase(WB_ExtendNumLet, WB_Numeric):
            case WBcase(WB_ExtendNumLet, WB_Katakana):
                return FALSE;

            /* Do not break between regional indicator symbols.
               WB13c.  Regional_Indicator  ×  Regional_Indicator */
            case WBcase(WB_Regional_Indicator, WB_Regional_Indicator):
                return FALSE;

    }

    NOT_REACHED; /* NOTREACHED */
STATIC bool
S_isWB(pTHX_ WB_enum previous,
             WB_enum before,
             WB_enum after,
             const U8 * const strbeg,
             const U8 * const curpos,
             const U8 * const strend,
             const bool utf8_target)
{
     

    U8 * before_pos = (U8 *) curpos;
    U8 * after_pos = (U8 *) curpos;

    PERL_ARGS_ASSERT_ISWB;

     
    if (before == WB_EDGE || after == WB_EDGE) {
        return TRUE;
    }

     
    if (before == WB_CR && after == WB_LF) {
        return FALSE;
    }

     
    if (   before == WB_CR || before == WB_LF || before == WB_Newline
        || after ==  WB_CR || after ==  WB_LF || after ==  WB_Newline)
    {
        return TRUE;
    }

     

    if (after == WB_Extend || after == WB_Format) {
        return FALSE;
    }

    if (before == WB_Extend || before == WB_Format) {
        before = backup_one_WB(&previous, strbeg, &before_pos, utf8_target);
    }

    switch (WBcase(before, after)) {
             
            default:
                return TRUE;

             
            case WBcase(WB_ALetter, WB_ALetter):
            case WBcase(WB_ALetter, WB_Hebrew_Letter):
            case WBcase(WB_Hebrew_Letter, WB_ALetter):
            case WBcase(WB_Hebrew_Letter, WB_Hebrew_Letter):
                return FALSE;

             
            case WBcase(WB_ALetter, WB_MidLetter):
            case WBcase(WB_ALetter, WB_MidNumLet):
            case WBcase(WB_ALetter, WB_Single_Quote):
            case WBcase(WB_Hebrew_Letter, WB_MidLetter):
            case WBcase(WB_Hebrew_Letter, WB_MidNumLet):
             
                after = advance_one_WB(&after_pos, strend, utf8_target);
                return after != WB_ALetter && after != WB_Hebrew_Letter;

             
            case WBcase(WB_MidLetter, WB_ALetter):
            case WBcase(WB_MidLetter, WB_Hebrew_Letter):
            case WBcase(WB_MidNumLet, WB_ALetter):
            case WBcase(WB_MidNumLet, WB_Hebrew_Letter):
            case WBcase(WB_Single_Quote, WB_ALetter):
            case WBcase(WB_Single_Quote, WB_Hebrew_Letter):
                before
                  = backup_one_WB(&previous, strbeg, &before_pos, utf8_target);
                return before != WB_ALetter && before != WB_Hebrew_Letter;

             
            case WBcase(WB_Hebrew_Letter, WB_Single_Quote):
                return FALSE;

             
            case WBcase(WB_Hebrew_Letter, WB_Double_Quote):
                return advance_one_WB(&after_pos, strend, utf8_target)
                                                        != WB_Hebrew_Letter;

             
            case WBcase(WB_Double_Quote, WB_Hebrew_Letter):
                return backup_one_WB(&previous, strbeg, &before_pos, utf8_target)
                                                        != WB_Hebrew_Letter;

             
            case WBcase(WB_Numeric, WB_Numeric):
                return FALSE;

             
            case WBcase(WB_ALetter, WB_Numeric):
            case WBcase(WB_Hebrew_Letter, WB_Numeric):
                return FALSE;

             
            case WBcase(WB_Numeric, WB_ALetter):
            case WBcase(WB_Numeric, WB_Hebrew_Letter):
                return FALSE;

             
            case WBcase(WB_MidNum, WB_Numeric):
            case WBcase(WB_MidNumLet, WB_Numeric):
            case WBcase(WB_Single_Quote, WB_Numeric):
                return backup_one_WB(&previous, strbeg, &before_pos, utf8_target)
                                                               != WB_Numeric;

             
            case WBcase(WB_Numeric, WB_MidNum):
            case WBcase(WB_Numeric, WB_MidNumLet):
            case WBcase(WB_Numeric, WB_Single_Quote):
                return advance_one_WB(&after_pos, strend, utf8_target)
                                                               != WB_Numeric;

             
            case WBcase(WB_Katakana, WB_Katakana):
                return FALSE;

             
            case WBcase(WB_ALetter, WB_ExtendNumLet):
            case WBcase(WB_Hebrew_Letter, WB_ExtendNumLet):
            case WBcase(WB_Numeric, WB_ExtendNumLet):
            case WBcase(WB_Katakana, WB_ExtendNumLet):
            case WBcase(WB_ExtendNumLet, WB_ExtendNumLet):
                return FALSE;

             
            case WBcase(WB_ExtendNumLet, WB_ALetter):
            case WBcase(WB_ExtendNumLet, WB_Hebrew_Letter):
            case WBcase(WB_ExtendNumLet, WB_Numeric):
            case WBcase(WB_ExtendNumLet, WB_Katakana):
                return FALSE;

             
            case WBcase(WB_Regional_Indicator, WB_Regional_Indicator):
                return FALSE;

    }

    NOT_REACHED;  