Annotation of mstools/samples/deb/linklist.c, revision 1.1.1.1

1.1       root        1: // ************************************************************************
                      2: // LinkList.C - Ordered Double Linked List Package
                      3: // ************************************************************************
                      4: // PURPOSE: Provide a generalized sorted double linked list package
                      5: //
                      6: // FUNCTIONS:
                      7: //   InitList          - initialize/clear list
                      8: //   CreateNode        - allocate a new node that can be put into list
                      9: //   InsertNode        - insert a new node into the list
                     10: //   DeleteCurrentNode - remove a node from the list
                     11: //   GetNextNode       - get the next (right) node from the CurrentNode
                     12: //   GetPreviousNode   - get the previous (left) node from the
                     13: //                       CurrentNode
                     14: //   GetNode           - get nth Occurence of a node that matches a
                     15: //                       key(s)
                     16: //   GetListError      - get the error value
                     17: //
                     18: // COMMENTS: The application must serialize access to the linked list
                     19: //
                     20: //   Format of the Ordering and Matching functions is as follows:
                     21: //
                     22: //   int OrderFunc( PNODE pNodeOne, PNODE pNodeTwo )
                     23: //   {
                     24: //     if( (pNodeOne->NodeData).Key <  (pNodeTwo->NodeData).Key )
                     25: //       return( LEFT_OF  );
                     26: //     if( (pNodeOne->NodeData).Key == (pNodeTwo->NodeData).Key )
                     27: //       return( MATCH    );
                     28: //     if( (pNodeOne->NodeData).Key  > (pNodeTwo->NodeData).Key )
                     29: //       return( RIGHT_OF );
                     30: //   }
                     31: //
                     32: // ************************************************************************
                     33: #include <StdLib.H>     // malloc(), free()
                     34: #include <StdIO.H>      // printf()
                     35: #include "LinkList.H"
                     36: 
                     37: //-- NULL pointer dereferencing checking macro
                     38: #define CHECH_POINTER( Node )                                  \
                     39:           if( Node == NULL ) {                                 \
                     40:             printf("Attempt to dereference NULL.\n");          \
                     41:             return(pList->ListError = DEREFERENCE_NULL_ERROR); \
                     42:           }
                     43: 
                     44: //-- "member" functions that return the private data
                     45: int   GetListError(   PLIST pList ) { return( pList->ListError );    }
                     46: PNODE GetFirstNode(   PLIST pList ) { return( pList->pFirstNode );   }
                     47: PNODE GetCurrentNode( PLIST pList ) { return( pList->pCurrentNode ); }
                     48: PNODE GetLastNode(    PLIST pList ) { return( pList->pLastNode );    }
                     49: 
                     50: 
                     51: // ************************************************************************
                     52: // FUNCTION : InitList( PLIST pList, int (*)(PNODE, PNODE) )
                     53: // PURPOSE  : initialize/clear list, registers the ordering function
                     54: // COMMENTS :
                     55: // ************************************************************************
                     56: int
                     57: InitList( PLIST pList, int (*OrderFunc)( PNODE pNodeOne, PNODE pNodeTwo ) )
                     58: {
                     59:   PNODE pTempNode;
                     60: 
                     61:   //-- remove all nodes if the list is not empty
                     62:   while( ( (pList->pFirstNode) != NULL) && ( (pList->ListError) == NO_ERROR_FOUND) ) {
                     63:     pTempNode = (pList->pFirstNode);
                     64:     if( DeleteCurrentNode( pList ) < NO_ERROR_FOUND ) {
                     65:       (pList->ListError) = NO_NODE_ERROR;
                     66:       return( pList->ListError );
                     67:     }
                     68:   }
                     69: 
                     70:   //-- initialize the "private" pointers to NULL
                     71:   (pList->pFirstNode)   = NULL;
                     72:   (pList->pCurrentNode) = NULL;
                     73:   (pList->pLastNode)    = NULL;
                     74: 
                     75:   //-- register the link list data ordering function
                     76:   (pList->OrderFunction) = OrderFunc;
                     77: 
                     78:   (pList->ListError)    = NO_ERROR_FOUND;
                     79:   return( pList->ListError );
                     80: }
                     81: 
                     82: 
                     83: // ************************************************************************
                     84: // FUNCTION : CreateNode( PLIST pList, PNODE* )
                     85: // PURPOSE  : create/allocate a new node that can be put into list
                     86: // COMMENTS :
                     87: // ************************************************************************
                     88: int
                     89: CreateNode( PLIST pList, PNODE* ppNewNode )
                     90: {
                     91:   (*ppNewNode) = (PNODE) malloc(sizeof(NODE));
                     92:   if(*ppNewNode == NULL) {
                     93:     printf("malloc failed.\n");
                     94:     (pList->ListError) = NO_NODE_ERROR;
                     95:     return( pList->ListError );
                     96:   }
                     97:   ((*ppNewNode)->pRightLink) = NULL;
                     98:   ((*ppNewNode)->pLeftLink)  = NULL;
                     99: 
                    100:   (pList->ListError)         = NO_ERROR_FOUND;
                    101:   return( pList->ListError );
                    102: }
                    103: 
                    104: 
                    105: // ************************************************************************
                    106: // FUNCTION : InsertNode( PLIST pList, PNODE )
                    107: // PURPOSE  : insert a new node into the list
                    108: // COMMENTS : all nodes must have a unique key entry (from order
                    109: //            function), if a match is found during an insert then the
                    110: //            old node gets replaced with the new node
                    111: //            NOTE: changes pList->pCurrentNode
                    112: // ************************************************************************
                    113: int
                    114: InsertNode( PLIST pList, PNODE pNewNode )
                    115: {
                    116:   int Position;
                    117:   int LastPosition;
                    118: 
                    119:   if( (pList->pFirstNode) == NULL ) {
                    120: 
                    121:     (pList->pFirstNode)   = pNewNode;
                    122:     (pList->pLastNode)    = pNewNode;
                    123:     (pList->pCurrentNode) = pNewNode;
                    124:     (pList->ListError)    = NO_ERROR_FOUND;
                    125: 
                    126:     return( pList->ListError );
                    127:   }
                    128: 
                    129:   Position = (*(pList->OrderFunction))( pNewNode, pList->pCurrentNode );
                    130: 
                    131:   //-- search for insertion point
                    132:   while( (pList->pCurrentNode) != NULL ) {
                    133: 
                    134:     LastPosition = Position;
                    135:     Position = (*(pList->OrderFunction))(pNewNode, pList->pCurrentNode);
                    136: 
                    137:     if( (pList->pFirstNode) == (pList->pLastNode) )
                    138:       break;
                    139: 
                    140:     if( Position != LastPosition )
                    141:       break;
                    142: 
                    143:     if( (pList->pCurrentNode) == (pList->pFirstNode) ) {
                    144:       if( Position == RIGHT_OF ) {
                    145:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
                    146:         continue;
                    147:       }
                    148:       break;
                    149:     }
                    150: 
                    151:     if( (pList->pCurrentNode) == (pList->pLastNode) ) {
                    152:       if( Position == LEFT_OF ) {
                    153:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
                    154:         continue;
                    155:       }
                    156:       break;
                    157:     }
                    158: 
                    159:     if( Position == LastPosition ) {
                    160:       if( Position == LEFT_OF) {
                    161:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
                    162:         continue;
                    163:       }
                    164:       if( Position == RIGHT_OF ) {
                    165:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
                    166:         continue;
                    167:       }
                    168:       break;
                    169:     }
                    170: 
                    171:   }
                    172: 
                    173:   //-- now, insert the pNewNode
                    174:   switch( Position ) {
                    175: 
                    176:     case LEFT_OF:
                    177:       (pNewNode->pRightLink) = (pList->pCurrentNode);
                    178:       (pNewNode->pLeftLink)  = ((pList->pCurrentNode)->pLeftLink);
                    179:       if( (pList->pCurrentNode) == (pList->pFirstNode) )
                    180:         (pList->pFirstNode) = pNewNode;
                    181:       else
                    182:         (((pList->pCurrentNode)->pLeftLink)->pRightLink) = pNewNode;
                    183:       ((pList->pCurrentNode)->pLeftLink)  = pNewNode;
                    184:       break;
                    185: 
                    186:     case RIGHT_OF:
                    187:       (pNewNode->pLeftLink)  = (pList->pCurrentNode);
                    188:       (pNewNode->pRightLink) = ((pList->pCurrentNode)->pRightLink);
                    189:       if( (pList->pCurrentNode) == (pList->pLastNode) )
                    190:         (pList->pLastNode) = pNewNode;
                    191:       else
                    192:         (((pList->pCurrentNode)->pRightLink)->pLeftLink) = pNewNode;
                    193:       ((pList->pCurrentNode)->pRightLink)  = pNewNode;
                    194:       break;
                    195: 
                    196:     case MATCH:
                    197:       (pNewNode->pLeftLink)  = ((pList->pCurrentNode)->pLeftLink);
                    198:       (pNewNode->pRightLink) = ((pList->pCurrentNode)->pRightLink);
                    199:       DestroyNode( pList->pCurrentNode );
                    200:       break;
                    201: 
                    202:   }
                    203:   (pList->pCurrentNode) = pNewNode;
                    204: 
                    205:   (pList->ListError)    = NO_ERROR_FOUND;
                    206:   return( pList->ListError );
                    207: }
                    208: 
                    209: 
                    210: // ************************************************************************
                    211: // FUNCTION : DestroyNode( PNODE )
                    212: // PURPOSE  : deallocates a node
                    213: // COMMENTS :
                    214: // ************************************************************************
                    215: int
                    216: DestroyNode( PNODE pNode )
                    217: {
                    218:   free( pNode );
                    219:   return( 1 );
                    220: }
                    221: 
                    222: 
                    223: // ************************************************************************
                    224: // FUNCTION : DeleteCurrentNode( PLIST pList )
                    225: // PURPOSE  : delete pList->pCurrentNode from the list and deallocate it
                    226: // COMMENTS : changes pList->pCurrentNode. Typically, GetNode is called first so
                    227: //            pList->pCurrentNode points to the correct node
                    228: // ************************************************************************
                    229: int
                    230: DeleteCurrentNode( PLIST pList )
                    231: {
                    232:   PNODE pOldCurrentNode;
                    233: 
                    234:   if( (pList->pCurrentNode) != NULL ) {
                    235:     pOldCurrentNode = (pList->pCurrentNode);
                    236: 
                    237:     if( pOldCurrentNode == (pList->pFirstNode) ) {
                    238:       (pList->pFirstNode)   = (pOldCurrentNode->pRightLink);
                    239:       (pList->pCurrentNode) = (pOldCurrentNode->pRightLink);
                    240:     }
                    241:     else {
                    242:       ((pOldCurrentNode->pLeftLink)->pRightLink) = (pOldCurrentNode->pRightLink);
                    243:       (pList->pCurrentNode) = (pOldCurrentNode->pLeftLink);
                    244:     }
                    245: 
                    246:     if( pOldCurrentNode == (pList->pLastNode) )
                    247:       (pList->pLastNode)    = (pOldCurrentNode->pLeftLink);
                    248:     else
                    249:       ((pOldCurrentNode->pRightLink)->pLeftLink) = (pOldCurrentNode->pLeftLink);
                    250: 
                    251:     DestroyNode( pOldCurrentNode );
                    252: 
                    253:     (pList->ListError) = NO_ERROR_FOUND;
                    254:     return( pList->ListError );
                    255:   }
                    256: 
                    257:   (pList->ListError) = NO_ERROR_FOUND;
                    258:   return( pList->ListError );
                    259: }
                    260: 
                    261: 
                    262: // ************************************************************************
                    263: // FUNCTION : GetNextNode( PLIST pList, PNODE* )
                    264: // PURPOSE  : get the next (right) node from the pList->pCurrentNode
                    265: // COMMENTS : Does not change pList->pCurrentNode
                    266: // ************************************************************************
                    267: int
                    268: GetNextNode( PLIST pList, PNODE* ppNode )
                    269: {
                    270:   CHECH_POINTER( ppNode );
                    271:   if( ((*ppNode)->pRightLink) == NULL )
                    272:     return( (pList->ListError) = NO_NEXT_NODE_ERROR );
                    273:   (*ppNode) = ((*ppNode)->pRightLink);
                    274: 
                    275:   (pList->ListError) = NO_ERROR_FOUND;
                    276:   return( pList->ListError );
                    277: }
                    278: 
                    279: 
                    280: // ************************************************************************
                    281: // FUNCTION : GetPreviousNode( PLIST pList, PNODE* )
                    282: // PURPOSE  : get the previous (left) node from the pList->pCurrentNode
                    283: // COMMENTS : Does not change pList->pCurrentNode
                    284: // ************************************************************************
                    285: int
                    286: GetPreviousNode( PLIST pList, PNODE* ppNode )
                    287: {
                    288:   CHECH_POINTER( ppNode );
                    289:   if( ((*ppNode)->pLeftLink) == NULL )
                    290:     return( (pList->ListError) = NO_PREV_NODE_ERROR);
                    291:   (*ppNode) = ((*ppNode)->pLeftLink);
                    292: 
                    293:   (pList->ListError) = NO_ERROR_FOUND;
                    294:   return( pList->ListError );
                    295: }
                    296: 
                    297: 
                    298: // ************************************************************************
                    299: // FUNCTION : GetNode( PLIST pList, PNODE*, int (*)(PNODE, PNODE), int )
                    300: // PURPOSE  : get nth Occurence of a node from the list that matches a
                    301: //            key(s).
                    302: // COMMENTS : may use the ordering function or a new matching function
                    303: //            if not searching for a match based on the primary
                    304: //            ordering key.  Note: the matching and ordering functions
                    305: //            have the same definition.
                    306: //            NOTE: changes pList->pCurrentNode
                    307: // ************************************************************************
                    308: int
                    309: GetNode( PLIST pList, PNODE* ppKeyNode,
                    310:          int  (*MatchFunction)( PNODE pNodeOne, PNODE pNodeTwo ),
                    311:          int  Occurence )
                    312: {
                    313:   int Position;
                    314: 
                    315:   //-- if match and order are same function
                    316:   if( MatchFunction == (pList->OrderFunction) ) {
                    317:     int  LastPosition;
                    318: 
                    319:     Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
                    320:     LastPosition = Position;
                    321: 
                    322:     while( Occurence ) {
                    323:       if( (Position == LEFT_OF) && (LastPosition == LEFT_OF)
                    324:           && ( (pList->pCurrentNode) != (pList->pFirstNode) ) )
                    325:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pLeftLink);
                    326:       else if( (Position == RIGHT_OF) && (LastPosition == RIGHT_OF)
                    327:             && ( (pList->pCurrentNode) != (pList->pLastNode) ) )
                    328:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
                    329:       else {
                    330:         Occurence--;
                    331:         continue;
                    332:       }
                    333:       LastPosition = Position;
                    334:       Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
                    335:     }
                    336: 
                    337:   }
                    338:   else {  // match and order are not the same function, thus start
                    339:           // the search at the front of the list
                    340:     (pList->pCurrentNode) = (pList->pFirstNode);
                    341: 
                    342:     while( (Occurence > 0) && ( (pList->pCurrentNode) != NULL)) {
                    343:       Position = (*MatchFunction)(*ppKeyNode, pList->pCurrentNode);
                    344:       if(Position == MATCH)
                    345:         Occurence--;
                    346:       if(Occurence > 0 )
                    347:         (pList->pCurrentNode) = ((pList->pCurrentNode)->pRightLink);
                    348:     }
                    349: 
                    350:   }
                    351: 
                    352:   if( (Position == MATCH) && (Occurence == 0) ) {
                    353:     *ppKeyNode = (pList->pCurrentNode);
                    354: 
                    355:     (pList->ListError) = NO_ERROR_FOUND;
                    356:     return( pList->ListError );
                    357:   }
                    358: 
                    359:   (pList->ListError) = NO_MATCH_ERROR;
                    360:   return( pList->ListError );
                    361: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.