opendir sequence

Brian K. White brian at aljex.com
Mon Nov 9 15:23:05 PST 2015


On 9/27/2012 2:01 AM, Fairlight wrote:
> On Wed, Sep 26, 2012 at 10:31:58AM -0500, Scott Nelson thus spoke:
>> fP 5.06 on SCO OSE 6
>>
>> It appears that opendir reads the requested directory the same as doing
>> an 'l' to list, by name order.  Is there a way to read the listing with
>> opendir in date / time order?
>
> Nope, not inherently.  You're at the mercy of what readdir gives you in
> terms of order.
>
> Your only recourse is limited.  Store all file information in arrays and
> then re-sort the array.  Cakewalk in perl, horrendously painful in fP--and
> limited by the maximum size of your array.
>
> mark->
>


I was just about to ask if anyone had a good array sort routine for this 
very same purpose. That's why I searched my saved emails first and found 
this.

I just wrote a file-select call table in pure fp, and I did include a 
bubble-sort gosub, but it's pretty slow. Bubble sort is very small and 
easy to translate from generic BASIC or pseudo-code examples into fp 
processing. The only fancy function it needs is if you're sorting text 
strings, then some way to compare text strings, which is one thing we do 
have very easy in fp. We can throw and numerical or alpha strings 
together and compare them and get a sensible result as if it were all 
simple integers.

But it's a bit slow for generating a directory listing as frequently as 
this will be used. Tolerable, but noticeable. A full second or more to 
display our main filepro directory.

So I was about to investigate implementing some other sorting algorithm 
besides bubble sort, but they are all more complicated and require 
functions like bitwise ops that we don't have, and might not be 
practical to implement in processing. I mean if a more efficient 
algorithm required a bitwise-xor, you COULD write a gosub that turned 
integers into strings of 1&0 and then walk through those strings one 
char at a time... but I'm sure the result would be even slower than the 
original plain bubble sort!

Conversely if no one implemented any kind of array sort, here is the 
simple bubble sort at least if you want.

Not possible to dim an array of variable size, so you have to pick a max 
number of elements and hardcode it up front. So this uses 2048. A 
directory can certainly have more than 2048 entries in it so this will 
fail on any of those. You could declare the arrays larger than 2048 
array if you want.

The harm from dimming a lot of array elements is mostly limited to using 
up memory. The loops and the listbox all just work from 1-to-N, where N 
is the return value from opendir(), and ignore the rest. So you could 
probably go ahead and dim a little more.

For reference:
2k (2048) elements per array * 32 bytes per element * 2 arrays =
131072 bytes (128KB) per running instance of this call table.
32k (32768) elements would be 2MB per instance.
That's on top of whatever fp is maintaining internally to provide 
@DIRLIST*[] in the first place.

So at 32k elements, if 100 users each had 3 windows open with this in 
each of them all at the same time, that would be 600M used by this 
routine. Hm. Maybe it's fine to just go ahead and dim them up around 32k 
after all. Unless it takes extra seconds for FP to allocate all that 
each time the routine is called.

filenames (just the filename part, not counting the leading path) can be 
longer than 32 characters, but @DIRLIST_FILENAME[] only returns 32 bytes 
per entry, so there's no point in dimming the array elements any larger.

        If: 'directory list    ; temp copy for bubble sort
      Then: dim dirl[2048](32) ; dim tmpl[2048](32)
        If:
      Then: d = getenv("PFDATA"){getenv("PFDIR"){"/filepro"
        If:
      Then: n = opendir("*",d) ; i = "1"
cpd    If: i le n
      Then: dirl[i] = @DIRLIST_FILENAME[i] ; i = i + "1" ; goto cpd
        If:
      Then: x = closedir()
        If:
      Then: gosub bsrt

[...]

bsrt   If: '*** bubble sort dirl[]  ***
      Then: ' works but slow
        If:
      Then: i = "1"
bsi    If:
      Then: r = "1"
bsr    If: dirl[r] gt dirl[r+"1"]
      Then: tmpl[r]=dirl[r] ;dirl[r]=dirl[r+"1"] ;dirl[r+"1"]=tmpl[r]
        If: r lt n-i
      Then: r = r + "1" ; goto bsr
        If: i lt n
      Then: i = i + "1" ; goto bsi
        If:
      Then: return   ' bsrt


I was going to ask if anyone had a better sort routine to share already 
implemented, but given that 32 character limit, and the speed, and 
another little problem having to hard code some logic and values from 
sys/stat.h instead of being able to use IS_DIR(m) like you're supposed 
to, it's probably actually better to just give up on the "pure filepro" 
goal and make a user() co-process that uses normal system utils to get 
file listings, sorted, with metadata.

But I came pretty close.

I have it displaying directory contents, current path to currently 
displayed directory, you can navigate up and down through directories, 
meaning it shows . and .. in the listbox, and if you select "..", it 
strips off a path element and displays the listing for the parent dir. 
When you select an item, it looks at @FSTAT["3"] and determines if it's 
a directory, and if it's a directory it adds it to the path and displays 
that new directory. If it's not a dir then it considers that file your 
final selection and returns. If you select "." then it considers the 
directory you are in as your selection instead of one of it's files or 
navigating to a parent or child dir.

If you comment out the gosub bsrt it's pretty fast, and most filenames 
happen to be under 32 bytes long so it handles most cases. It just can't 
get any better than those "mosts".

-- 
bkw


More information about the Filepro-list mailing list