uint32_t
ngx_utf8_decode(u_char **p, size_t n)
{
    size_t    len;
    uint32_t  u, i, valid;
    u = **p;
    if (u > 0xf0) {
        u &= 0x07;
        valid = 0xffff;
        len = 3;
    } else if (u > 0xe0) {
        u &= 0x0f;
        valid = 0x7ff;
        len = 2;
    } else if (u > 0xc0) {
        u &= 0x1f;
        valid = 0x7f;
        len = 1;
    } else {
        (*p)++;
        return 0xffffffff;
    }
    if (n - 1 < len) {
        return 0xfffffffe;
    }
    (*p)++;
    while (len) {
        i = *(*p)++;
        if (i < 0x80) {
            return 0xffffffff;
        }
        u = (u << 6) | (i & 0x3f);
        len--;
    }
    if (u > valid) {
        return u;
    }
    return 0xffffffff;
}
['static char *\nngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)\n{\n    u_char                       *p, *dst2src, **pp;\n    uint32_t                      n;\n    ngx_int_t                     src, dst;\n    ngx_str_t                    *value;\n    ngx_uint_t                    i;\n    ngx_http_charset_tables_t    *table;\n    ngx_http_charset_conf_ctx_t  *ctx;\n    if (cf->args->nelts != 2) {\n        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameters number");\n        return NGX_CONF_ERROR;\n    }\n    value = cf->args->elts;\n    src = ngx_hextoi(value[0].data, value[0].len);\n    if (src == NGX_ERROR || src > 255) {\n        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                           "invalid value \\"%V\\"", &value[0]);\n        return NGX_CONF_ERROR;\n    }\n    ctx = cf->ctx;\n    table = ctx->table;\n    if (ctx->charset->utf8) {\n        p = &table->src2dst[src * NGX_UTF_LEN];\n        *p++ = (u_char) (value[1].len / 2);\n        for (i = 0; i < value[1].len; i += 2) {\n            dst = ngx_hextoi(&value[1].data[i], 2);\n            if (dst == NGX_ERROR || dst > 255) {\n                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                                   "invalid value \\"%V\\"", &value[1]);\n                return NGX_CONF_ERROR;\n            }\n            *p++ = (u_char) dst;\n        }\n        i /= 2;\n        ctx->charset->length += i;\n        ctx->characters++;\n        p = &table->src2dst[src * NGX_UTF_LEN] + 1;\n        n = ngx_utf8_decode(&p, i);\n        if (n > 0xffff) {\n            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                               "invalid value \\"%V\\"", &value[1]);\n            return NGX_CONF_ERROR;\n        }\n        pp = (u_char **) &table->dst2src[0];\n        dst2src = pp[n >> 8];\n        if (dst2src == NULL) {\n            dst2src = ngx_pcalloc(cf->pool, 256);\n            if (dst2src == NULL) {\n                return NGX_CONF_ERROR;\n            }\n            pp[n >> 8] = dst2src;\n        }\n        dst2src[n & 0xff] = (u_char) src;\n    } else {\n        dst = ngx_hextoi(value[1].data, value[1].len);\n        if (dst == NGX_ERROR || dst > 255) {\n            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                               "invalid value \\"%V\\"", &value[1]);\n            return NGX_CONF_ERROR;\n        }\n        table->src2dst[src] = (u_char) dst;\n        table->dst2src[dst] = (u_char) src;\n    }\n    return NGX_CONF_OK;\n}', 'uint32_t\nngx_utf8_decode(u_char **p, size_t n)\n{\n    size_t    len;\n    uint32_t  u, i, valid;\n    u = **p;\n    if (u > 0xf0) {\n        u &= 0x07;\n        valid = 0xffff;\n        len = 3;\n    } else if (u > 0xe0) {\n        u &= 0x0f;\n        valid = 0x7ff;\n        len = 2;\n    } else if (u > 0xc0) {\n        u &= 0x1f;\n        valid = 0x7f;\n        len = 1;\n    } else {\n        (*p)++;\n        return 0xffffffff;\n    }\n    if (n - 1 < len) {\n        return 0xfffffffe;\n    }\n    (*p)++;\n    while (len) {\n        i = *(*p)++;\n        if (i < 0x80) {\n            return 0xffffffff;\n        }\n        u = (u << 6) | (i & 0x3f);\n        len--;\n    }\n    if (u > valid) {\n        return u;\n    }\n    return 0xffffffff;\n}']