home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snpd9707.zip / LL_DEMO.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  9KB  |  243 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /* =======================================================================
  4.     LL_DEMO.C   Demonstration of the use of my Linked List modules.
  5.                 Intentionally over-commented w.r.t the List stuff and
  6.                 under-commented w.r.t. the rest.
  7.                 Not all LLS functions are used, especially LLSnodeDelete()
  8.                 is not used. But I've tried to use all the most important
  9.                 functions. Even when this resulted in less than optimal
  10.                 functionality. E.g. the use of LLSnodeInsert for inserting
  11.                 the data for a directory in the list.
  12.  
  13.                 All subdirectories in the current directory are displayed
  14.                 first sorted by name. Then all files sorted by date and
  15.                 time.
  16.                 The sorting is done by inserting a new node at the
  17.                 appropriate point in the list. This is not the most
  18.                 efficient way to sort, but it is the only possibility with
  19.                 these Linked Lists because some info internal to the list
  20.                 is (intentionally) not available to the user. Some kind of
  21.                 tree would be better anyway ;-)
  22.  
  23.                 Doubly Linked Lists should work the same here as the used
  24.                 Singly Linked Lists. Just replace any 'LLS' by 'LLD'
  25.                 preserving the case. I haven't tried it though, as their
  26.                 only advantage is speed (at the expense of space) when
  27.                 moving backwards in a list.
  28.  
  29.                 v1.00  97-05-22  Initial version.
  30.                        97-05-23  Comments added and completed.
  31.  
  32.  _____          This version is Public Domain.
  33.  /_|__|         A.Reitsma, Delft, Nederland.
  34. /  | \  --------------------------------------------------------------- */
  35.  
  36. #include <stdio.h>        /* for printf()                         */
  37. #include "dirport.h"      /* for all the FIND_* and ff_* stuff    */
  38. #include "sniptype.h"     /* for Success_                         */
  39. #include "lls.h"          /* the Singly Linked List stuff         */
  40.  
  41. /*  Comparison functions which are to be called by LLSnodeFind
  42. */
  43. int DirComp( const void * D1, const void * D2 );
  44. int FileComp( const void * D1, const void * D2 );
  45.  
  46. /*  Separate output functions for directories and files.
  47.     Could be one function with a conditional on ff_attr() == _A_SUBDIR
  48. */
  49. void DirOutput( int List );
  50. void FileOutput( int List );
  51.  
  52. int CompareResult; /* Kludge to solve an (intentional) limitation of    */
  53.                    /* the Linked List system. Serves as secondary       */
  54.                    /* output channel from the ...Comp functions to main.*/
  55.  
  56. int main( int argc , char * argv[] )
  57. {
  58.     DOSFileData Info;
  59.  
  60.     /*  Create and initialize two lists
  61.     */
  62.     int ListDirs  = LLScreate( sizeof( DOSFileData ));
  63.     int ListFiles = LLScreate( sizeof( DOSFileData ));
  64.  
  65.     if( Success_ != FIND_FIRST( argc < 2 ? "*.*" : argv[ 1 ],
  66.                                 _A_ANY, &Info ))
  67.     {
  68.         return EXIT_FAILURE;
  69.     }
  70.  
  71.     do
  72.     {
  73.         if( _A_SUBDIR & ff_attr( &Info ))
  74.         {
  75.             /*  It is a directory but we'll ignore the '.' and '..' dirs
  76.             */
  77.             if( '.' == ff_name( &Info )[ 0 ])
  78.                 continue;
  79.  
  80.             /*  Search from the start ...
  81.             */
  82.             LLSnodePtr2First( ListDirs );
  83.             /*  ... and set the 'current node pointer' to the node
  84.                 matching -- according to the function DirComp --
  85.                 the new data.
  86.             */
  87.             LLSnodeFind( ListDirs, DirComp, &Info );
  88.             /*  LLSnodeFind has a problem in that it is basically designed
  89.                 to find EXACT matches. And DirComp says it is a match when
  90.                 it is the current node is 'larger' than the new data.
  91.                 Also -- unless the list is empty -- the design of the list
  92.                 system is such that the current node pointer can NEVER
  93.                 point at an empty (dummy) node. This means we can NEVER
  94.                 use LLSnodeInsert() to insert a node as the last element
  95.                 of the list.
  96.                 Resulting in the following if/else construct.
  97.             */
  98.             if( 0 <= CompareResult )
  99.                 LLSnodeInsert( ListDirs, Info );
  100.             else
  101.                 LLSnodeAdd( ListDirs, Info );
  102.             /*  Now note that Info is put directly on the stack. This
  103.                 _should_ cause a warning, but you can safely ignore it.
  104.             */
  105.         }
  106.         else if( _A_VOLID & ff_attr( &Info ))
  107.         {
  108.             /*  Do nothing with volume label */
  109.         }
  110.         else
  111.         {   /*  It is a file. Deal with it in a similar way as a
  112.                 directory. The major difference is the way the data
  113.                 is inserted in the list. Note that the difference is
  114.                 for demonstration purposes!
  115.             */
  116.             LLSnodePtr2First( ListFiles );
  117.             LLSnodeFind( ListFiles, FileComp, &Info );
  118.             if( 0 <= CompareResult )
  119.                 LLSnodeInsertFrom( ListFiles, &Info );
  120.             else
  121.                 LLSnodeAddFrom( ListFiles, &Info );
  122.             /*  In this case a _pointer_ to the info is put on the stack.
  123.                 This is -- in this case -- more efficient.
  124.                 With data sizes less than the size of a pointer the direct
  125.                 method -- the way a directory is handled earlier -- is
  126.                 both faster and smaller.
  127.             */
  128.         }
  129.     }while( Success_ == FIND_NEXT( &Info ));
  130.  
  131.     FIND_END( &Info );
  132.  
  133.     /*  Output the content of the List with directories,
  134.         then get rid of it.
  135.     */
  136.     DirOutput( ListDirs);
  137.     LLSdelete( ListDirs );
  138.  
  139.     /*  And similar for the files.
  140.     */
  141.     FileOutput( ListFiles );
  142.     LLSdelete( ListFiles );
  143.  
  144.     return EXIT_SUCCESS;
  145. }
  146.  
  147. int DirComp( const void * D1, const void * D2 )
  148. {
  149.     int RetVal = strcmp( ff_name( (DOSFileData *) D2 ),
  150.                          ff_name( (DOSFileData *) D1 ));
  151.  
  152.     CompareResult = RetVal;
  153.  
  154.     /*  Return a 'match' (0) if the item in the list is 'larger' than the
  155.         new data.
  156.     */
  157.     return RetVal >= 0 ? 0 : 1 ;
  158. }
  159.  
  160. int FileComp( const void * D1, const void * D2 )
  161. {
  162.     /*  Date and time structs are transformed into 'normal' ints by
  163.         casting. This is not really portable to non-DOS systems ...
  164.     */
  165.     int RetVal = *((int *) & ff_date( (DOSFileData *) D2 )) -
  166.                  *((int *) & ff_date( (DOSFileData *) D1 ));
  167.  
  168.     if( 0 == RetVal )
  169.         RetVal = *((int *) & ff_time( (DOSFileData *) D2 )) -
  170.                  *((int *) & ff_time( (DOSFileData *) D1 ));
  171.  
  172.     CompareResult = RetVal;
  173.  
  174.     /*  Return a 'match' (0) if the item in the list is 'larger' than the
  175.         new data.
  176.     */
  177.     return RetVal >= 0 ? 0 : 1 ;
  178. }
  179.  
  180. void DirOutput( int List )
  181. {
  182.     /*  In this case we KNOW the type of the data for certain.
  183.         Otherwise we'd use a pointer and malloc sufficient memory.
  184.         E.g. by:
  185.             char * Sufficient = malloc( LLSnodeDataTo( List, NULL );
  186.         Note the NULL! It says: "return only the size".
  187.         Later on we'd use "Sufficient" in stead of "&Data".
  188.     */
  189.     DOSFileData Data;
  190.  
  191.     /*  From the start of the list ...
  192.     */
  193.     if( ! LLSnodePtr2First( List ))
  194.     {
  195.         return; /* list is empty */
  196.     }
  197.  
  198.     do
  199.     {
  200.         /* ... transfer the data the current node points at to 'Data' ...
  201.         */
  202.         LLSnodeDataTo( List, &Data );
  203.         /*  ... then output it.
  204.         */
  205.         printf( "%-14.14s  %10.10s  "
  206.                 "%4.4d-%2.2d-%2.2d  "
  207.                 "%2.2d:%2.2d:%2.2d  "
  208.                 "%2.2x\n",
  209.                 ff_name( &Data ), "<<dir>>",
  210.                 1980 + ff_yr( &Data ), ff_mo( &Data ), ff_day( &Data ),
  211.                 ff_hr( &Data ), ff_min( &Data ), 2 * ff_sec( &Data ),
  212.                 ff_attr( &Data ));
  213.         /*  And go to the next node if there is one.
  214.         */
  215.     }while( LLSnodePtr2Next( List ));
  216. }
  217.  
  218. void FileOutput( int List ) /* Nearly identical to DirOutput */
  219. {
  220.     DOSFileData Data;
  221.  
  222.     if( ! LLSnodePtr2First( List ))
  223.     {
  224.         return; /* list is empty */
  225.     }
  226.  
  227.     do
  228.     {
  229.         LLSnodeDataTo( List, &Data );
  230.         printf( "%-14.14s  %10.1ld  "
  231.                 "%4.4d-%2.2d-%2.2d  "
  232.                 "%2.2d:%2.2d:%2.2d  "
  233.                 "%2.2x\n",
  234.                 ff_name( &Data ), ff_size( &Data ),
  235.                 1980 + ff_yr( &Data ), ff_mo( &Data ), ff_day( &Data ),
  236.                 ff_hr( &Data ), ff_min( &Data ), 2 * ff_sec( &Data ),
  237.                 ff_attr( &Data ));
  238.  
  239.     }while( LLSnodePtr2Next( List ));
  240. }
  241.  
  242. /* === LL_demo.c ======================================================= */
  243.