/* tapset for nginx */


function ngx_indent(n, delta)
{
    s = ""
    for (i = 0; i < n; i++) {
        s .= delta
    }

    return s
}


function ngx_http_subreq_depth(r)
{
    depth = 0

    for (pr = @cast(r, "ngx_http_request_t", "NGX_SBIN_PATH")->parent;
         pr != 0;
         pr = @cast(pr, "ngx_http_request_t", "NGX_SBIN_PATH")->parent)
    {
        depth++
    }

    return depth
}


function ngx_http_req_parent(r)
{
    return @cast(r, "ngx_http_request_s", "NGX_SBIN_PATH")->parent
}


/* retrieve the request uri string from the ngx_http_request_t pointer */
function ngx_http_req_uri(r)
{
    len = @cast(r, "ngx_http_request_s", "NGX_SBIN_PATH")->uri->len

    if (len == 0) {
        return ""
    }

    return user_string_n(@cast(r, "ngx_http_request_s", "NGX_SBIN_PATH")->uri->data, len)
}


/* retrieve the request query string from the ngx_http_request_t pointer */
function ngx_http_req_args(r)
{
    len = @cast(r, "ngx_http_request_s", "NGX_SBIN_PATH")->args->len

    if (len == 0) {
        return ""
    }

    return user_string_n(@cast(r, "ngx_http_request_s", "NGX_SBIN_PATH")->args->data, len)
}


/* retrieve the first command name (or directive name) from
 * the ngx_module_t pointer */
function ngx_http_module_cmd(m)
{
    cmds = @cast(m, "ngx_module_t", "NGX_SBIN_PATH")->commands
    if (cmds == 0) {
        return ""
    }

    len = @cast(cmds, "ngx_command_t", "NGX_SBIN_PATH")->name->len

    if (len == 0) {
        return ""
    }

    return user_string_n(@cast(cmds, "ngx_command_t", "NGX_SBIN_PATH")->name->data, len)
}


function ngx_chain_buf(cl)
{
    return @cast(cl, "ngx_chain_t", "NGX_SBIN_PATH")->buf
}


function ngx_chain_next(cl)
{
    return @cast(cl, "ngx_chain_t", "NGX_SBIN_PATH")->next
}

function ngx_buf_tag(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->tag
}

function ngx_buf_in_memory(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->temporary
        || @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->memory
        || @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->mmap
}


function ngx_buf_pos(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->pos
}


function ngx_buf_file_pos(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->file_pos
}


function ngx_buf_last(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->last
}


function ngx_buf_file_last(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->file_last
}


function ngx_buf_end(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->end
}


function ngx_buf_in_file(b)
{
    return @cast(b, "ngx_buf_t", "NGX_SBIN_PATH")->in_file
}


function ngx_buf_last_buf(b)
{
    return @cast(b, "ngx_buf_t", "/home/agentzh/git/lua-nginx-module/work/nginx/sbin/nginx")->last_buf
}


function ngx_buf_last_in_chain(b)
{
    return @cast(b, "ngx_buf_t", "/home/agentzh/git/lua-nginx-module/work/nginx/sbin/nginx")->last_in_chain
}


function ngx_buf_sync(b)
{
    return @cast(b, "ngx_buf_t", "/home/agentzh/git/lua-nginx-module/work/nginx/sbin/nginx")->sync
}


function ngx_buf_flush(b)
{
    return @cast(b, "ngx_buf_t", "/home/agentzh/git/lua-nginx-module/work/nginx/sbin/nginx")->flush
}


function ngx_buf_size(b)
{
    if (ngx_buf_in_memory(b)) {
        return ngx_buf_last(b) - ngx_buf_pos(b)
    }

    return ngx_buf_file_last(b) - ngx_buf_file_pos(b)
}


function ngx_buf_data(b)
{
    return user_string_n(ngx_buf_pos(b), ngx_buf_last(b) - ngx_buf_pos(b))
}


function ngx_chain_writer_ctx_out(ctx)
{
    return @cast(c, "ngx_chain_writer_ctx_t", "NGX_SBIN_PATH")->out
}


function ngx_chain_dump:string (input)
{
    if (input == 0) {
        return "NULL"
    }

    out = ""
    cl = input
    while (cl) {
        buf = ngx_chain_buf(cl)

        if (ngx_buf_in_memory(buf)) {
            out .= sprintf("[%s]", text_str(ngx_buf_data(buf)))

        } else {
            out .= "\"\""
        }

        if (ngx_buf_in_file(buf)) {
            out .= sprintf("<in_file:%d-%d>", ngx_buf_file_pos(buf),
                           ngx_buf_file_last(buf))
        }

        if (ngx_buf_last_buf(buf)) {
            out .= "<last_buf>"
        }

        if (ngx_buf_last_in_chain(buf)) {
            out .= "<last_in_chain>"
        }

        if (ngx_buf_sync(buf)) {
            out .= "<sync>"
        }

        if (ngx_buf_flush(buf)) {
            out .= "<flush>"
        }

        tag = ngx_buf_tag(buf)
        if (tag) {
            out .= sprintf("<tag:%p>", tag)
        }

        cl = ngx_chain_next(cl)
        if (cl) {
            out .= " "
        }
    }
    return out
}


function ngx_pool_cleanup_file_name(c)
{
    return user_string(@cast(c, "ngx_pool_cleanup_file_t", "NGX_SBIN_PATH")->name)
}


function ngx_http_req_content_length(r)
{
    return @cast(r, "ngx_http_request_t", "NGX_SBIN_PATH")->headers_in->content_length_n
}


function ngx_http_req_body_temp_file_name(r)
{
    rb = @cast(r, "ngx_http_request_t", "NGX_SBIN_PATH")->request_body
    if (!rb) {
        return ""
    }

    tf = @cast(rb, "ngx_http_request_body_t", "NGX_SBIN_PATH")->temp_file
    if (!tf) {
        return ""
    }

    len = @cast(tf, "ngx_temp_file_t", "NGX_SBIN_PATH")->file->name->len

    return user_string_n(@cast(tf, "ngx_temp_file_t", "NGX_SBIN_PATH")->file->name->data, len)
}


function ngx_table_elt_key(e)
{
    len = @cast(e, "ngx_table_elt_t", "NGX_SBIN_PATH")->key->len

    return user_string_n(@cast(e, "ngx_table_elt_t", "NGX_SBIN_PATH")->key->data, len)
}


function ngx_table_elt_value(e)
{
    len = @cast(e, "ngx_table_elt_t", "NGX_SBIN_PATH")->value->len

    return user_string_n(@cast(e, "ngx_table_elt_t", "NGX_SBIN_PATH")->value->data, len)
}


function ngx_iovec_dump:string (iov, iovcnt) {
    out = ""
    for (i = 0; i < iovcnt; i++) {
        out .= sprintf("\"%s\"(%p)", text_str(user_string_n(
                @cast(iov, "struct iovec")[i]->iov_base,
                @cast(iov, "struct iovec")[i]->iov_len)
            ), @cast(iov, "struct iovec")[i]->iov_base)
        if (i != iovcnt - 1) {
            out .= " "
        }
    }
    return out
}

