static int re_parse_char_class()

in src/couch_quickjs/quickjs/libregexp.c [786:872]


static int re_parse_char_class(REParseState *s, const uint8_t **pp)
{
    const uint8_t *p;
    uint32_t c1, c2;
    CharRange cr_s, *cr = &cr_s;
    CharRange cr1_s, *cr1 = &cr1_s;
    BOOL invert;

    cr_init(cr, s->opaque, lre_realloc);
    p = *pp;
    p++;    /* skip '[' */

    invert = FALSE;
    if (*p == '^') {
        p++;
        invert = TRUE;
    }

    for(;;) {
        if (*p == ']')
            break;
        c1 = get_class_atom(s, cr1, &p, TRUE);
        if ((int)c1 < 0)
            goto fail;
        if (*p == '-' && p[1] != ']') {
            const uint8_t *p0 = p + 1;
            if (c1 >= CLASS_RANGE_BASE) {
                if (s->is_unicode) {
                    cr_free(cr1);
                    goto invalid_class_range;
                }
                /* Annex B: match '-' character */
                goto class_atom;
            }
            c2 = get_class_atom(s, cr1, &p0, TRUE);
            if ((int)c2 < 0)
                goto fail;
            if (c2 >= CLASS_RANGE_BASE) {
                cr_free(cr1);
                if (s->is_unicode) {
                    goto invalid_class_range;
                }
                /* Annex B: match '-' character */
                goto class_atom;
            }
            p = p0;
            if (c2 < c1) {
            invalid_class_range:
                re_parse_error(s, "invalid class range");
                goto fail;
            }
            if (cr_union_interval(cr, c1, c2))
                goto memory_error;
        } else {
        class_atom:
            if (c1 >= CLASS_RANGE_BASE) {
                int ret;
                ret = cr_union1(cr, cr1->points, cr1->len);
                cr_free(cr1);
                if (ret)
                    goto memory_error;
            } else {
                if (cr_union_interval(cr, c1, c1))
                    goto memory_error;
            }
        }
    }
    if (s->ignore_case) {
        if (cr_regexp_canonicalize(cr, s->is_unicode))
            goto memory_error;
    }
    if (invert) {
        if (cr_invert(cr))
            goto memory_error;
    }
    if (re_emit_range(s, cr))
        goto fail;
    cr_free(cr);
    p++;    /* skip ']' */
    *pp = p;
    return 0;
 memory_error:
    re_parse_out_of_memory(s);
 fail:
    cr_free(cr);
    return -1;
}