
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */  
#include <guththila_namespace.h>
#include <guththila_stack.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int GUTHTHILA_CALL
guththila_namespace_list_grow(guththila_namespace_list_t * namesp_list,int addition,const axutil_env_t * env) 
{
    int i = 0;
    if (addition > 0 || (addition < 0 && namesp_list->capacity + addition > 0 &&
          namesp_list->capacity + addition >= namesp_list->size))
    {
            namesp_list->list =
            (guththila_namespace_t *) realloc(namesp_list->list,
                                              sizeof(guththila_namespace_t) *
                                              (namesp_list->capacity + addition));
        if (namesp_list->list)
        {
            for (i = namesp_list->capacity;i < namesp_list->capacity + addition; i++)
            {
                guththila_stack_push(&namesp_list->fr_stack,namesp_list->list + i, env);
            }
            namesp_list->capacity += addition;
        }
        else
        {
            return GUTHTHILA_FAILURE;
        }
    }
    return 0;
}

guththila_namespace_list_t *GUTHTHILA_CALL
guththila_namespace_list_create(const axutil_env_t * env) 
{
    int i = 0;
    guththila_namespace_list_t * namesp_list =
        (guththila_namespace_list_t *) AXIS2_MALLOC(env->allocator,sizeof(guththila_namespace_list_t));

    if (!namesp_list)
        return NULL;

    namesp_list->list =
        (guththila_namespace_t *) AXIS2_MALLOC(env->allocator,sizeof(guththila_namespace_t) *
                                               GUTHTHILA_NAMESPACE_DEF_SIZE);

    if (namesp_list->list && guththila_stack_init(&namesp_list->fr_stack, env))
    {
        namesp_list->capacity = GUTHTHILA_NAMESPACE_DEF_SIZE;
        namesp_list->size = 0;
        for (i = 0; i < GUTHTHILA_NAMESPACE_DEF_SIZE; i++)
        {
            guththila_stack_push(&namesp_list->fr_stack, namesp_list->list + i,env);
        }
        return namesp_list;
    }
    return NULL;
}

int GUTHTHILA_CALL
guththila_namespace_list_init(guththila_namespace_list_t * namesp_list,const axutil_env_t * env) 
{
    int i = 0;
    namesp_list->list =
        (guththila_namespace_t *) AXIS2_MALLOC(env->allocator,
                                               sizeof(guththila_namespace_t) *
                                               GUTHTHILA_NAMESPACE_DEF_SIZE);
    if (namesp_list->list && guththila_stack_init(&namesp_list->fr_stack, env))
    {
        namesp_list->capacity = GUTHTHILA_NAMESPACE_DEF_SIZE;
        namesp_list->size = 0;
        for (i = 0; i < GUTHTHILA_NAMESPACE_DEF_SIZE; i++)
        {
            guththila_stack_push(&namesp_list->fr_stack, namesp_list->list + i,env);
        }
        return GUTHTHILA_SUCCESS;
    }
    return GUTHTHILA_FAILURE;
}

guththila_namespace_t *GUTHTHILA_CALL
guththila_namespace_list_get(guththila_namespace_list_t *namesp_list,const axutil_env_t * env) 
{
    if (namesp_list->fr_stack.top > 0 ||guththila_namespace_list_grow(namesp_list,GUTHTHILA_NAMESPACE_DEF_SIZE, env))
    {
        return guththila_stack_pop(&namesp_list->fr_stack, env);
    }
    return NULL;
}

int GUTHTHILA_CALL
guththila_namespace_list_release(guththila_namespace_list_t * namesp_list,guththila_namespace_t * namespace,
				 const axutil_env_t * env) 
{
    return guththila_stack_push(&namesp_list->fr_stack, namespace, env);
}

void GUTHTHILA_CALL
msuila_namespace_list_free_data(guththila_namespace_list_t * namesp_list,const axutil_env_t * env) 
{
    AXIS2_FREE(env->allocator, namesp_list->list);
    guththila_stack_un_init(&namesp_list->fr_stack, env);
} 

void GUTHTHILA_CALL
guththila_namespace_list_free(guththila_namespace_list_t * namesp_list,const axutil_env_t * env) 
{

    guththila_stack_un_init(&namesp_list->fr_stack, env);
    AXIS2_FREE(env->allocator, namesp_list->list);
    AXIS2_FREE(env->allocator, namesp_list);
} 
