
directory and GNU autotools setup. Change-Id: I6c59d1297389c9413db0c0b9bdf3b759080bf1b8 Signed-off-by: Ole Troan <ot@cisco.com>
337 lines
10 KiB
C
337 lines
10 KiB
C
/*
|
|
*------------------------------------------------------------------
|
|
* index_list.c - vector-index-based lists. 64-bit pointers suck.
|
|
*
|
|
* Copyright (c) 2008-2009, 2011 Cisco and/or its affiliates.
|
|
* Licensed 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 <stdio.h>
|
|
#include <string.h>
|
|
//#include <clib_lite.h>
|
|
#include <vppinfra/vec.h>
|
|
#include "index_list.h"
|
|
|
|
/*
|
|
* index_slist_addhead
|
|
*
|
|
* args: headp -- pointer to e.g. a hash bucket
|
|
* vector -- vector containing the list
|
|
* elsize -- size of an element in this vector
|
|
* offset -- offset in each vector element of this list thread
|
|
* index_to_add -- index in the vector to add to the list
|
|
*
|
|
* Adds new items to the head of the list. Try not to screw up the args!
|
|
*/
|
|
void index_slist_addhead (index_slist_t *headp,
|
|
u8 *vector, u32 elsize, u32 offset, u32 index_to_add)
|
|
{
|
|
return (index_slist_addhead_inline(headp, vector, elsize, offset,
|
|
index_to_add));
|
|
}
|
|
|
|
/*
|
|
* index_slist_remelem
|
|
*
|
|
* args: headp -- pointer to e.g. a hash bucket
|
|
* vector -- vector containing the list
|
|
* elsize -- size of an element in this vector
|
|
* offset -- offset in each vector element of this list thread
|
|
* index_to_del -- index in the vector to delete from the list
|
|
*
|
|
* Try not to screw up the args!
|
|
*/
|
|
|
|
int index_slist_remelem (index_slist_t *headp,
|
|
u8 *vector, u32 elsize, u32 offset,
|
|
u32 index_to_delete)
|
|
{
|
|
return (index_slist_remelem_inline(headp, vector, elsize, offset,
|
|
index_to_delete));
|
|
}
|
|
|
|
|
|
/*
|
|
* index_dlist_addtail
|
|
*
|
|
* Append the indicated vector element to the doubly-linked list
|
|
* whose first element is pointed to by headp.
|
|
*
|
|
* args: head_index -- listhead vector element index.
|
|
* vector -- vector containing the list
|
|
* elsize -- size of an element in this vector
|
|
* offset -- offset in each vector element of this list thread
|
|
* index_to_add -- index in the vector to add to the list
|
|
*
|
|
* Do not call this routine to create the listhead. Simply set
|
|
* index_dlist->next = index_dlist->prev = index of item.
|
|
*
|
|
* Try not to screw up the args.
|
|
*/
|
|
|
|
void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize,
|
|
u32 offset, u32 index_to_add)
|
|
{
|
|
index_dlist_t *elp;
|
|
index_dlist_t *elp_next;
|
|
index_dlist_t *headp;
|
|
|
|
headp = (index_dlist_t *)(vector + offset + elsize*head_index);
|
|
elp = (index_dlist_t *)(vector + offset + elsize*index_to_add);
|
|
elp->next = index_to_add;
|
|
elp->prev = index_to_add;
|
|
|
|
elp->next = headp->next;
|
|
headp->next = index_to_add;
|
|
|
|
elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next);
|
|
elp->prev = elp_next->prev;
|
|
elp_next->prev = index_to_add;
|
|
}
|
|
|
|
u32 index_dlist_remelem (u32 head_index,
|
|
u8 *vector, u32 elsize, u32 offset,
|
|
u32 index_to_delete)
|
|
{
|
|
u32 rv = head_index;
|
|
index_dlist_t *headp, *elp, *elp_next;
|
|
|
|
elp = (index_dlist_t *)(vector + offset + elsize*index_to_delete);
|
|
|
|
/* Deleting the head index? */
|
|
if (PREDICT_FALSE(head_index == index_to_delete)) {
|
|
rv = elp->next;
|
|
/* The only element on the list? */
|
|
if (PREDICT_FALSE(rv == head_index))
|
|
rv = EMPTY;
|
|
}
|
|
|
|
headp = (index_dlist_t *)(vector + offset + elsize*elp->prev);
|
|
headp->next = elp->next;
|
|
elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next);
|
|
elp_next->prev = elp->prev;
|
|
|
|
elp->next = elp->prev = EMPTY;
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
#ifdef TEST_CODE2
|
|
|
|
typedef struct tv_ {
|
|
char junk[43];
|
|
index_dlist_t l;
|
|
} tv_t;
|
|
|
|
|
|
void index_list_test_cmd(int argc, unsigned long *argv)
|
|
{
|
|
int i, j;
|
|
u32 head_index;
|
|
index_dlist_t *headp;
|
|
tv_t *tp=0;
|
|
|
|
vec_validate(tp, 3);
|
|
head_index = 3;
|
|
|
|
memset(tp, 0xa, sizeof(tp[0])*vec_len(tp));
|
|
|
|
/* Here's how to set up the head element... */
|
|
headp = &((tp + head_index)->l);
|
|
headp->next = headp->prev = head_index;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
printf("headp next %d prev %d\n",
|
|
headp->next, headp->prev);
|
|
for (j = 0; j <= 3; j++) {
|
|
printf ("[%d]: next %d prev %d\n", j,
|
|
tp[j].l.next, tp[j].l.prev);
|
|
}
|
|
printf("---------------\n");
|
|
|
|
}
|
|
|
|
printf("After all adds:\n");
|
|
|
|
printf("headp next %d prev %d\n",
|
|
headp->next, headp->prev);
|
|
|
|
for (j = 0; j <= 3; j++) {
|
|
printf ("[%d]: next %d prev %d\n", j,
|
|
tp[j].l.next, tp[j].l.prev);
|
|
}
|
|
printf("---------------\n");
|
|
|
|
head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]),
|
|
STRUCT_OFFSET_OF(tv_t, l), 1);
|
|
|
|
printf("after delete 1, head index %d\n", head_index);
|
|
headp = &((tp + head_index)->l);
|
|
printf("headp next %d prev %d\n",
|
|
headp->next, headp->prev);
|
|
for (j = 0; j <= 3; j++) {
|
|
printf ("[%d]: next %d prev %d\n", j,
|
|
tp[j].l.next, tp[j].l.prev);
|
|
}
|
|
printf("---------------\n");
|
|
|
|
index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]),
|
|
STRUCT_OFFSET_OF(tv_t, l), 1);
|
|
|
|
printf("after re-add 1, head index %d\n", head_index);
|
|
headp = &((tp + head_index)->l);
|
|
printf("headp next %d prev %d\n",
|
|
headp->next, headp->prev);
|
|
for (j = 0; j <= 3; j++) {
|
|
printf ("[%d]: next %d prev %d\n", j,
|
|
tp[j].l.next, tp[j].l.prev);
|
|
}
|
|
printf("---------------\n");
|
|
|
|
for (i = 3; i >= 0; i--) {
|
|
head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
printf("after delete, head index %d\n", head_index);
|
|
if (head_index != EMPTY) {
|
|
headp = &((tp + head_index)->l);
|
|
printf("headp next %d prev %d\n",
|
|
headp->next, headp->prev);
|
|
for (j = 0; j <= 3; j++) {
|
|
printf ("[%d]: next %d prev %d\n", j,
|
|
tp[j].l.next, tp[j].l.prev);
|
|
}
|
|
} else {
|
|
printf("empty list\n");
|
|
}
|
|
printf("---------------\n");
|
|
}
|
|
}
|
|
#endif /* test code 2 */
|
|
|
|
#ifdef TEST_CODE
|
|
|
|
typedef struct tv_ {
|
|
char junk[43];
|
|
index_slist_t l;
|
|
} tv_t;
|
|
|
|
|
|
void index_list_test_cmd(int argc, unsigned long *argv)
|
|
{
|
|
int i, j;
|
|
tv_t *tp = 0;
|
|
index_slist_t *buckets = 0;
|
|
|
|
vec_add1((u32 *)buckets, EMPTY);
|
|
vec_validate(tp, 9);
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
}
|
|
|
|
printf ("after adds, buckets[0] = %u\n", buckets[0]);
|
|
|
|
for (j = 0; j < 10; j++) {
|
|
printf("tp[%d] next %u\n", j, tp[j].l);
|
|
|
|
}
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i))) {
|
|
printf("OUCH: remelem failure at index %d\n", i);
|
|
}
|
|
if (PREDICT_FALSE(tp[i].l.next != EMPTY)) {
|
|
printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
|
|
}
|
|
}
|
|
|
|
printf ("after deletes, buckets[0] = %x\n", buckets[0]);
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
}
|
|
|
|
printf ("after adds, buckets[0] = %u\n", buckets[0]);
|
|
|
|
for (j = 0; j < 10; j++) {
|
|
printf("tp[%d] next %u\n", j, tp[j].l);
|
|
|
|
}
|
|
|
|
for (i = 9; i >= 0; i--) {
|
|
if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i))) {
|
|
printf("OUCH: remelem failure at index %d\n", i);
|
|
}
|
|
if ((tp[i].l.next != EMPTY)) {
|
|
printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
|
|
}
|
|
}
|
|
|
|
printf ("after deletes, buckets[0] = %x\n", buckets[0]);
|
|
|
|
printf("add evens, then odds...\n");
|
|
|
|
for (i = 0; i < 10; i += 2) {
|
|
index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
|
|
printf ("head = buckets[0].next = %d\n", buckets[0].next);
|
|
for (j = 0; j < 10; j++) {
|
|
printf("tp[%d] next %u\n", j, tp[j].l);
|
|
}
|
|
printf("-------------\n");
|
|
}
|
|
|
|
for (i = 1; i < 10; i += 2) {
|
|
index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i);
|
|
|
|
printf ("head = buckets[0].next = %d\n", buckets[0].next);
|
|
for (j = 0; j < 10; j++) {
|
|
printf("tp[%d] next %u\n", j, tp[j].l);
|
|
}
|
|
printf("-------------\n");
|
|
}
|
|
|
|
printf ("after adds, buckets[0] = %u\n", buckets[0]);
|
|
|
|
for (j = 0; j < 10; j++) {
|
|
printf("tp[%d] next %u\n", j, tp[j].l);
|
|
|
|
}
|
|
|
|
for (i = 9; i >= 0; i--) {
|
|
if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp),
|
|
STRUCT_OFFSET_OF(tv_t, l), i))) {
|
|
printf("OUCH: remelem failure at index %d\n", i);
|
|
}
|
|
if (PREDICT_FALSE(tp[i].l.next != EMPTY)) {
|
|
printf("OUCH: post-remelem next not EMPTY, index %d\n", i);
|
|
}
|
|
}
|
|
|
|
printf ("after deletes, buckets[0] = %x\n", buckets[0]);
|
|
|
|
vec_free(buckets);
|
|
vec_free(tp);
|
|
}
|
|
#endif /* test code */
|