/*
Mocks source file

Generated with Narmock v{{ narmock_version }} (https://github.com/vberlier/narmock)
Do not edit manually
*/
{{ includes }}
void narmock_reset_all_mocks(void)
{
{% for mock in mocks %}
    MOCK({{ mock.func_name }})->reset();
{% endfor %}
}
{% for mock in mocks %}

{{ mock.IMPL_MARKER }} {{ mock.func_name }}

{{ mock.real_decl | render }};

typedef struct {{ mock.private_state_type }} {{ mock.private_state_type }};

struct {{ mock.private_state_type }}
{
    {{ mock.state_type }} public;

    int mode;
    {% if mock.return_value %}
    {{ mock.return_value_decl | render }};
    {% endif %}
    {{ mock.implementation_decl | render }};
    int errno_value;
    {{ mock.params_type }} last_call;
};

static const {{ mock.state_type }} *_narmock_mock_return_function_for_{{ mock.func_name }}({{ mock.return_value_decl | render }});
static const {{ mock.state_type }} *_narmock_mock_implementation_function_for_{{ mock.func_name }}({{ mock.implementation_decl | render }});
static const {{ mock.state_type }} *_narmock_mock_errno_function_for_{{ mock.func_name }}(int errno_value);
static const {{ mock.state_type }} *_narmock_disable_mock_function_for_{{ mock.func_name }}(void);
static const {{ mock.state_type }} *_narmock_reset_function_for_{{ mock.func_name }}(void);

static {{ mock.private_state_type }} {{ mock.state_name }} =
{
    .public = {
        .mock_return = _narmock_mock_return_function_for_{{ mock.func_name }},
        .mock_implementation = _narmock_mock_implementation_function_for_{{ mock.func_name }},
        .mock_errno = _narmock_mock_errno_function_for_{{ mock.func_name }},
        .disable_mock = _narmock_disable_mock_function_for_{{ mock.func_name }},
        .reset = _narmock_reset_function_for_{{ mock.func_name }},
        .call_count = 0,
        .last_call = NULL
    },

    .mode = 0,
    .errno_value = 0
};

{{ mock.perform_decl | render }}
{
    switch ({{ mock.state_name }}.mode)
    {
        case 1:
            {% if mock.return_value %}
            return {{ mock.state_name }}.return_value;
            {% else %}
            return;
            {% endif %}
        case 2:
            {% if mock.variadic %}
#ifdef __GNUC__
            {% for param in mock.params_struct %}
            (void){{ param.name }};
            {% endfor %}
            __builtin_return(__builtin_apply((void *){{ mock.state_name }}.implementation, __builtin_apply_args(), {{ variadic_forward_size }}));
#else
            {% endif %}
            {% if mock.return_value %}
            return {{ mock.state_name }}.implementation({{ mock.forward_args }});
            {% else %}
            {{ mock.state_name }}.implementation({{ mock.forward_args }});
            return;
            {% endif %}
            {% if mock.variadic %}
#endif
            {% endif %}
        default:
            {% if mock.variadic %}
#ifdef __GNUC__
            {% for param in mock.params_struct %}
            (void){{ param.name }};
            {% endfor %}
            __builtin_return(__builtin_apply((void *){{ mock.real_func }}, __builtin_apply_args(), {{ variadic_forward_size }}));
#else
            {% endif %}
            {% if mock.return_value %}
            return {{ mock.real_func }}({{ mock.forward_args }});
            {% else %}
            {{ mock.real_func }}({{ mock.forward_args }});
            return;
            {% endif %}
            {% if mock.variadic %}
#endif
            {% endif %}
    }
}

{{ mock.wrapped_decl | render }}
{
    {% if mock.return_value %}
    {{ mock.return_value_decl | render }};

    {% endif %}
    {% if mock.variadic %}
#ifdef __GNUC__
    {% if mock.return_value %}
    return_value = *(({{ mock.return_value_decl.type | render }} *)__builtin_apply((void *){{ mock.perform_func }}, __builtin_apply_args(), {{ variadic_forward_size }}));
    {% else %}
    __builtin_apply((void*){{ mock.perform_func }}, __builtin_apply_args(), {{ variadic_forward_size }});
    {% endif %}
#else
    {% endif %}
    {% if mock.return_value %}
    return_value = {{ mock.perform_func }}({{ mock.forward_args }});
    {% else %}
    {{ mock.perform_func }}({{ mock.forward_args }});
    {% endif %}
    {% if mock.variadic %}
#endif
    {% endif %}

    if ({{ mock.state_name }}.errno_value != 0)
    {
        errno = {{ mock.state_name }}.errno_value;
    }

    {{ mock.state_name }}.public.call_count++;

    {{ mock.params_type }} last_call = { {{ mock.save_args }} };

    {{ mock.state_name }}.last_call = last_call;
    {{ mock.state_name }}.public.last_call = &{{ mock.state_name }}.last_call;

    return{% if mock.return_value %} return_value{% endif %};
}

static const {{ mock.state_type }} *_narmock_mock_return_function_for_{{ mock.func_name }}({{ mock.return_value_decl | render }})
{
    {{ mock.state_name }}.mode = 1;
    {% if mock.return_value %}
    {{ mock.state_name }}.return_value = return_value;
    {% endif %}

    return &{{ mock.state_name }}.public;
}

static const {{ mock.state_type }} *_narmock_mock_implementation_function_for_{{ mock.func_name }}({{ mock.implementation_decl | render }})
{
    {{ mock.state_name }}.mode = 2;
    {{ mock.state_name }}.implementation = implementation;

    return &{{ mock.state_name }}.public;
}

static const {{ mock.state_type }} *_narmock_mock_errno_function_for_{{ mock.func_name }}(int errno_value)
{
    {{ mock.state_name }}.errno_value = errno_value;

    return &{{ mock.state_name }}.public;
}

static const {{ mock.state_type }} *_narmock_disable_mock_function_for_{{ mock.func_name }}(void)
{
    {{ mock.state_name }}.mode = 0;
    {{ mock.state_name }}.errno_value = 0;

    return &{{ mock.state_name }}.public;
}

static const {{ mock.state_type }} *_narmock_reset_function_for_{{ mock.func_name }}(void)
{
    {{ mock.state_name }}.mode = 0;
    {{ mock.state_name }}.errno_value = 0;
    {{ mock.state_name }}.public.call_count = 0;
    {{ mock.state_name }}.public.last_call = NULL;

    return &{{ mock.state_name }}.public;
}

const {{ mock.state_type }} *_narmock_get_mock_for_{{ mock.func_name }}(const void *function)
{
    (void)function;

    return &{{ mock.state_name }}.public;
}
{% endfor %}
