blob: ba152b4ccbfb058079fb845d0a8c4bcb9cb906ba [file] [log] [blame]
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "sw.h"
#include "util.h"
static sll_node_t *
sll_nd_new(sll_head_t * sll)
{
sll_node_t *new_nd;
if (LL_FIX_NDNR & sll->flag)
{
if (NULL == sll->free_nd)
{
new_nd = NULL;
}
else
{
new_nd = sll->free_nd;
sll->free_nd = sll->free_nd->next;
}
}
else
{
new_nd = aos_mem_alloc(sizeof (sll_node_t));
}
if (NULL != new_nd)
{
aos_mem_zero(new_nd, sizeof (sll_node_t));
}
return new_nd;
}
static void
sll_nd_free(sll_head_t * sll, sll_node_t * nd)
{
if (LL_FIX_NDNR & sll->flag)
{
nd->next = sll->free_nd;
sll->free_nd = nd;
}
else
{
aos_mem_free(nd);
}
return;
}
//#define SLL_DENUG
#ifdef SLL_DENUG
static void
sll_nd_dump(sll_head_t * sll, const char * info)
{
sll_node_t * curr;
if (NULL == sll->nd_dump)
{
return;
}
aos_printk("\n%s node number = %d\n", info, sll->nd_nr);
curr = sll->fst_nd;
while (NULL != curr)
{
sll->nd_dump(curr->data);
curr = curr->next;
}
}
#else
#define sll_nd_dump(sll, info)
#endif
sll_head_t *
sll_creat(ll_nd_cmp cmp_func, ll_nd_dump dump_func, a_uint32_t flag, a_uint32_t nd_nr)
{
sll_head_t *head;
sll_node_t *node;
a_uint32_t i, size;
if (flag & LL_FIX_NDNR)
{
size = sizeof (sll_head_t) + sizeof (sll_node_t) * nd_nr;
}
else
{
size = sizeof (sll_head_t);
}
head = aos_mem_alloc(size);
if (NULL == head)
{
return NULL;
}
aos_mem_zero(head, size);
head->fst_nd = NULL;
head->nd_nr = 0;
head->flag = flag;
head->nd_cmp = cmp_func;
head->nd_dump = dump_func;
head->free_nd = NULL;
if (flag & LL_FIX_NDNR)
{
node = (sll_node_t *) ((a_uint8_t *) head + sizeof (sll_head_t));
for (i = 0; i < nd_nr; i++)
{
node[i].next = head->free_nd;
head->free_nd = &(node[i]);
}
}
return head;
}
void
sll_destroy(sll_head_t * sll)
{
aos_mem_free(sll);
return;
}
void
sll_lock(sll_head_t * sll)
{
return;
}
void
sll_unlock(sll_head_t * sll)
{
return;
}
void *
sll_nd_find(const sll_head_t *sll, void *data, a_ulong_t *iterator)
{
sll_node_t *node;
ll_cmp_rslt_t rslt;
node = sll->fst_nd;
while (NULL != node)
{
rslt = sll->nd_cmp(node->data, data);
if (LL_CMP_EQUAL == rslt)
{
*iterator = (a_ulong_t)node;
return node->data;
}
if ((LL_CMP_GREATER == rslt) && (sll->flag & LL_IN_ORDER))
{
return NULL;
}
node = node->next;
}
return NULL;
}
void *
sll_nd_next(const sll_head_t *sll, a_ulong_t *iterator)
{
sll_node_t *curr = NULL;
if (0 == *iterator)
{
if (NULL != sll->fst_nd)
{
curr = sll->fst_nd;
}
}
else
{
curr = ((sll_node_t *)(*iterator))->next;
}
if (NULL == curr)
{
return NULL;
}
else
{
*iterator = (a_ulong_t)curr;
return curr->data;
}
}
sw_error_t
sll_nd_insert(sll_head_t * sll, void *data)
{
sll_node_t *node = NULL;
sll_node_t *curr = NULL;
sll_node_t *prev;
ll_cmp_rslt_t rslt;
sll_nd_dump(sll, "sll_nd_insert before insert");
node = sll_nd_new(sll);
if (NULL == node)
{
return SW_NO_RESOURCE;
}
node->data = data;
if ((NULL == sll->fst_nd)
|| (0 == (sll->flag & LL_IN_ORDER)))
{
node->next = sll->fst_nd;
sll->fst_nd = node;
sll->nd_nr++;
sll_nd_dump(sll, "sll_nd_insert after insert");
return SW_OK;
}
curr = sll->fst_nd;
prev = NULL;
while (NULL != curr)
{
rslt = sll->nd_cmp(curr->data, data);
if (LL_CMP_EQUAL == rslt)
{
sll_nd_free(sll, node);
return SW_ALREADY_EXIST;
}
if (LL_CMP_GREATER == rslt)
{
break;
}
prev = curr;
curr = curr->next;
}
if (NULL == prev)
{
node->next = sll->fst_nd;
sll->fst_nd = node;
}
else
{
prev->next = node;
node->next = curr;
}
sll->nd_nr++;
sll_nd_dump(sll, "sll_nd_insert after insert");
return SW_OK;
}
sw_error_t
sll_nd_delete(sll_head_t * sll, void *data)
{
sll_node_t *curr;
sll_node_t *prev = NULL;
ll_cmp_rslt_t rslt;
sll_nd_dump(sll, "sll_nd_delete before delete");
curr = sll->fst_nd;
while (NULL != curr)
{
rslt = sll->nd_cmp(curr->data, data);
if (LL_CMP_EQUAL == rslt)
{
if (NULL != prev)
{
prev->next = curr->next;
}
else
{
sll->fst_nd = curr->next;
}
sll->nd_nr--;
sll_nd_free(sll, curr);
sll_nd_dump(sll, "sll_nd_delete after delete");
return SW_OK;
}
if ((LL_CMP_GREATER == rslt) && (sll->flag & LL_IN_ORDER))
{
return SW_NOT_FOUND;
}
prev = curr;
curr = curr->next;
}
return SW_NOT_FOUND;
}
#define ID_SIZE_U8 0x1
#define ID_SIZE_U16 0x2
#define ID_SIZE_U32 0x4
#define ID_NR_IN_U8 256
#define ID_NR_IN_U16 65536
sid_pool_t *
sid_pool_creat(a_uint32_t id_nr, a_uint32_t min_id)
{
sid_pool_t * pool;
a_uint32_t size;
a_uint32_t id_size;
a_uint32_t i;
if (0 == id_nr)
{
return NULL;
}
pool = aos_mem_alloc(sizeof(sid_pool_t));
if (NULL == pool)
{
return NULL;
}
aos_mem_zero(pool, sizeof(sid_pool_t));
pool->id_min = min_id;
pool->id_nr = id_nr;
pool->id_ptr = 0;
if (ID_NR_IN_U8 >= id_nr)
{
size = ((id_nr + 3) >> 2) << 2;
id_size = ID_SIZE_U8;
}
else if (ID_NR_IN_U16 >= id_nr)
{
size = ((id_nr + 1) >> 1) << 2;
id_size = ID_SIZE_U16;
}
else
{
size = id_nr << 2;
id_size = ID_SIZE_U32;
}
pool->id_size = id_size;
pool->id_pool = aos_mem_alloc(size);
if (NULL == pool->id_pool)
{
aos_mem_free(pool);
return NULL;
}
aos_mem_zero(pool->id_pool, size);
if (ID_SIZE_U8 == id_size)
{
a_uint8_t *p_id;
p_id = pool->id_pool;
for (i = 0; i < id_nr; i++)
{
p_id[i] = i;
}
}
else if (ID_SIZE_U16 == id_size)
{
a_uint16_t *p_id;
p_id = pool->id_pool;
for (i = 0; i < id_nr; i++)
{
p_id[i] = i;
}
}
else
{
a_uint32_t *p_id;
p_id = pool->id_pool;
for (i = 0; i < id_nr; i++)
{
p_id[i] = i;
}
}
return pool;
}
void
sid_pool_destroy(sid_pool_t * pool)
{
aos_mem_free(pool->id_pool);
aos_mem_free(pool);
return;
}
sw_error_t
sid_pool_id_alloc(sid_pool_t * pool, a_uint32_t * id)
{
if (pool->id_nr <= pool->id_ptr)
{
return SW_NO_RESOURCE;
}
if (ID_SIZE_U8 == pool->id_size)
{
a_uint8_t *p_id;
p_id = pool->id_pool;
*id = p_id[pool->id_ptr] + pool->id_min;
}
else if (ID_SIZE_U16 == pool->id_size)
{
a_uint16_t *p_id;
p_id = pool->id_pool;
*id = p_id[pool->id_ptr] + pool->id_min;
}
else
{
a_uint32_t *p_id;
p_id = pool->id_pool;
*id = p_id[pool->id_ptr] + pool->id_min;
}
pool->id_ptr++;
return SW_OK;
}
sw_error_t
sid_pool_id_free(sid_pool_t * pool, a_uint32_t id)
{
if (0 == pool->id_ptr)
{
return SW_FAIL;
}
pool->id_ptr--;
if (ID_SIZE_U8 == pool->id_size)
{
a_uint8_t *p_id;
if (ID_NR_IN_U8 < (id - id - pool->id_min))
{
return SW_FAIL;
}
p_id = pool->id_pool;
p_id[pool->id_ptr] = id - pool->id_min;
}
else if (ID_SIZE_U16 == pool->id_size)
{
a_uint16_t *p_id;
if (ID_NR_IN_U16 < (id - id - pool->id_min))
{
return SW_FAIL;
}
p_id = pool->id_pool;
p_id[pool->id_ptr] = id - pool->id_min;
}
else
{
a_uint32_t *p_id;
p_id = pool->id_pool;
p_id[pool->id_ptr] = id - pool->id_min;
}
return SW_OK;
}