Home | History | Annotate | Download | only in src
      1 /*---------------------------------------------------------------------------*
      2  *  linklist_impl.c  *
      3  *                                                                           *
      4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
      5  *                                                                           *
      6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
      7  *  you may not use this file except in compliance with the License.         *
      8  *                                                                           *
      9  *  You may obtain a copy of the License at                                  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
     11  *                                                                           *
     12  *  Unless required by applicable law or agreed to in writing, software      *
     13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
     15  *  See the License for the specific language governing permissions and      *
     16  *  limitations under the License.                                           *
     17  *                                                                           *
     18  *---------------------------------------------------------------------------*/
     19 
     20 
     21 
     22 #include <stdlib.h>
     23 
     24 #include "pmemory.h"
     25 #include "plog.h"
     26 
     27 #include "linklist.h"
     28 
     29 extern void *lts_alloc(int num, int size);
     30 
     31 
     32 /* very simple static memory allocation:
     33    1. pool of linked list nodes - from static allocated array
     34    2. each node is marked "used" when allocated; marked "unused" when deallocated
     35    3. since the stress linked lists deal with single words, an array will suffice.
     36 */
     37 
     38 #ifdef USE_STATIC_SLTS
     39 #define NUM_ALLOC_NODES 30  /* Max 30 syllables per word */
     40 
     41 typedef struct LNodeAllocElement
     42 {
     43   LNode node;
     44   short usedflag;
     45 } LNodeAllocElement;
     46 
     47 static LNodeAllocElement g_LNodeAllocArray[NUM_ALLOC_NODES];
     48 
     49 void ClearLNodeArray()
     50 {
     51   int i;
     52   LNode *n;
     53 
     54   for(i=0; i<NUM_ALLOC_NODES; i++){
     55     g_LNodeAllocArray[i].usedflag = 0;
     56     n = &(g_LNodeAllocArray[i].node);
     57     n->data = 0;
     58     n->next = n->prev = 0;
     59   }
     60 }
     61 
     62 static LNode *AllocNode()
     63 {
     64   int i;
     65 
     66   /* return first unused element */
     67   for(i=0; i<NUM_ALLOC_NODES; i++){
     68     if(g_LNodeAllocArray[i].usedflag == 0){
     69       g_LNodeAllocArray[i].usedflag = 1;
     70 
     71 	  /* zero out the node first*/
     72 	  (g_LNodeAllocArray[i].node).data = NULL;
     73 	  (g_LNodeAllocArray[i].node).prev = NULL;
     74 	  (g_LNodeAllocArray[i].node).next = NULL;
     75 
     76       return &(g_LNodeAllocArray[i].node);
     77     }
     78   }
     79   /* ran out of nodes */
     80   return NULL;
     81 }
     82 
     83 static void FreeNode(LNode *n)
     84 {
     85   int i;
     86   long addr;
     87 
     88   /* compare addresses of pointers */
     89   for(i=0; i<NUM_ALLOC_NODES; i++){
     90     addr = (long) (&(g_LNodeAllocArray[i].node));
     91     if(addr == (long)n){
     92       g_LNodeAllocArray[i].usedflag = 0;
     93       return;
     94     }
     95   }
     96 
     97   /* not found. don't do anything */
     98    return;
     99 }
    100 
    101 
    102 #else /* !USE_STATIC_SLTS */
    103 
    104 static LNode *AllocNode()
    105 {
    106   return (LNode *)lts_alloc(1, sizeof(LNode));
    107 }
    108 static void FreeNode(LNode *n)
    109 {
    110   FREE(n);
    111 }
    112 
    113 #endif
    114 
    115 
    116 
    117 /* Inserts after current element
    118    At return, current element will be point to newly created node
    119 
    120    handle static allocation later - possibly using a pool of nodes?
    121    For now, dynamically allocate a new list node with the data
    122 */
    123 LListResult Insert(LList *list, void *data)
    124 {
    125   LNode *newnode = AllocNode();
    126   if(newnode == NULL){
    127      return LListResourceAllocError;
    128   }
    129   newnode->data = data;
    130 
    131   if(list->head == NULL){
    132     /* if list is empty, assign to head */
    133     list->head = newnode;
    134     (list->head)->next = NULL;
    135     (list->head)->prev = NULL;
    136 
    137     /* update curr to newly inserted node */
    138     list->curr = list->head;
    139     list->tail = list->head;
    140     return LListSuccess;
    141   }
    142 
    143     /* curr not specified, insert from the end */
    144   if(list->curr == NULL){
    145     list->curr = list->tail;
    146   }
    147 
    148   /* in cases with single node, default to insert at end */
    149   if(list->curr == list->tail){
    150     /* insert at the end */
    151     newnode->prev = list->curr;
    152     newnode->next = NULL;
    153     (list->curr)->next = newnode;
    154 
    155     /* update both curr and end */
    156     list->curr = newnode;
    157     list->tail = newnode;
    158     return LListSuccess;
    159 
    160   }else if(list->curr == list->head){
    161     /* insert at head */
    162     newnode->next = list->head;
    163     newnode->prev = NULL;
    164     (list->head)->prev = newnode;
    165 
    166     /* update curr to newly inserted node */
    167     list->curr = list->head;
    168     list->head = newnode;
    169 
    170     return LListSuccess;
    171 
    172   }else{
    173     /* insert somewhere in middle */
    174     newnode->prev = list->curr;
    175     newnode->next = (list->curr)->next;
    176     (list->curr)->next = newnode;
    177     (newnode->next)->prev = newnode;
    178 
    179     /* update curr to newly inserted node */
    180     list->curr = newnode;
    181     return LListSuccess;
    182   }
    183 }
    184 
    185 /* Deletes at current element
    186    At return, current element will point to previous node
    187 
    188    handle static deallocation later - possibly using a pool of nodes?
    189    For now, dynamically free a new list node
    190 */
    191 
    192 LListResult Delete(LList *list)
    193 {
    194   LNode *curr;
    195 
    196   if(list->head == NULL){
    197     return LListEmpty;
    198   }
    199 
    200   /* start deleting from the end if curr not specified */
    201   if(list->curr == NULL){
    202     list->curr = list->tail;
    203   }
    204 
    205   curr = list->curr;
    206 
    207   if(curr == list->head){
    208   /* delete from the head */
    209     list->head = curr->next;
    210 
    211     if(list->head != NULL){
    212       (list->head)->prev = NULL;
    213     }
    214 
    215     FreeNode(curr);
    216     list->curr = list->head;
    217     return LListSuccess;
    218 
    219   }else if(curr == list->tail){
    220     /* delete from the end */
    221     list->tail = curr->prev;
    222 
    223     if(list->tail != NULL){
    224       (list->tail)->next = NULL;
    225     }
    226 
    227     FreeNode(curr);
    228     list->curr = list->tail;
    229     return LListSuccess;
    230 
    231   }else{
    232     /* delete somewhere in the middle */
    233     list->curr = curr->next;
    234 
    235     /* still check, just in case*/
    236     if(curr->next != NULL){
    237       (curr->next)->prev = curr->prev;
    238     }
    239     if(curr->prev != NULL){
    240       (curr->prev)->next = curr->next;
    241     }
    242 
    243     FreeNode(curr);
    244     return LListSuccess;
    245   }
    246 }
    247 
    248