filelist.h source code

// filelist.h
// BarSSoft, 1999

#ifndef __FILELIST_H__
#define __FILELIST_H__

#include <pthread.h>

#define MAX_LIST_ITEMS 200


typedef enum
{
    NoSort,
    SortByName,
    SortByType,
    SortBySize,
    SortByTime
} SortField;

struct sFileInf
{
   char	  	*name;
   char	  	*type;
   int	  	size;
   time_t 	mtime;
   struct sFileInf  *next;
};

typedef struct sFileInf FileInf;

extern FileInf 	 *fileList[MAX_LIST_ITEMS];
extern int 		 nextItem;
extern SortField sortField;
extern int 	     ascSort; 

extern  pthread_mutex_t	lockFileList;

int  	 fileList_Add(FileInf *item);
FileInf  *fileList_CopyItem(const FileInf *src);
void 	 fileList_Clear(void);
void 	 fileList_Print(void);
void     fileList_Sort(SortField field, int sortAsc);
 
#endif
 
filelist.c source code

#include 
#include 
#include "filelist.h"

FileInf 	*fileList[MAX_LIST_ITEMS];
int 		nextItem;

SortField 	sortField = NoSort;
int			ascSort	= 1;

pthread_mutex_t	lockFileList;


static FileInf *top = 0;

#define MAX_INT_SEGMENTS  10
#define SEGMENT_DELTA 1000000000/MAX_INT_SEGMENTS

#define MAX_CHAR_SEGMENTS 27

int fileList_Add(FileInf *item)
{
   int index;

   item->next = top;
   top = item;

   fileList[nextItem] = item;

   index = nextItem++;
   
   if (sortField == NoSort || nextItem == MAX_LIST_ITEMS)
   {
      fileList_Print();
      fileList_Clear();
   }

   return index;
}

FileInf *fileList_CopyItem(const FileInf *src)
{
   FileInf* dest;
   
   dest = (FileInf*)malloc(sizeof(FileInf));
   memcpy(dest, src, sizeof(FileInf));
   
   dest->name = (char*)malloc(strlen(src->name)+1);
   strcpy(dest->name, src->name);
   
   dest->type = (char*)malloc(strlen(src->type)+1);
   strcpy(dest->type, src->type);

   return dest;
}


void fileList_Clear(void)
{
   int i;

   for (i = 0; i < nextItem; i++)
   {
      free(fileList[i]->name);
      free(fileList[i]->type);
      free(fileList[i]);
   }

   nextItem = 0;
   top = 0;
}

void fileList_Print(void)
{
   FileInf   *item;

   struct tm *t;
   int       i = 0;
   char      s[10];
   
   if (sortField != NoSort)
      fileList_Sort(sortField, ascSort);

   printf("%79s\r", "");

   for (item = top; item; item = item->next)
   {
      t = localtime(&(item->mtime));
      if (item->size < 10000)
         sprintf(s, "%i", item->size);
      else
         if (item->size < 10000000)
            sprintf(s, "%iK", item->size / 1000);
         else   
            sprintf(s, "%iM", item->size / 1000000);
        
      printf("%-30s\t%6s %2.2i.%2.2i.%4i %2.2i:%2.2i:%2.2i %s\n", item->name, s, 
         	 t->tm_mday, t->tm_mon + 1, 1900 + t->tm_year, 
             t->tm_hour, t->tm_min, t->tm_sec,
             item->type);
   }   
}   


char *returnName(FileInf *item)
{
    return item->name;
}

char *returnType(FileInf *item)
{
    return item->type;
}

int  returnSize(FileInf *item)
{
    return item->size;
}

int  returnTime(FileInf *item)
{
    return (int)item->mtime;
}

void joinSegments(FileInf **m, int max)
{
    int 	i;
    FileInf	*item;
    
    for (i = 0; i < max && !*m; i++, m++)
        ;

    if (i >= max)
    {
        perror("all M[i] are null");
        return;
    }

    top = *m;
    item = top;
 
    for(i++, m++; i < MAX_INT_SEGMENTS; i++, m++)
    {
        if (*m)
        {
            while (item->next) item = item->next;
            item->next = *m;
        }
    }
}

void sortInt(int val(FileInf*))
{
    FileInf *M[MAX_INT_SEGMENTS], *item, *cmpItem, *prev;
    int     i, v, ind;
    
    memset(M, 0, MAX_INT_SEGMENTS * sizeof(FileInf*));

    for (i = 0; i < nextItem; i++)
    {
        item = fileList[i];
          
        ind = val(item) / SEGMENT_DELTA;
        if (ind > MAX_INT_SEGMENTS - 1)
           ind = MAX_INT_SEGMENTS - 1;
        
        v = val(item);
        if (!M[ind] || v <= val(M[ind]))
        {
            item->next = M[ind];
            M[ind] = item;
        }
        else
        {
            for (prev = cmpItem = M[ind]; 
                 cmpItem && v > val(cmpItem);
                 prev = cmpItem, cmpItem = cmpItem->next)
                ;
            item->next = cmpItem;
            prev->next = item;
        }
    }
    
    joinSegments(&M[0], MAX_INT_SEGMENTS);
}

int strcomp (char *s1, char *s2)
{
   while (s1 && s2 && tolower(*s1) == tolower(*s2)) 
      	 {s1++; s2++;}
         
   if (!s1 && !s2)
      return 0;
   else
      if (!s1)
         return -1;
      else
         if (!s2)
            return 1;
         else
            if (tolower(*s1) < tolower(*s2))
               return -1;
            else
               return 1;
}

void sortChar(char *val(FileInf*))
{
    FileInf *M[MAX_CHAR_SEGMENTS], *item, *cmpItem, *prev;
    int     i, ind = 0;
    char	*s, c;
    
    memset(M, 0, MAX_CHAR_SEGMENTS * sizeof(FileInf*));

    for (i = 0; i < nextItem; i++)
    {
        item = fileList[i];
        
        s = val(item);
        c = tolower(*s);
        
        if (isalpha(c))
           ind = (int)(c - 'a') + 1;
        else   
           ind = 0;

        if (!M[ind] || strcomp(s, val(M[ind])) <= 0)
        {
            item->next = M[ind];
            M[ind] = item;
        }
        else
        {
            for (prev = cmpItem = M[ind]; 
                 cmpItem && strcomp(s, val(cmpItem)) > 0;
                 prev = cmpItem, cmpItem = cmpItem->next)
                ;
            item->next = cmpItem;
            prev->next = item;
        }
    }
 
    joinSegments(&M[0], MAX_CHAR_SEGMENTS);
}


void fileList_Sort(SortField field, int sortAsc)
{
    FileInf *next, *tmp;

    if (!top)
        return;

    switch (field)
    {
    case SortByName:
        sortChar(returnName);
        break;

    case SortByType:
        sortChar(returnType);
        break;
        
    case SortBySize:
        sortInt(returnSize);
        break;
     
    case SortByTime:
        sortInt(returnTime);
        break;
     
    default:
        return;
    }

    if (!sortAsc)
    {
        for (next = top->next, top->next = 0; next;)
        {
             tmp = next->next; 
             next->next = top;
             top = next;
             next = tmp;
        }
    }
}