int lre_case_conv()

in GaiaXAndroidQuickJS/quickjs/gxquickjs/libunicode.c [56:158]


int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
{
    if (c < 128) {
        if (conv_type) {
            if (c >= 'A' && c <= 'Z') {
                c = c - 'A' + 'a';
            }
        } else {
            if (c >= 'a' && c <= 'z') {
                c = c - 'a' + 'A';
            }
        }
    } else {
        uint32_t v, code, data, type, len, a, is_lower;
        int idx, idx_min, idx_max;
        
        is_lower = (conv_type != 0);
        idx_min = 0;
        idx_max = countof(case_conv_table1) - 1;
        while (idx_min <= idx_max) {
            idx = (unsigned)(idx_max + idx_min) / 2;
            v = case_conv_table1[idx];
            code = v >> (32 - 17);
            len = (v >> (32 - 17 - 7)) & 0x7f;
            if (c < code) {
                idx_max = idx - 1;
            } else if (c >= code + len) {
                idx_min = idx + 1;
            } else {
                type = (v >> (32 - 17 - 7 - 4)) & 0xf;
                data = ((v & 0xf) << 8) | case_conv_table2[idx];
                switch(type) {
                case RUN_TYPE_U:
                case RUN_TYPE_L:
                case RUN_TYPE_UF:
                case RUN_TYPE_LF:
                    if (conv_type == (type & 1) ||
                        (type >= RUN_TYPE_UF && conv_type == 2)) {
                        c = c - code + (case_conv_table1[data] >> (32 - 17));
                    }
                    break;
                case RUN_TYPE_UL:
                    a = c - code;
                    if ((a & 1) != (1 - is_lower))
                        break;
                    c = (a ^ 1) + code;
                    break;
                case RUN_TYPE_LSU:
                    a = c - code;
                    if (a == 1) {
                        c += 2 * is_lower - 1;
                    } else if (a == (1 - is_lower) * 2) {
                        c += (2 * is_lower - 1) * 2;
                    }
                    break;
                case RUN_TYPE_U2L_399_EXT2:
                    if (!is_lower) {
                        res[0] = c - code + case_conv_ext[data >> 6];
                        res[1] = 0x399;
                        return 2;
                    } else {
                        c = c - code + case_conv_ext[data & 0x3f];
                    }
                    break;
                case RUN_TYPE_UF_D20:
                    if (conv_type == 1)
                        break;
                    c = data + (conv_type == 2) * 0x20;
                    break;
                case RUN_TYPE_UF_D1_EXT:
                    if (conv_type == 1)
                        break;
                    c = case_conv_ext[data] + (conv_type == 2);
                    break;
                case RUN_TYPE_U_EXT:
                case RUN_TYPE_LF_EXT:
                    if (is_lower != (type - RUN_TYPE_U_EXT))
                        break;
                    c = case_conv_ext[data];
                    break;
                case RUN_TYPE_U_EXT2:
                case RUN_TYPE_L_EXT2:
                    if (conv_type != (type - RUN_TYPE_U_EXT2))
                        break;
                    res[0] = c - code + case_conv_ext[data >> 6];
                    res[1] = case_conv_ext[data & 0x3f];
                    return 2;
                default:
                case RUN_TYPE_U_EXT3:
                    if (conv_type != 0)
                        break;
                    res[0] = case_conv_ext[data >> 8];
                    res[1] = case_conv_ext[(data >> 4) & 0xf];
                    res[2] = case_conv_ext[data & 0xf];
                    return 3;
                }
                break;
            }
        }
    }
    res[0] = c;
    return 1;
}