examples: add archive, archive-info, archive-extract
FossilOrigin-Name: 17e2edec1ba3dc6941f233adb84d4fd64d6c176b6c6e657984ac4c96014fba8c
This commit is contained in:
parent
1be0d4b85f
commit
64fd933ae8
4 changed files with 164 additions and 0 deletions
|
@ -22,5 +22,7 @@
|
|||
|
||||
## Examples
|
||||
|
||||
- add archive, archive-info, archive-extract
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
53
example/archive-extract.retro
Executable file
53
example/archive-extract.retro
Executable file
|
@ -0,0 +1,53 @@
|
|||
This is archive-extract, an un-archiver. Pass it a file created
|
||||
by `archive.retro` to extract the files.
|
||||
|
||||
As a recap of the file format.
|
||||
|
||||
# of files
|
||||
filename
|
||||
length in bytes
|
||||
... data ...
|
||||
filename
|
||||
length in bytes
|
||||
... data ...
|
||||
[ ... repeat for each file ... ]
|
||||
|
||||
I track the input (the archive) in `In` and the current file
|
||||
being extracted in `Out`.
|
||||
|
||||
~~~
|
||||
'In var
|
||||
'Out var
|
||||
~~~
|
||||
|
||||
The filename is passed in via the command line. Open it, save
|
||||
the pointer.
|
||||
|
||||
~~~
|
||||
#0 script:get-argument file:open-for-reading nip !In
|
||||
~~~
|
||||
|
||||
I define a helper that will be used write data to the output
|
||||
file.
|
||||
|
||||
~~~
|
||||
:write @Out file:write ;
|
||||
~~~
|
||||
|
||||
Define words to process the archive data.
|
||||
|
||||
~~~
|
||||
:get-count @In file:read-line s:to-number ;
|
||||
:filename @In file:read-line file:open-for-writing !Out ;
|
||||
:size @In file:read-line s:to-number ;
|
||||
:extract [ @In file:read write ] times ;
|
||||
:skip-nl @In file:read-line drop ;
|
||||
:close @Out file:close ;
|
||||
~~~
|
||||
|
||||
Then use them to process the file.
|
||||
|
||||
~~~
|
||||
get-count [ filename size extract close skip-nl ] times
|
||||
@In file:close
|
||||
~~~
|
32
example/archive-info.retro
Executable file
32
example/archive-info.retro
Executable file
|
@ -0,0 +1,32 @@
|
|||
This displays the contents (file names, sizes) of an archive.
|
||||
|
||||
I track the input (the archive) in `In`.
|
||||
|
||||
~~~
|
||||
'In var
|
||||
~~~
|
||||
|
||||
The filename is passed in via the command line. Open it, save
|
||||
the pointer.
|
||||
|
||||
~~~
|
||||
#0 script:get-argument file:open-for-reading nip !In
|
||||
~~~
|
||||
|
||||
Define words to process the archive data.
|
||||
|
||||
~~~
|
||||
:get-count @In file:read-line s:to-number dup n:put '_files s:put nl ;
|
||||
:pad s:length #32 swap - #0 n:max [ sp ] times ;
|
||||
:filename @In file:read-line dup s:put pad ;
|
||||
:size @In file:read-line s:to-number dup n:put '_bytes s:put nl ;
|
||||
:skip [ @In file:read drop ] times ;
|
||||
:skip-nl @In file:read-line drop ;
|
||||
~~~
|
||||
|
||||
Then use them to process the file.
|
||||
|
||||
~~~
|
||||
get-count [ filename size skip skip-nl ] times
|
||||
@In file:close
|
||||
~~~
|
77
example/archive.retro
Executable file
77
example/archive.retro
Executable file
|
@ -0,0 +1,77 @@
|
|||
This generates an archive of files. It's currently only tested
|
||||
with plain text, so use caution if archiving binary files.
|
||||
|
||||
The file format is currently very simple. An archive starts
|
||||
with a line containing the number of entries. This is followed
|
||||
by a file name, then the file size in bytes. Then data for the
|
||||
file, a newline, and then any other files.
|
||||
|
||||
It's not robust, it's not scalable, and it's definitely not a
|
||||
thing that most people should use. But it's simple, and works
|
||||
well enough for my small tasks.
|
||||
|
||||
#Entries
|
||||
filename
|
||||
length
|
||||
...
|
||||
filename
|
||||
length
|
||||
...
|
||||
|
||||
The output file handle is stored in the `Out` variable.
|
||||
|
||||
~~~
|
||||
'Out var
|
||||
~~~
|
||||
|
||||
I define `file:put` to write to the `Out` file. This will be
|
||||
mapped in place of `c:put` later.
|
||||
|
||||
~~~
|
||||
:file:put @Out file:write ;
|
||||
~~~
|
||||
|
||||
Each entry has a file name, size, and data. These words write
|
||||
the relevant information to the archive.
|
||||
|
||||
~~~
|
||||
:name dup s:put nl ;
|
||||
:size n:put nl ;
|
||||
:copy [ [ file:read c:put ] sip ] times nl ;
|
||||
:data file:open-for-reading swap [ size ] [ copy ] bi file:close ;
|
||||
:archive name data ;
|
||||
~~~
|
||||
|
||||
The top level part gets the filename for the archive and stores
|
||||
the file pointer in `Out`.
|
||||
|
||||
~~~
|
||||
#0 script:get-argument file:open-for-writing !Out
|
||||
~~~
|
||||
|
||||
Then I replace `c:put` with `file:put` so I can just use the
|
||||
standard output words to write to the archive.
|
||||
|
||||
~~~
|
||||
&file:put &c:put set-hook
|
||||
~~~
|
||||
|
||||
The first line in the archive is the number of files in the
|
||||
archive.
|
||||
|
||||
~~~
|
||||
script:arguments n:dec n:put nl
|
||||
~~~
|
||||
|
||||
Then loop over the files, copying them in
|
||||
~~~
|
||||
script:arguments n:dec
|
||||
[ I n:inc script:get-argument archive ] indexed-times
|
||||
~~~
|
||||
|
||||
And cleanup by reverting `c:put` and closing the archive file.
|
||||
|
||||
~~~
|
||||
&c:put unhook
|
||||
@Out file:close
|
||||
~~~
|
Loading…
Reference in a new issue