reset();
}
-FileItem::FileItem(char *path,
- char *name,
- int is_dir,
- int64_t size,
- int month,
- int day,
- int year,
- int64_t calendar_time)
+FileItem::FileItem(const char *path, const char *name, int is_dir,
+ int64_t size, time_t mtime, int item_no)
{
this->path = new char[strlen(path)];
this->name = new char[strlen(name)];
if(this->name) strcpy(this->name, name);
this->is_dir = is_dir;
this->size = size;
- this->month = month;
- this->day = day;
- this->year = year;
- this->calendar_time = calendar_time;
+ this->mtime = mtime;
+ this->item_no = item_no;
}
FileItem::~FileItem()
name = 0;
is_dir = 0;
size = 0;
- month = 0;
- day = 0;
- year = 0;
- calendar_time = 0;
+ mtime = 0;
+ item_no = -1;
return 0;
}
return 0;
}
-const char* FileItem::get_path()
-{
- return path;
-}
-
-const char* FileItem::get_name()
-{
- return name;
-}
-
-int FileItem::get_is_dir()
-{
- return is_dir;
-}
-
FileSystem::FileSystem()
int FileSystem::delete_directory()
{
- for(int i = 0; i < dir_list.total; i++)
- {
- delete dir_list.values[i];
- }
- dir_list.remove_all();
+ dir_list.remove_all_objects();
return 0;
}
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
//printf("path_ascending %p %p\n", ptr1, ptr2);
- return strcasecmp(item1->name, item2->name);
+ int ret = strcasecmp(item1->name, item2->name);
+ if( ret != 0 ) return ret;
+ return item1->item_no - item2->item_no;
}
int FileSystem::path_descending(const void *ptr1, const void *ptr2)
{
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
- return strcasecmp(item2->name, item1->name);
+ int ret = strcasecmp(item2->name, item1->name);
+ if( ret != 0 ) return ret;
+ return item2->item_no - item1->item_no;
}
{
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
- return item1->size >= item2->size;
+ return item1->size == item2->size ?
+ item1->item_no - item2->item_no :
+ item1->size > item2->size;
}
int FileSystem::size_descending(const void *ptr1, const void *ptr2)
{
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
- return item1->size <= item2->size;
+ return item2->size == item1->size ?
+ item2->item_no - item1->item_no :
+ item2->size > item1->size;
}
{
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
- return item1->calendar_time >= item2->calendar_time;
+ return item1->mtime == item2->mtime ?
+ item1->item_no - item2->item_no :
+ item1->mtime > item2->mtime;
}
int FileSystem::date_descending(const void *ptr1, const void *ptr2)
{
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
- return item1->calendar_time <= item2->calendar_time;
+ return item2->mtime == item1->mtime ?
+ item2->item_no - item1->item_no :
+ item2->mtime > item1->mtime;
}
int FileSystem::ext_ascending(const void *ptr1, const void *ptr2)
{
- char dotreversedname1[BCTEXTLEN], dotreversedname2[BCTEXTLEN];
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
+ char *ext1 = strrchr(item1->name,'.');
+ if( !ext1 ) ext1 = item1->name;
+ char *ext2 = strrchr(item2->name,'.');
+ if( !ext2 ) ext2 = item2->name;
+ int ret = strcasecmp(ext1, ext2);
+ if( ret ) return ret;
+ if( item1->item_no >= 0 && item2->item_no >= 0 )
+ return item1->item_no - item2->item_no;
+ char dotreversedname1[BCTEXTLEN], dotreversedname2[BCTEXTLEN];
dot_reverse_filename(dotreversedname1,item1->name);
dot_reverse_filename(dotreversedname2,item2->name);
return strcasecmp(dotreversedname1, dotreversedname2);
int FileSystem::ext_descending(const void *ptr1, const void *ptr2)
{
- char dotreversedname1[BCTEXTLEN], dotreversedname2[BCTEXTLEN];
FileItem *item1 = *(FileItem**)ptr1;
FileItem *item2 = *(FileItem**)ptr2;
+ char *ext1 = strrchr(item1->name,'.');
+ if( !ext1 ) ext1 = item1->name;
+ char *ext2 = strrchr(item2->name,'.');
+ if( !ext2 ) ext2 = item2->name;
+ int ret = strcasecmp(ext2, ext1);
+ if( ret ) return ret;
+ if( item2->item_no >= 0 && item1->item_no >= 0 )
+ return item2->item_no - item1->item_no;
+ char dotreversedname1[BCTEXTLEN], dotreversedname2[BCTEXTLEN];
dot_reverse_filename(dotreversedname1,item1->name);
dot_reverse_filename(dotreversedname2,item2->name);
return strcasecmp(dotreversedname2, dotreversedname1);
int FileSystem::sort_table(ArrayList<FileItem*> *dir_list)
{
-#define SORT_MACRO(compare) \
- qsort(dir_list->values, dir_list->size(), sizeof(FileItem*), compare);
-
if(!dir_list || !dir_list->size()) return 0;
+ static int (*cmpr[][2])(const void *ptr1, const void *ptr2) = {
+ { &path_ascending, &path_descending },
+ { &size_ascending, &size_descending },
+ { &date_ascending, &date_descending },
+ { &ext_ascending, &ext_descending },
+ };
-//printf("FileSystem::sort_table %p\n", dir_list->values);
- switch(sort_field)
- {
- case SORT_PATH:
- if(sort_order == SORT_ASCENDING)
- SORT_MACRO(path_ascending)
- else
- SORT_MACRO(path_descending)
- break;
- case SORT_SIZE:
- if(sort_order == SORT_ASCENDING)
- SORT_MACRO(size_ascending)
- else
- SORT_MACRO(size_descending)
- break;
- case SORT_DATE:
- if(sort_order == SORT_ASCENDING)
- SORT_MACRO(date_ascending)
- else
- SORT_MACRO(date_descending)
- break;
- case SORT_EXTENSION:
- if(sort_order == SORT_ASCENDING)
- SORT_MACRO(ext_ascending)
- else
- SORT_MACRO(ext_descending)
- break;
- }
+ qsort(dir_list->values,
+ dir_list->size(), sizeof(FileItem*),
+ cmpr[sort_field][sort_order]);
return 0;
}
return 0;
}
-void FileSystem::alphabetize()
-{
- sort_table(&dir_list);
-}
-
-int FileSystem::is_root_dir(char *path)
-{
- if(!strcmp(current_dir, "/")) return 1;
- return 0;
-}
-
-int FileSystem::test_filter(FileItem *file)
+int FileSystem::test_filter(const char *url, const char *filter)
{
- char *filter1 = 0, *filter2 = filter, *subfilter1, *subfilter2;
- int result = 0;
- int done = 0, token_done;
- int token_number = 0;
+ char string[BCTEXTLEN], string2[BCTEXTLEN];
+ const char *filter1 = 0, *filter2 = filter;
+ int done = 0, result = 0, token_number = 0;
-// Don't filter directories
- if(file->is_dir) return 0;
-
-// Empty filename string
- if(!file->name) return 1;
-
- do
- {
-// Get next token
+ do { // Get next token
filter1 = strchr(filter2, '[');
string[0] = 0;
-
-// Get next filter
- if(filter1)
- {
- filter1++;
- filter2 = strchr(filter1, ']');
-
- if(filter2)
- {
- int i;
- for(i = 0; filter1 + i < filter2; i++)
- string[i] = filter1[i];
- string[i] = 0;
+ if( filter1 ) { // Get next filter
+ filter2 = strchr(++filter1, ']');
+ if( filter2 ) {
+ int n = filter2 - filter1;
+ for( int i=0; i<n; ++i ) string[i] = filter1[i];
+ string[n] = 0;
}
- else
- {
+ else {
strcpy(string, filter1);
done = 1;
}
}
- else
- {
- if(!token_number)
+ else {
+ if( !token_number )
strcpy(string, filter);
else
done = 1;
}
-// Process the token
- if(string[0] != 0)
- {
- char *path = file->name;
- subfilter1 = string;
- token_done = 0;
+ if( string[0] ) { // Process the token
+ const char *path = url;
+ const char *subfilter1 = string, *subfilter2 = 0;
+ int token_done = 0;
result = 0;
-
- do
- {
+ do {
string2[0] = 0;
subfilter2 = strchr(subfilter1, '*');
-
- if(subfilter2)
- {
- int i;
- for(i = 0; subfilter1 + i < subfilter2; i++)
- string2[i] = subfilter1[i];
-
- string2[i] = 0;
+ if( subfilter2 ) {
+ int n = subfilter2 - subfilter1;
+ for( int i=0; i<n; ++i ) string2[i] = subfilter1[i];
+ string2[n] = 0;
}
- else
- {
+ else {
strcpy(string2, subfilter1);
token_done = 1;
}
- if(string2[0] != 0)
- {
-// Subfilter must exist at some later point in the string
- if(subfilter1 > string)
- {
- if(!strstr(path, string2))
- {
- result = 1;
- token_done = 1;
- }
+ if( string2[0] ) { // Subfilter exists
+ if( subfilter1 > string ) {
+ const char *cp = strstr(path, string2);
+ if( !cp )
+ result = token_done = 1;
else
- path = strstr(path, string2) + strlen(string2);
+ path = cp + strlen(string2);
}
- else
-// Subfilter must exist at this point in the string
- {
- if(strncmp(path, string2, strlen(string2)))
-// if(strncasecmp(path, string2, strlen(string2)))
- {
- result = 1;
- token_done = 1;
- }
+ else { // Subfilter exists
+ if( strncmp(path, string2, strlen(string2)) ) // strncasecmp?
+ result = token_done = 1;
else
- path += strlen(string2);
+ path += strlen(string2);
}
// String must terminate after subfilter
- if(!subfilter2)
- {
- if(*path != 0)
- {
- result = 1;
- token_done = 1;
- }
+ if( !subfilter2 ) {
+ if( *path )
+ result = token_done = 1;
}
}
subfilter1 = subfilter2 + 1;
// Let pass if no subfilter
- }while(!token_done && !result);
+ } while( !token_done && !result );
}
- token_number++;
- }while(!done && result);
+ ++token_number;
+ } while( !done && result );
return result;
}
-
-int FileSystem::update(const char *new_dir)
+int FileSystem::test_filter(FileItem *file)
{
- DIR *dirstream;
- struct dirent64 *new_filename;
- struct stat ostat;
- struct tm *mod_time;
- int include_this;
- FileItem *new_file;
- char full_path[BCTEXTLEN], name_only[BCTEXTLEN];
- ArrayList<FileItem*>directories;
- ArrayList<FileItem*>files;
- int result = 0;
+// Don't filter directories
+ if( file->is_dir ) return 0;
+ if( !file->name ) return 1;
+ return test_filter(file->name, this->filter);
+}
- delete_directory();
- if(new_dir != 0) strcpy(current_dir, new_dir);
- dirstream = opendir(current_dir);
- if(!dirstream) return 1; // failed to open directory
+int FileSystem::scan_directory(const char *new_dir)
+{
+ if( new_dir != 0 )
+ strcpy(current_dir, new_dir);
+ DIR *dirstream = opendir(current_dir);
+ if( !dirstream ) return 1; // failed to open directory
- while( (new_filename = readdir64(dirstream)) != 0 )
- {
- include_this = 1;
+ struct dirent64 *new_filename;
+ while( (new_filename = readdir64(dirstream)) != 0 ) {
+ FileItem *new_file = 0;
+ int include_this = 1;
// File is directory heirarchy
if(!strcmp(new_filename->d_name, ".") ||
// file not hidden
if(include_this)
- {
+ {
new_file = new FileItem;
+ char full_path[BCTEXTLEN], name_only[BCTEXTLEN];
sprintf(full_path, "%s", current_dir);
- if(!is_root_dir(current_dir)) strcat(full_path, "/");
+ add_end_slash(full_path);
strcat(full_path, new_filename->d_name);
strcpy(name_only, new_filename->d_name);
new_file->set_path(full_path);
new_file->set_name(name_only);
// Get information about the file.
+ struct stat ostat;
if(!stat(full_path, &ostat))
{
new_file->size = ostat.st_size;
- mod_time = localtime(&(ostat.st_mtime));
- new_file->month = mod_time->tm_mon + 1;
- new_file->day = mod_time->tm_mday;
- new_file->year = mod_time->tm_year + 1900;
- new_file->calendar_time = ostat.st_mtime;
+ new_file->mtime = ostat.st_mtime;
if(S_ISDIR(ostat.st_mode))
{
// add to list
if(include_this)
- {
- if(new_file->is_dir) directories.append(new_file);
- else files.append(new_file);
- }
+ dir_list.append(new_file);
else
delete new_file;
}
}
-//printf("FileSystem::update %d\n", __LINE__);
-
closedir(dirstream);
+ return 0;
+}
+
+int FileSystem::update(const char *new_dir)
+{
+ delete_directory();
+ int result = scan_directory(new_dir);
// combine the directories and files in the master list
- combine(&directories, &files);
-// remove pointers
- directories.remove_all();
- files.remove_all();
-//printf("FileSystem::update %d\n", __LINE__);
+ return !result ? update_sort() : result;
+}
- return result;
+int FileSystem::update_sort()
+{
+ ArrayList<FileItem*> directories, files;
+ for( int i=0; i< dir_list.size(); ++i ) {
+ FileItem *item = dir_list[i];
+ item->item_no = i;
+ (item->is_dir ? &directories : &files)->append(item);
+ }
+ dir_list.remove_all();
+// combine the directories and files in the master list
+ combine(&directories, &files);
+ return 0;
// success
}
+
int FileSystem::set_filter(const char *new_filter)
{
strcpy(filter, new_filter);
char new_dir[BCTEXTLEN];
strcpy(new_dir, new_dir_);
complete_path(new_dir);
-
- mkdir(new_dir, S_IREAD | S_IWRITE | S_IEXEC);
- return 0;
+ return mkdir(new_dir, S_IRWXU | S_IRWXG | S_IRWXO);
}
int FileSystem::parse_tildas(char *new_dir)
int FileSystem::parse_directories(char *new_dir)
{
//printf("FileSystem::parse_directories 1 %s\n", new_dir);
- if(new_dir[0] != '/')
- {
-// extend path completely
+ if( *new_dir != '/' && current_dir[0] ) { // expand to abs path
char string[BCTEXTLEN];
-//printf("FileSystem::parse_directories 2 %s\n", current_dir);
- if(!strlen(current_dir))
- {
-// no current directory
- strcpy(string, new_dir);
- }
- else
- if(!is_root_dir(current_dir))
- {
-// current directory is not root
- if(current_dir[strlen(current_dir) - 1] == '/')
-// current_dir already has ending /
- sprintf(string, "%s%s", current_dir, new_dir);
- else
-// need ending /
- sprintf(string, "%s/%s", current_dir, new_dir);
- }
- else
- sprintf(string, "%s%s", current_dir, new_dir);
-
-//printf("FileSystem::parse_directories 3 %s %s\n", new_dir, string);
+ strcpy(string, current_dir);
+ add_end_slash(string);
+ strcat(string, new_dir);
strcpy(new_dir, string);
-//printf("FileSystem::parse_directories 4\n");
}
return 0;
}
return 0;
}
-char* FileSystem::get_current_dir()
-{
- return current_dir;
-}
-
-int FileSystem::total_files()
-{
- return dir_list.total;
-}
-
-
-FileItem* FileSystem::get_entry(int entry)
-{
- return dir_list.values[entry];
-}
-
// collapse ".", "..", "//" eg. x/./..//y = y
char *FileSystem::basepath(const char *path)