Annotation of mstools/samples/sdktools/windiff/list.h, revision 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.