Annotation of mstools/samples/sdktools/windiff/list.h, revision 1.1.1.1

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /*
                     13:  * LIST.H
                     14:  */
                     15: /*------------------------------------------------------------------------
                     16: | Abstract data type LIST OF (*untyped*) object.
                     17: | Different lists can have different types of object in them
                     18: | Different items in a list can have different types of object in them.
                     19: | The price of this lack of typing is that you have a slightly more
                     20: | awkward syntax and you get no help from the compiler if you try to
                     21: | put the wrong type of data into the list.
                     22: |
                     23: | The list is implemented as a collection of items.  Within the item
                     24: | somewhere is the object.
                     25: |
                     26: | Objects are stored UNALIGNED within items.
                     27: |
                     28: | Use:
                     29: |
                     30: |   #include <list.h>
                     31: |   . . .
                     32: |   LIST MyList; (* or LIST liMyList for Hungarians *)
                     33: |   . . .
                     34: |   MyList = List_Create();
                     35: |   List_AddLast(MyList,&MyObject,sizeof(OBJECT));
                     36: |
                     37: | In the abstract a LIST is a list of objects.  The representation
                     38: | is a linked collection of items.  The manner of the linking is
                     39: | implementation dependent (as I write this it's linear but when you
                     40: | read it it might be a tree (See Knuth for why a tree)).
                     41: |
                     42: | A LIST is a "handle" for a list which may be thought of as a POINTER
                     43: | (whether it is really a pointer or not is implementation dependent)
                     44: | so that it can be copied at the risk of creating an alias. e.g.
                     45: |
                     46: |   L = List_Create();
                     47: |   L1 = L;             (* L and L1 are both healthy and empty *)
                     48: |   List_AddFirst(L, &elem, sizeof(elem));
                     49: |   (* L1 may also appear to have one object, there again it may be sick *)
                     50: |   L1 = L;               (* Now they both surely see the one element *)
                     51: |   List_Destroy(&L1);    (* L is almost certainly sick now too *)
                     52: |   L1 = List_Create();   (* All bets off as to what L is like now
                     53: |                            but L1 is empty and healthy
                     54: |                         *)
                     55: |
                     56: | If two handles compare equal then the lists must be equal, but
                     57: | unequal handles could address two similar lists i.e. the same list
                     58: | of objects held in two different LISTs of items (like pointers).
                     59: |
                     60: | A LIST can be transferred from one variable to another like this:
                     61: |
                     62: |   NewList = OldList;           (* copy the handle *)
                     63: |   OldList = List_Create();     (* kill the old alias *)
                     64: |
                     65: | and the Create statement can be omitted if OldList is never touched again.
                     66: |
                     67: | Items are identified by Cursors.  A cursor is the address of an object
                     68: | within an item in the list. i.e. it is the address of the piece of your
                     69: | data that you had inserted.  (It is probably NOT the address of the item).
                     70: | It is typed as pointer to void here, but you should declare it as a pointer
                     71: | to whatever sort of object you are putting in the LIST.
                     72: |
                     73: | The operations AddFirst, AddLast, AddAfter and AddBefore
                     74: | all copy elements by direct assignment.  If an element is itself
                     75: | a complex structure (say a tree) then this will only copy a pointer
                     76: | or an anchor block or whatever and give all the usual problems of
                     77: | aliases.  Clear will make the list empty, but will only free the
                     78: | storage that it can "see" directly.  SplitBefore or Split After may
                     79: | also perform a Clear operation.  To deal with fancy data structures
                     80: | use New rather than Add calls and copy the data yourself
                     81: |   e.g.  P = List_NewLast(MyList, sizeof(MyArray[14])*(23-14+1));
                     82: |         CopyArraySlice(P, MyArray, 14, 23);
                     83: |
                     84: | The operations NewFirst, NewLast, NewAfter, NewBefore, First and Last
                     85: | all return pointers to elements and thus allow you to do any copying.
                     86: | This is how you might copy a whole list of fancy structures:
                     87: |
                     88: |    void CopyFancyList(LIST * To, LIST From)
                     89: |             (* Assumes that To has been Created and is empty *)
                     90: |    { PELEMENT Cursor;
                     91: |      PELEMENT P;
                     92: |
                     93: |      List_TRAVERSE(From, Cursor);
                     94: |      { P = List_NewLast(To, sizeof(element) );
                     95: |        FancyCopy(P, Cursor);    (* Copy so that *Cursor==*P afterwords *)
                     96: |      }
                     97: |    }
                     98:  --------------------------------------------------------------------*/
                     99: 
                    100:   typedef struct item_tag FAR * LIST;
                    101:   typedef LIST FAR * PLIST;
                    102: 
                    103:   void APIENTRY List_Init(void);
                    104:   /* MUST BE CALLED BEFORE ANY OF THE OTHER FUNCTIONS. */
                    105: 
                    106:   void APIENTRY List_Dump(LPSTR Header, LIST lst);
                    107:   /* Dump the internals to current output stream -- debug only */
                    108: 
                    109:   void APIENTRY List_Show(LIST lst);
                    110:   /* Dump hex representation of handle to current out stream -- debug only */
                    111: 
                    112:   LIST APIENTRY List_Create(void);
                    113:   /* Create a list.  It will be initially empty */
                    114: 
                    115:   void APIENTRY List_Destroy(PLIST plst);
                    116:   /* Destroy *plst.  It does not need to be empty first.
                    117:   |  All storage directly in the list wil be freed.
                    118:   */
                    119: 
                    120:   void APIENTRY List_AddFirst(LIST lst, LPVOID pObject, UINT uLen);
                    121:   /* Add an item holding Object to the beginning of * plst */
                    122: 
                    123:   LPVOID APIENTRY List_NewFirst(LIST lst, UINT uLen);
                    124:   /* Return the address of the place for Len bytes of data in a new
                    125:   |  item at the start of *plst
                    126:   */
                    127: 
                    128:   void APIENTRY List_DeleteFirst(LIST lst);
                    129:   /* Delete the first item in lst.  Error if lst is empty */
                    130: 
                    131:   void APIENTRY List_AddLast(LIST lst, LPVOID pObject, UINT uLen);
                    132:   /* Add an item holding Object to the end of lst */
                    133: 
                    134:   LPVOID APIENTRY List_NewLast(LIST lst, UINT uLen);
                    135:   /* Return the address of the place for uLen bytes of data in a new
                    136:   |  item at the end of lst
                    137:   */
                    138: 
                    139:   void APIENTRY List_DeleteLast(LIST lst);
                    140:   /* Delete the last item in lst.  Error if lst is empty */
                    141: 
                    142:   void APIENTRY List_AddAfter( LIST lst
                    143:                     , LPVOID Curs
                    144:                     , LPVOID pObject
                    145:                     , UINT uLen
                    146:                     );
                    147:   /*--------------------------------------------------------------------
                    148:   | Add an item holding *pObject to lst immediately after Curs.
                    149:   | List_AddAfter(lst, NULL, pObject, Len) adds it to the start of the lst
                    150:    ---------------------------------------------------------------------*/
                    151: 
                    152:   LPVOID APIENTRY List_NewAfter(LIST lst, LPVOID Curs, UINT uLen);
                    153:   /*--------------------------------------------------------------------
                    154:   | Return the address of the place for uLen bytes of data in a new
                    155:   | item immediately after Curs.
                    156:   | List_NewAfter(Lst, NULL, uLen) returns a pointer
                    157:   | to space for uLen bytes in a new first element.
                    158:    ---------------------------------------------------------------------*/
                    159: 
                    160:   void APIENTRY List_AddBefore( LIST lst
                    161:                      , LPVOID Curs
                    162:                      , LPVOID pObject
                    163:                      , UINT uLen
                    164:                      );
                    165:   /*--------------------------------------------------------------------
                    166:   | Add an item holding Object to lst immediately before Curs.
                    167:   | List_AddBefore(Lst, NULL, Object, uLen) adds it to the end of the list
                    168:    ---------------------------------------------------------------------*/
                    169: 
                    170:   LPVOID APIENTRY List_NewBefore(LIST lst, LPVOID Curs, UINT uLen );
                    171:   /*--------------------------------------------------------------------
                    172:   | Return the address of the place for uLen bytes of data in a new
                    173:   | item immediately before Curs.
                    174:   | List_NewBefore(Lst, NULL, uLen) returns a pointer
                    175:   | to space for uLen bytes in a new last element.
                    176:    ---------------------------------------------------------------------*/
                    177: 
                    178:   void APIENTRY List_Delete(LPVOID Curs);
                    179:   /*------------------------------------------------------------------
                    180:   | Delete the item that Curs identifies.
                    181:   | This will be only a few (maybe as little as 3) machine instructions
                    182:   | quicker than DeleteAndNext or DeleteAndPrev but leaves Curs dangling.
                    183:   | It is therefore NOT usually to be preferred.
                    184:   | It may be useful when you have a function which returns an LPVOID
                    185:   | since the argument does not need to be a variable.
                    186:   |     Trivial example: List_Delete(List_First(L));
                    187:    -------------------------------------------------------------------*/
                    188: 
                    189:   int APIENTRY List_ItemLength(LPVOID Curs);
                    190:   /* Return the length of the object identified by the cursor Curs */
                    191: 
                    192:   /*------------------------------------------------------------------
                    193:   | TRAVERSING THE ULIST
                    194:   |
                    195:   | LIST lst;
                    196:   | object * Curs;
                    197:   | . . .
                    198:   | Curs = List_First(lst);
                    199:   | while (Curs!=NULL)
                    200:   | {  DoSomething(*Curs);   (* Curs points to YOUR data not to chain ptrs *)
                    201:   |    Curs = List_Next(Curs);
                    202:   | }
                    203:   |
                    204:   | This is identically equal to
                    205:   | List_TRAVERSE(lst, Curs)  // note NO SEMI COLON!
                    206:   | {  DoSomething(*Curs); }
                    207:    -------------------------------------------------------------------*/
                    208: 
                    209:   #define List_TRAVERSE(lst, curs)  for(  curs=List_First(lst)            \
                    210:                                        ;  curs!=NULL                      \
                    211:                                        ;  curs = List_Next((LPVOID)curs)  \
                    212:                                        )
                    213: 
                    214:   LPVOID APIENTRY List_First(LIST lst);
                    215:   /*------------------------------------------------------------------
                    216:   | Return the address of the first object in lst
                    217:   |  If lst is empty then Return NULL.
                    218:   --------------------------------------------------------------------*/
                    219: 
                    220:   LPVOID APIENTRY List_Last(LIST lst);
                    221:   /*------------------------------------------------------------------
                    222:   | Return the address of the last object in lst
                    223:   | If lst is empty then return NULL.
                    224:   --------------------------------------------------------------------*/
                    225: 
                    226:   LPVOID APIENTRY List_Next(LPVOID Curs);
                    227:   /*------------------------------------------------------------------
                    228:   | Return the address of the object after Curs^.
                    229:   | List_Next(List_Last(lst)) == NULL;  List_Next(NULL) is an error.
                    230:   | List_Next(List_Prev(curs)) is illegal if curs identifies first el
                    231:   --------------------------------------------------------------------*/
                    232: 
                    233:   LPVOID APIENTRY List_Prev(LPVOID Curs);
                    234:   /*------------------------------------------------------------------
                    235:   | Return the address of the object after Curs^.
                    236:   | List_Prev(List_First(L)) == NULL;  List_Prev(NULL) is an error.
                    237:   | List_Prev(List_Next(curs)) is illegal if curs identifies last el
                    238:   --------------------------------------------------------------------*/
                    239: 
                    240:   /*------------------------------------------------------------------
                    241:   |  Whole list operations
                    242:    -----------------------------------------------------------------*/
                    243:   void APIENTRY List_Clear(LIST lst);
                    244:   /* arrange that lst is empty after this */
                    245: 
                    246:   BOOL APIENTRY List_IsEmpty(LIST lst);
                    247:   /* Return TRUE if and only if lst is empty */
                    248: 
                    249:   void APIENTRY List_Join(LIST l1, LIST l2);
                    250:   /*-----------------------------------------------------------------------
                    251:   | l1 := l1||l2; l2 := empty
                    252:   | The elements themselves are not moved, so pointers to them remain valid.
                    253:   |
                    254:   | l1 gets all the elements of l1 in their original order followed by
                    255:   | all the elements of l2 in the order they were in in l2.
                    256:   | l2 becomes empty.
                    257:    ------------------------------------------------------------------------*/
                    258: 
                    259:   void APIENTRY List_InsertListAfter(LIST l1, LIST l2, LPVOID Curs);
                    260:   /*-----------------------------------------------------------------------
                    261:   | l1 := l1[...Curs] || l2 || l1[Curs+1...]; l2 := empty
                    262:   | Curs=NULL means insert l2 at the start of l1
                    263:   | The elements themselves are not moved, so pointers to them remain valid.
                    264:   |
                    265:   | l1 gets the elements of l1 from the start up to and including the element
                    266:   | that Curs points at, in their original order,
                    267:   | followed by all the elements that were in l2, in their original order,
                    268:   | followed by the rest of l1
                    269:    ------------------------------------------------------------------------*/
                    270: 
                    271:   void APIENTRY List_InsertListBefore(LIST l1, LIST l2, LPVOID Curs);
                    272:   /*-----------------------------------------------------------------------
                    273:   | l1 := l1[...Curs-1] || l2 || l1[Curs...]; l2 := empty
                    274:   | Curs=NULL means insert l2 at the end of l1
                    275:   | The elements themselves are not moved, so pointers to them remain valid.
                    276:   |
                    277:   | l1 gets the elements of l1 from the start up to but not including the
                    278:   | element that Curs points at, in their original order,
                    279:   | followed by all the elements that were in l2, in their original order,
                    280:   | followed by the rest of l1.
                    281:    ------------------------------------------------------------------------*/
                    282: 
                    283:   void APIENTRY List_SplitAfter(LIST l1, LIST l2, LPVOID Curs);
                    284:   /*-----------------------------------------------------------------------
                    285:   | Let l1 be l1 and l2 be l2
                    286:   | Split l2 off from the front of l1:    final l2,l1 = original l1
                    287:   |
                    288:   | Split l1 into l2: objects of l1 up to and including Curs object
                    289:   |               l1: objects of l1 after Curs
                    290:   | Any original contents of l2 are freed.
                    291:   | List_Spilt(l1, l2, NULL) splits l1 before the first object so l1 gets all.
                    292:   | The elements themselves are not moved.
                    293:    ------------------------------------------------------------------------*/
                    294: 
                    295:   void APIENTRY List_SplitBefore(LIST l1, LIST l2, LPVOID Curs);
                    296:   /*----------------------------------------------------------------------
                    297:   | Split l2 off from the back of l1:  final l1,l2 = original l1
                    298:   |
                    299:   | Split l1 into l1: objects of l1 up to but not including Curs object
                    300:   |               l2: objects of l1 from Curs onwards
                    301:   | Any original contants of l2 are freed.
                    302:   | List_Spilt(l1, l2, NULL) splits l1 after the last object so l1 gets all.
                    303:   | The elements themselves are not moved.
                    304:    -----------------------------------------------------------------------*/
                    305: 
                    306:   int APIENTRY List_Card(LIST lst);
                    307:   /* Return the number of items in L */
                    308: 
                    309:   /*------------------------------------------------------------------
                    310:   | Error handling.
                    311:   |
                    312:   | Each list has within it a flag which indicates whether any illegal
                    313:   | operation has been detected (e.g. DeleteFirst when empty).
                    314:   | Rather than have a flag on every operation, there is a flag held
                    315:   | within the list that can be queried when convenient.  Many operations
                    316:   | do not have enough redundancy to allow any meaningful check.  This
                    317:   | is a design compromise (for instance to allow P = List_Next(P);
                    318:   | rather than P = List_Next(L, P); which is more awkward, especially
                    319:   | if L is actually a lengthy phrase).
                    320:   |
                    321:   | List_IsOK tests this flag (so is a very simple, quick operation).
                    322:   | MakeOK sets the flag to TRUE, in other words to accept the current
                    323:   | state of the list.
                    324:   |
                    325:   | It is possible for a list to be damaged (whether or not the flag
                    326:   | says OK) for instance by the storage being overwritten.
                    327:   |
                    328:   | List_Check attempts to verify that the list is sound (for instance where
                    329:   | there are both forward and backward pointers they should agree).
                    330:   |
                    331:   | List_Recover attempts to make a sound list out of whatever debris is left.
                    332:   | If the list is damaged, Recover may trap (e.g. address error) but
                    333:   | if the list was damaged then ANY operation on it may trap.
                    334:   | If Check succeeds without trapping then so will Recover.
                    335:    -----------------------------------------------------------------*/
                    336: 
                    337:   BOOL APIENTRY List_IsOK(LIST lst);
                    338:   /* Check return code */
                    339: 
                    340:   void APIENTRY List_MakeOK(LIST lst);
                    341:   /* Set return code to good */
                    342: 
                    343:   BOOL APIENTRY List_Check(LIST lst);
                    344:   /* Attempt to validate the chains */
                    345: 
                    346:   void APIENTRY List_Recover(PLIST plst);
                    347:   /* Desperate stuff.  Attempt to reconstruct something */
                    348: 
                    349: /*------------------------------------------------------------------
                    350: |  It is designed to be as easy to USE as possible, consistent
                    351: |  only with being an opaque type.
                    352: |
                    353: |  In particular, the decision to use the address of an object a list cursor
                    354: |  means that there is a small amount of extra arithmetic (in the
                    355: |  IMPLEMENTATION) in cursor operations (e.g. Next and Prev).
                    356: |  and spurious arguments are avoided whenever possible, even though
                    357: |  it would allow greater error checking.
                    358: |
                    359: | Of the "whole list" operations, Clear is given because it seems to be
                    360: | a common operation, even though the caller can implement it with almost
                    361: | the same efficiency as the List implementation module.
                    362: | Join, Split and InsertListXxx cannot be implemented efficiently without
                    363: | knowing the representation.
                    364:  --------------------------------------------------------------------*/

unix.superglobalmegacorp.com

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