static char *
ngx_http_geo_add_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
    in_addr_t start, in_addr_t end)
{
    in_addr_t              n;
    ngx_uint_t             h, i, s, e;
    ngx_array_t           *a;
    ngx_http_geo_range_t  *range;
    for (n = start; n <= end; n += 0x10000) {
        h = n >> 16;
        if (n == start) {
            s = n & 0xffff;
        } else {
            s = 0;
        }
        if ((n | 0xffff) > end) {
            e = end & 0xffff;
        } else {
            e = 0xffff;
        }
        a = (ngx_array_t *) ctx->high->low[h].ranges;
        if (a == NULL) {
            a = ngx_array_create(ctx->temp_pool, 64,
                                 sizeof(ngx_http_geo_range_t));
            if (a == NULL) {
                return NGX_CONF_ERROR;
            }
            ctx->high->low[h].ranges = (ngx_http_geo_range_t *) a;
        }
        i = a->nelts;
        range = a->elts;
        while (i) {
            i--;
            if (e < (ngx_uint_t) range[i].start) {
                continue;
            }
            if (s > (ngx_uint_t) range[i].end) {
                range = ngx_array_push(a);
                if (range == NULL) {
                    return NGX_CONF_ERROR;
                }
                range = a->elts;
                ngx_memcpy(&range[i + 2], &range[i + 1],
                           (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
                range[i + 1].start = (u_short) s;
                range[i + 1].end = (u_short) e;
                range[i + 1].value = ctx->value;
                goto next;
            }
            if (s == (ngx_uint_t) range[i].start
                && e == (ngx_uint_t) range[i].end)
            {
                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    "duplicate range \"%V\", value: \"%v\", old value: \"%v\"",
                    ctx->net, ctx->value, range[i].value);
                range[i].value = ctx->value;
                goto next;
            }
            if (s > (ngx_uint_t) range[i].start
                && e < (ngx_uint_t) range[i].end)
            {
                range = ngx_array_push(a);
                if (range == NULL) {
                    return NGX_CONF_ERROR;
                }
                range = ngx_array_push(a);
                if (range == NULL) {
                    return NGX_CONF_ERROR;
                }
                range = a->elts;
                ngx_memcpy(&range[i + 3], &range[i + 1],
                           (a->nelts - 3 - i) * sizeof(ngx_http_geo_range_t));
                range[i + 2].start = (u_short) (e + 1);
                range[i + 2].end = range[i].end;
                range[i + 2].value = range[i].value;
                range[i + 1].start = (u_short) s;
                range[i + 1].end = (u_short) e;
                range[i + 1].value = ctx->value;
                range[i].end = (u_short) (s - 1);
                goto next;
            }
            if (s == (ngx_uint_t) range[i].start
                && e < (ngx_uint_t) range[i].end)
            {
                range = ngx_array_push(a);
                if (range == NULL) {
                    return NGX_CONF_ERROR;
                }
                range = a->elts;
                ngx_memcpy(&range[i + 1], &range[i],
                           (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
                range[i + 1].start = (u_short) (e + 1);
                range[i].start = (u_short) s;
                range[i].end = (u_short) e;
                range[i].value = ctx->value;
                goto next;
            }
            if (s > (ngx_uint_t) range[i].start
                && e == (ngx_uint_t) range[i].end)
            {
                range = ngx_array_push(a);
                if (range == NULL) {
                    return NGX_CONF_ERROR;
                }
                range = a->elts;
                ngx_memcpy(&range[i + 2], &range[i + 1],
                           (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
                range[i + 1].start = (u_short) s;
                range[i + 1].end = (u_short) e;
                range[i + 1].value = ctx->value;
                range[i].end = (u_short) (s - 1);
                goto next;
            }
            s = (ngx_uint_t) range[i].start;
            e = (ngx_uint_t) range[i].end;
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                         "range \"%V\" overlaps \"%d.%d.%d.%d-%d.%d.%d.%d\"",
                         ctx->net,
                         h >> 8, h & 0xff, s >> 8, s & 0xff,
                         h >> 8, h & 0xff, e >> 8, e & 0xff);
            return NGX_CONF_ERROR;
        }
        range = ngx_array_push(a);
        if (range == NULL) {
            return NGX_CONF_ERROR;
        }
        range->start = (u_short) s;
        range->end = (u_short) e;
        range->value = ctx->value;
    next:
        continue;
    }
    return NGX_CONF_OK;
}
['static char *\nngx_http_geo_add_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,\n    in_addr_t start, in_addr_t end)\n{\n    in_addr_t              n;\n    ngx_uint_t             h, i, s, e;\n    ngx_array_t           *a;\n    ngx_http_geo_range_t  *range;\n    for (n = start; n <= end; n += 0x10000) {\n        h = n >> 16;\n        if (n == start) {\n            s = n & 0xffff;\n        } else {\n            s = 0;\n        }\n        if ((n | 0xffff) > end) {\n            e = end & 0xffff;\n        } else {\n            e = 0xffff;\n        }\n        a = (ngx_array_t *) ctx->high->low[h].ranges;\n        if (a == NULL) {\n            a = ngx_array_create(ctx->temp_pool, 64,\n                                 sizeof(ngx_http_geo_range_t));\n            if (a == NULL) {\n                return NGX_CONF_ERROR;\n            }\n            ctx->high->low[h].ranges = (ngx_http_geo_range_t *) a;\n        }\n        i = a->nelts;\n        range = a->elts;\n        while (i) {\n            i--;\n            if (e < (ngx_uint_t) range[i].start) {\n                continue;\n            }\n            if (s > (ngx_uint_t) range[i].end) {\n                range = ngx_array_push(a);\n                if (range == NULL) {\n                    return NGX_CONF_ERROR;\n                }\n                range = a->elts;\n                ngx_memcpy(&range[i + 2], &range[i + 1],\n                           (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));\n                range[i + 1].start = (u_short) s;\n                range[i + 1].end = (u_short) e;\n                range[i + 1].value = ctx->value;\n                goto next;\n            }\n            if (s == (ngx_uint_t) range[i].start\n                && e == (ngx_uint_t) range[i].end)\n            {\n                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,\n                    "duplicate range \\"%V\\", value: \\"%v\\", old value: \\"%v\\"",\n                    ctx->net, ctx->value, range[i].value);\n                range[i].value = ctx->value;\n                goto next;\n            }\n            if (s > (ngx_uint_t) range[i].start\n                && e < (ngx_uint_t) range[i].end)\n            {\n                range = ngx_array_push(a);\n                if (range == NULL) {\n                    return NGX_CONF_ERROR;\n                }\n                range = ngx_array_push(a);\n                if (range == NULL) {\n                    return NGX_CONF_ERROR;\n                }\n                range = a->elts;\n                ngx_memcpy(&range[i + 3], &range[i + 1],\n                           (a->nelts - 3 - i) * sizeof(ngx_http_geo_range_t));\n                range[i + 2].start = (u_short) (e + 1);\n                range[i + 2].end = range[i].end;\n                range[i + 2].value = range[i].value;\n                range[i + 1].start = (u_short) s;\n                range[i + 1].end = (u_short) e;\n                range[i + 1].value = ctx->value;\n                range[i].end = (u_short) (s - 1);\n                goto next;\n            }\n            if (s == (ngx_uint_t) range[i].start\n                && e < (ngx_uint_t) range[i].end)\n            {\n                range = ngx_array_push(a);\n                if (range == NULL) {\n                    return NGX_CONF_ERROR;\n                }\n                range = a->elts;\n                ngx_memcpy(&range[i + 1], &range[i],\n                           (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));\n                range[i + 1].start = (u_short) (e + 1);\n                range[i].start = (u_short) s;\n                range[i].end = (u_short) e;\n                range[i].value = ctx->value;\n                goto next;\n            }\n            if (s > (ngx_uint_t) range[i].start\n                && e == (ngx_uint_t) range[i].end)\n            {\n                range = ngx_array_push(a);\n                if (range == NULL) {\n                    return NGX_CONF_ERROR;\n                }\n                range = a->elts;\n                ngx_memcpy(&range[i + 2], &range[i + 1],\n                           (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));\n                range[i + 1].start = (u_short) s;\n                range[i + 1].end = (u_short) e;\n                range[i + 1].value = ctx->value;\n                range[i].end = (u_short) (s - 1);\n                goto next;\n            }\n            s = (ngx_uint_t) range[i].start;\n            e = (ngx_uint_t) range[i].end;\n            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,\n                         "range \\"%V\\" overlaps \\"%d.%d.%d.%d-%d.%d.%d.%d\\"",\n                         ctx->net,\n                         h >> 8, h & 0xff, s >> 8, s & 0xff,\n                         h >> 8, h & 0xff, e >> 8, e & 0xff);\n            return NGX_CONF_ERROR;\n        }\n        range = ngx_array_push(a);\n        if (range == NULL) {\n            return NGX_CONF_ERROR;\n        }\n        range->start = (u_short) s;\n        range->end = (u_short) e;\n        range->value = ctx->value;\n    next:\n        continue;\n    }\n    return NGX_CONF_OK;\n}', 'ngx_array_t *\nngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)\n{\n    ngx_array_t *a;\n    a = ngx_palloc(p, sizeof(ngx_array_t));\n    if (a == NULL) {\n        return NULL;\n    }\n    a->elts = ngx_palloc(p, n * size);\n    if (a->elts == NULL) {\n        return NULL;\n    }\n    a->nelts = 0;\n    a->size = size;\n    a->nalloc = n;\n    a->pool = p;\n    return a;\n}']