Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

CompressionPackageDesign: tango-compression-stuff.d

File tango-compression-stuff.d, 6.1 kB (added by DRK, 2 years ago)

Some thoughts on compression model design

Line 
1 /**
2  * IArchive models the basic actions you can perform on an archive.
3  *
4  * Users should be able to read from an archive by opening it, and using the
5  * IArchiveEntry objects to read out the contents.
6  *
7  * Writing archives should be done by creating an empty archive, using
8  * addFile() calls to attach files to the archive, and then a call to write()
9  * to actually generate the archive.
10  *
11  * Modifying archives will be tricky, since the way this is usually done is to
12  * simply create a new archive, splicing the new and old together.  Perhaps it
13  * should be assumed that you can't write back to the same archive you've
14  * already opened.  If you want to do things like that, you'll have to use a
15  * temporary file...
16  */
17 interface IArchive
18 {
19     /**
20      * Closes the archive, discarding all changes.
21      */
22     void close();
23
24     /**
25      * Writes the contents of the archive out to either a file on disk, or to
26      * a conduit.
27      */
28     void write(char[] path);
29     void write(Path path);
30     void write(IConduit conduit);
31
32     /**
33      * Adds a file to the archive, reading from either a file on disk or a
34      * conduit, and placing it in the given archive path.
35      */
36     void addFile(char[] path, char[] archivePath);
37     void addFile(Path path, Path archivePath);
38     void addFile(IConduit conduit, Path archivePath);
39
40     /**
41      * (Maybe)
42      * Adds a directory and the files it contains to the archive.  The final
43      * argument can be given as "false" to prevent recursively adding all
44      * sub-directories as well.
45      */
46     void addDirectory(char[] path, char[] archivePath, bool recursive = true);
47     void addDirectory(Path path, Path archivePath, bool recursive = true);
48
49     /**
50      * Removes a file from the archive.
51      */
52     void removeFile(char[] path);
53     void removeFile(Path path);
54
55     /**
56      * Retrieves the archive entry for a given archive path.
57      */
58     IArchiveEntry getFile(char[] path);
59     IArchiveEntry getFile(Path path);
60
61     /**
62      * (Maybe--would be nice to have, and provides symmetry to addFile)
63      * Extracts the specified archive path to either a file on disk, or to a
64      * conduit.
65      */
66     void extractFile(char[] path, char[] outPath);
67     void extractFile(Path path, Path outPath);
68     void extractFile(Path path, IConduit conduit);
69
70     /**
71      * Iterates over all files in the archive.
72      */
73     int opApply(int delegate(IArchiveEntry) dg);
74     int opApply(int delegate(IArchiveEntry, size_t) dg);
75
76     /**
77      * Gets/sets the abstract compression level.
78      *
79      * This is either a good idea, or a really bad one.  The problem is that
80      * this won't always make sense: for ZIP files, yeah; it makes sense.  But
81      * for TAR files, it doesn't make any sense whatsoever (unless we give
82      * TarFile.write magic powers to pick a compression codec from this value.
83      *
84      * It's worth thinking about, any way.
85      */
86     CompressionLevel compressionLevel();
87     void compressionLevel(CompressionLevel level);
88 }
89
90 /**
91  * These constants represent general compression levels that can be used
92  * without having to actually know what the compression scheme is, or how it
93  * works.
94  *
95  * However, whilst "Store" and "Maximum" are obviously useful, I'm not so sure
96  * about the middle three.  Yeah, granularity is nice, but who's going to sit
97  * there and think "Gee, I really think I need Medium on this one!"...
98  */
99 enum CompressionLevel
100 {
101     Store,
102     Low,
103     Medium,
104     High,
105     Maximum,
106 }
107
108 /**
109  * An alternative to the above would be to define two additional interfaces:
110  * IInternalCompression and IExternalCompression.  The first would be used
111  * with formats like ZIP that compress their contents, and the second for
112  * formats like TAR that are compressed in their entirety.
113  *
114  * IInternalCompression could expose something meaningful for ZIP-like files
115  * (like compression level), whilst IExternalCompression could have a
116  * reference to a compression codec to use.
117  */
118
119 class TarFile : IArchive
120 {
121     /**
122      * Opens an existing tar file from either a file on disk or a conduit, and
123      * decompresses it with the given codec.
124      *
125      * NOTE: there should exist a "magic" filter that automatically chooses
126      * the appropriate filter based on either the file name or magic numbers.
127      */
128     this(char[] path, IConduitFilter codec = null);
129     this(Path path, IConduitFilter codec = null);
130     this(IConduit conduit, IConduitFilter codec = null);
131
132     /**
133      * Writes the archive to either disk or a conduit, and applies the given
134      * compression codec to the stream.
135      */
136     void write(char[] path, IConduitFilter codec = null);
137     void write(Path path, IConduitFilter codec = null);
138     void write(IConduit conduit, IConduitFilter codec = null);
139 }
140
141 class ZipFile : IArchive
142 {
143     /**
144      * Opens an existing zip archive either from disk or from a conduit.
145      */
146     this(char[] path);
147     this(Path path);
148     this(IConduit conduit);
149 }
150
151 /**
152  * IArchiveEntry combines a conduit for reading data out of the file, and some
153  * basic metadata on the file itself.
154  *
155  * Archive entries should be assumed to be read-only and non-seekable, since
156  * writing and seeking are a complete pain in the arse with archive formats
157  * (especially compressed ones!).
158  */
159 interface IArchiveEntry : IConduit
160 {
161     char[]  filename;       // The entry's file name
162     Time    lastModified;   // Modification time-stamp
163     size_t  size;           // Uncompressed size
164 }
165
166 class TarEntry : IArchiveEntry
167 {
168     uint            mode;   // Permission bits
169     TarEntryType    type;   // File type (file, symlink, link, etc.)
170     char[]          linkName; // Link target
171     uint            userId, groupId;
172     char[]          userName, groupName;
173 }
174
175 class ZipEntry : IArchiveEntry
176 {
177     uint    compressType;   // More format-specific junk...
178     char[]  comment;
179     char[]  createSystem;
180     uint    createVersion, extractVersion;
181     uint    flagBits;
182     uint    volume;
183     size_t  compressedSize;
184 }