fixing the topic overviews
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51979 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: arc
|
||||
// Name: arc.h
|
||||
// Purpose: topic overview
|
||||
// Author: wxWidgets team
|
||||
// RCS-ID: $Id$
|
||||
@@ -8,82 +8,49 @@
|
||||
|
||||
/*!
|
||||
|
||||
@page arc_overview Archive formats such as zip
|
||||
@page overview_arc Archive formats such as zip
|
||||
|
||||
The archive classes handle archive formats such as zip, tar, rar and cab.
|
||||
Currently #wxZip
|
||||
and #wxTar classes are included.
|
||||
Currently #wxZip and #wxTar classes are included.
|
||||
|
||||
For each archive type, there are the following classes (using zip here
|
||||
as an example):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxZipInputStream
|
||||
|
||||
|
||||
|
||||
|
||||
Input stream
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxZipOutputStream
|
||||
|
||||
|
||||
|
||||
|
||||
Output stream
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxZipEntry
|
||||
|
||||
|
||||
|
||||
|
||||
Holds the meta-data for an
|
||||
entry (e.g. filename, timestamp, etc.)
|
||||
|
||||
|
||||
|
||||
|
||||
@li wxZipInputStream: input stream
|
||||
@li wxZipOutputStream: output stream
|
||||
@li wxZipEntry: holds the meta-data for an entry (e.g. filename, timestamp, etc.)
|
||||
|
||||
There are also abstract wxArchive classes that can be used to write code
|
||||
that can handle any of the archive types,
|
||||
see '@ref arcgeneric_overview'.
|
||||
that can handle any of the archive types, see @ref overview_arc_generic.
|
||||
|
||||
Also see #wxFileSystem for a higher level interface that
|
||||
can handle archive files in a generic way.
|
||||
|
||||
The classes are designed to handle archives on both seekable streams such
|
||||
as disk files, or non-seekable streams such as pipes and sockets
|
||||
(see '@ref arcnoseek_overview').
|
||||
@b See also
|
||||
#wxFileSystem
|
||||
(see @ref overview_arc_noseek).
|
||||
|
||||
@ref arccreate_overview
|
||||
@ref arcextract_overview
|
||||
@ref arcmodify_overview
|
||||
@ref arcbyname_overview
|
||||
@ref arcgeneric_overview
|
||||
@ref arcnoseek_overview
|
||||
See also #wxFileSystem.
|
||||
|
||||
@li @ref overview_arc_create
|
||||
@li @ref overview_arc_extract
|
||||
@li @ref overview_arc_modify
|
||||
@li @ref overview_arc_byname
|
||||
@li @ref overview_arc_generic
|
||||
@li @ref overview_arc_noseek
|
||||
|
||||
|
||||
@section wxarccreate Creating an archive
|
||||
<hr>
|
||||
|
||||
@ref arc_overview
|
||||
Call #PutNextEntry() to
|
||||
create each new entry in the archive, then write the entry's data.
|
||||
|
||||
@section overview_arc_create Creating an archive
|
||||
|
||||
Call #PutNextEntry() to create each new entry in the archive, then write the entry's data.
|
||||
Another call to PutNextEntry() closes the current entry and begins the next.
|
||||
For example:
|
||||
|
||||
@code
|
||||
wxFFileOutputStream out(_T("test.zip"));
|
||||
wxFFileOutputStream out(_T("test.zip"));
|
||||
wxZipOutputStream zip(out);
|
||||
wxTextOutputStream txt(zip);
|
||||
wxString sep(wxFileName::GetPathSeparator());
|
||||
@@ -99,18 +66,18 @@
|
||||
store entries in subdirectories.
|
||||
|
||||
|
||||
@section wxarcextract Extracting an archive
|
||||
@section overview_arc_extract Extracting an archive
|
||||
|
||||
#GetNextEntry() returns a pointer to entry object containing the meta-data for
|
||||
the next entry in the archive (and gives away ownership).
|
||||
|
||||
Reading from the input stream then returns the entry's data.
|
||||
Eof() becomes @true after an attempt has been made to read past the end of the entry's data.
|
||||
|
||||
@ref arc_overview
|
||||
#GetNextEntry() returns a pointer
|
||||
to entry object containing the meta-data for the next entry in the archive
|
||||
(and gives away ownership). Reading from the input stream then returns the
|
||||
entry's data. Eof() becomes @true after an attempt has been made to read past
|
||||
the end of the entry's data.
|
||||
When there are no more entries, GetNextEntry() returns @NULL and sets Eof().
|
||||
|
||||
@code
|
||||
auto_ptrwxZipEntry entry;
|
||||
auto_ptr<wxZipEntry> entry;
|
||||
|
||||
wxFFileInputStream in(_T("test.zip"));
|
||||
wxZipInputStream zip(in);
|
||||
@@ -125,31 +92,31 @@
|
||||
|
||||
|
||||
|
||||
@section wxarcmodify Modifying an archive
|
||||
@section overview_arc_modify Modifying an archive
|
||||
|
||||
@ref arc_overview
|
||||
To modify an existing archive, write a new copy of the archive to a new file,
|
||||
making any necessary changes along the way and transferring any unchanged
|
||||
entries using #CopyEntry().
|
||||
|
||||
For archive types which compress entry data, CopyEntry() is likely to be
|
||||
much more efficient than transferring the data using Read() and Write()
|
||||
since it will copy them without decompressing and recompressing them.
|
||||
|
||||
In general modifications are not possible without rewriting the archive,
|
||||
though it may be possible in some limited cases. Even then, rewriting the
|
||||
archive is usually a better choice since a failure can be handled without
|
||||
losing the whole
|
||||
archive. #wxTempFileOutputStream can
|
||||
be helpful to do this.
|
||||
losing the whole archive. #wxTempFileOutputStream can be helpful to do this.
|
||||
|
||||
For example to delete all entries matching the pattern "*.txt":
|
||||
|
||||
@code
|
||||
auto_ptrwxFFileInputStream in(new wxFFileInputStream(_T("test.zip")));
|
||||
auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip")));
|
||||
wxTempFileOutputStream out(_T("test.zip"));
|
||||
|
||||
wxZipInputStream inzip(*in);
|
||||
wxZipOutputStream outzip(out);
|
||||
|
||||
auto_ptrwxZipEntry entry;
|
||||
auto_ptr<wxZipEntry> entry;
|
||||
|
||||
// transfer any meta-data for the archive as a whole (the zip comment
|
||||
// in the case of zip)
|
||||
@@ -171,30 +138,30 @@
|
||||
|
||||
|
||||
|
||||
@section wxarcbyname Looking up an archive entry by name
|
||||
@section overview_arc_byname Looking up an archive entry by name
|
||||
|
||||
@ref arc_overview
|
||||
Also see #wxFileSystem for a higher level interface that is
|
||||
more convenient for accessing archive entries by name.
|
||||
|
||||
To open just one entry in an archive, the most efficient way is
|
||||
to simply search for it linearly by calling
|
||||
#GetNextEntry() until the
|
||||
to simply search for it linearly by calling #GetNextEntry() until the
|
||||
required entry is found. This works both for archives on seekable and
|
||||
non-seekable streams.
|
||||
|
||||
The format of filenames in the archive is likely to be different
|
||||
from the local filename format. For example zips and tars use
|
||||
unix style names, with forward slashes as the path separator,
|
||||
and absolute paths are not allowed. So if on Windows the file
|
||||
"C:\MYDIR\MYFILE.TXT" is stored, then when reading
|
||||
the entry back #GetName() will return
|
||||
"MYDIR\MYFILE.TXT". The conversion into the internal format
|
||||
"C:\MYDIR\MYFILE.TXT" is stored, then when reading the entry back #GetName()
|
||||
will return "MYDIR\MYFILE.TXT". The conversion into the internal format
|
||||
and back has lost some information.
|
||||
|
||||
So to avoid ambiguity when searching for an entry matching a local name,
|
||||
it is better to convert the local name to the archive's internal format
|
||||
and search for that:
|
||||
|
||||
@code
|
||||
auto_ptrwxZipEntry entry;
|
||||
auto_ptr<wxZipEntry> entry;
|
||||
|
||||
// convert the local name we are looking for into the internal format
|
||||
wxString name = wxZipEntry::GetInternalName(localname);
|
||||
@@ -216,11 +183,10 @@
|
||||
|
||||
To access several entries randomly, it is most efficient to transfer the
|
||||
entire catalogue of entries to a container such as a std::map or a
|
||||
#wxHashMap then entries looked up by name can be
|
||||
opened using the #OpenEntry() method.
|
||||
#wxHashMap then entries looked up by name can be opened using the #OpenEntry() method.
|
||||
|
||||
@code
|
||||
WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
|
||||
WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
|
||||
ZipCatalog::iterator it;
|
||||
wxZipEntry *entry;
|
||||
ZipCatalog cat;
|
||||
@@ -249,7 +215,7 @@
|
||||
underlying stream on the same archive:
|
||||
|
||||
@code
|
||||
// opening another entry without closing the first requires another
|
||||
// opening another entry without closing the first requires another
|
||||
// input stream for the same file
|
||||
wxFFileInputStream in2(_T("test.zip"));
|
||||
wxZipInputStream zip2(in2);
|
||||
@@ -259,78 +225,43 @@
|
||||
|
||||
|
||||
|
||||
@section wxarcgeneric Generic archive programming
|
||||
@section overview_arc_generic Generic archive programming
|
||||
|
||||
@ref arc_overview
|
||||
Also see #wxFileSystem for a higher level interface that
|
||||
can handle archive files in a generic way.
|
||||
|
||||
The specific archive classes, such as the wxZip classes, inherit from
|
||||
the following abstract classes which can be used to write code that can
|
||||
handle any of the archive types:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxArchiveInputStream
|
||||
|
||||
|
||||
|
||||
|
||||
Input stream
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxArchiveOutputStream
|
||||
|
||||
|
||||
|
||||
|
||||
Output stream
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#wxArchiveEntry
|
||||
|
||||
|
||||
|
||||
|
||||
Holds the meta-data for an
|
||||
entry (e.g. filename)
|
||||
|
||||
|
||||
|
||||
|
||||
@li wxArchiveInputStream: input stream
|
||||
@li wxArchiveOutputStream: output stream
|
||||
@li wxArchiveEntry: holds the meta-data for an entry (e.g. filename)
|
||||
|
||||
In order to able to write generic code it's necessary to be able to create
|
||||
instances of the classes without knowing which archive type is being used.
|
||||
|
||||
To allow this there is a class factory for each archive type, derived from
|
||||
#wxArchiveClassFactory, that can create
|
||||
the other classes.
|
||||
#wxArchiveClassFactory, that can create the other classes.
|
||||
|
||||
For example, given @e wxArchiveClassFactory* factory, streams and
|
||||
entries can be created like this:
|
||||
|
||||
@code
|
||||
// create streams without knowing their type
|
||||
auto_ptrwxArchiveInputStream inarc(factory-NewStream(in));
|
||||
auto_ptrwxArchiveOutputStream outarc(factory-NewStream(out));
|
||||
// create streams without knowing their type
|
||||
auto_ptr<wxArchiveInputStream> inarc(factory-NewStream(in));
|
||||
auto_ptr<wxArchiveOutputStream> outarc(factory-NewStream(out));
|
||||
|
||||
// create an empty entry object
|
||||
auto_ptrwxArchiveEntry entry(factory-NewEntry());
|
||||
auto_ptr<wxArchiveEntry> entry(factory-NewEntry());
|
||||
@endcode
|
||||
|
||||
For the factory itself, the static member
|
||||
wxArchiveClassFactory::Find().
|
||||
For the factory itself, the static member wxArchiveClassFactory::Find().
|
||||
can be used to find a class factory that can handle a given file
|
||||
extension or mime type. For example, given @e filename:
|
||||
|
||||
@code
|
||||
const wxArchiveClassFactory *factory;
|
||||
const wxArchiveClassFactory *factory;
|
||||
factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
|
||||
|
||||
if (factory)
|
||||
@@ -339,14 +270,15 @@
|
||||
|
||||
@e Find does not give away ownership of the returned pointer, so it
|
||||
does not need to be deleted.
|
||||
|
||||
There are similar class factories for the filter streams that handle the
|
||||
compression and decompression of a single stream, such as wxGzipInputStream.
|
||||
These can be found using
|
||||
wxFilterClassFactory::Find().
|
||||
These can be found using wxFilterClassFactory::Find().
|
||||
|
||||
For example, to list the contents of archive @e filename:
|
||||
|
||||
@code
|
||||
auto_ptrwxInputStream in(new wxFFileInputStream(filename));
|
||||
auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
|
||||
|
||||
if (in-IsOk())
|
||||
{
|
||||
@@ -363,8 +295,8 @@
|
||||
const wxArchiveClassFactory *acf;
|
||||
acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
|
||||
if (acf) {
|
||||
auto_ptrwxArchiveInputStream arc(acf-NewStream(in.release()));
|
||||
auto_ptrwxArchiveEntry entry;
|
||||
auto_ptr<wxArchiveInputStream> arc(acf-NewStream(in.release()));
|
||||
auto_ptr<wxArchiveEntry> entry;
|
||||
|
||||
// list the contents of the archive
|
||||
while ((entry.reset(arc-GetNextEntry())), entry.get() != @NULL)
|
||||
@@ -378,94 +310,72 @@
|
||||
|
||||
|
||||
|
||||
@section wxarcnoseek Archives on non-seekable streams
|
||||
@section overview_arc_noseek Archives on non-seekable streams
|
||||
|
||||
@ref arc_overview
|
||||
In general, handling archives on non-seekable streams is done in the same
|
||||
way as for seekable streams, with a few caveats.
|
||||
The main limitation is that accessing entries randomly using
|
||||
#OpenEntry()
|
||||
|
||||
The main limitation is that accessing entries randomly using #OpenEntry()
|
||||
is not possible, the entries can only be accessed sequentially in the order
|
||||
they are stored within the archive.
|
||||
|
||||
For each archive type, there will also be other limitations which will
|
||||
depend on the order the entries' meta-data is stored within the archive.
|
||||
These are not too difficult to deal with, and are outlined below.
|
||||
|
||||
@b PutNextEntry and the entry size
|
||||
When writing archives, some archive formats store the entry size before
|
||||
the entry's data (tar has this limitation, zip doesn't). In this case
|
||||
the entry's size must be passed to
|
||||
#PutNextEntry() or an error
|
||||
occurs.
|
||||
the entry's size must be passed to #PutNextEntry() or an error occurs.
|
||||
|
||||
This is only an issue on non-seekable streams, since otherwise the archive
|
||||
output stream can seek back and fix up the header once the size of the
|
||||
entry is known.
|
||||
|
||||
For generic programming, one way to handle this is to supply the size
|
||||
whenever it is known, and rely on the error message from the output
|
||||
stream when the operation is not supported.
|
||||
|
||||
@b GetNextEntry and the weak reference mechanism
|
||||
Some archive formats do not store all an entry's meta-data before the
|
||||
entry's data (zip is an example). In this case, when reading from a
|
||||
non-seekable stream, #GetNextEntry()
|
||||
can only return a partially populated #wxArchiveEntry
|
||||
object - not all the fields are set.
|
||||
non-seekable stream, #GetNextEntry() can only return a partially populated
|
||||
#wxArchiveEntry object - not all the fields are set.
|
||||
|
||||
The input stream then keeps a weak reference to the entry object and
|
||||
updates it when more meta-data becomes available. A weak reference being
|
||||
one that does not prevent you from deleting the wxArchiveEntry object - the
|
||||
input stream only attempts to update it if it is still around.
|
||||
|
||||
The documentation for each archive entry type gives the details
|
||||
of what meta-data becomes available and when. For generic programming,
|
||||
when the worst case must be assumed, you can rely on all the fields
|
||||
of wxArchiveEntry being fully populated when GetNextEntry() returns,
|
||||
with the the following exceptions:
|
||||
|
||||
@li GetSize(): Guaranteed to be available after the entry has been read to #Eof(),
|
||||
or #CloseEntry() has been called
|
||||
|
||||
@li IsReadOnly(): Guaranteed to be available after the end of the archive has been
|
||||
reached, i.e. after GetNextEntry() returns @NULL and Eof() is @true
|
||||
|
||||
This mechanism allows #CopyEntry() to always fully preserve entries' meta-data.
|
||||
No matter what order order the meta-data occurs within the archive, the input stream
|
||||
will always have read it before the output stream must write it.
|
||||
|
||||
|
||||
|
||||
#GetSize()
|
||||
|
||||
|
||||
|
||||
|
||||
Guaranteed to be
|
||||
available after the entry has been read to #Eof(),
|
||||
or #CloseEntry() has been called
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#IsReadOnly()
|
||||
|
||||
|
||||
|
||||
|
||||
Guaranteed to
|
||||
be available after the end of the archive has been reached, i.e. after
|
||||
GetNextEntry() returns @NULL and Eof() is @true
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
This mechanism allows #CopyEntry()
|
||||
to always fully preserve entries' meta-data. No matter what order order
|
||||
the meta-data occurs within the archive, the input stream will always
|
||||
have read it before the output stream must write it.
|
||||
@b wxArchiveNotifier
|
||||
Notifier objects can be used to get a notification whenever an input
|
||||
stream updates a #wxArchiveEntry object's data
|
||||
via the weak reference mechanism.
|
||||
|
||||
Consider the following code which renames an entry in an archive.
|
||||
This is the usual way to modify an entry's meta-data, simply set the
|
||||
required field before writing it with
|
||||
#CopyEntry():
|
||||
required field before writing it with #CopyEntry():
|
||||
|
||||
@code
|
||||
auto_ptrwxArchiveInputStream arc(factory-NewStream(in));
|
||||
auto_ptrwxArchiveOutputStream outarc(factory-NewStream(out));
|
||||
auto_ptrwxArchiveEntry entry;
|
||||
auto_ptr<wxArchiveInputStream> arc(factory-NewStream(in));
|
||||
auto_ptr<wxArchiveOutputStream> outarc(factory-NewStream(out));
|
||||
auto_ptr<wxArchiveEntry> entry;
|
||||
|
||||
outarc-CopyArchiveMetaData(*arc);
|
||||
|
||||
@@ -480,10 +390,8 @@
|
||||
@endcode
|
||||
|
||||
However, for non-seekable streams, this technique cannot be used for
|
||||
fields such as #IsReadOnly(),
|
||||
which are not necessarily set when
|
||||
#GetNextEntry() returns. In
|
||||
this case a #wxArchiveNotifier can be used:
|
||||
fields such as #IsReadOnly(), which are not necessarily set when
|
||||
#GetNextEntry() returns. In this case a #wxArchiveNotifier can be used:
|
||||
|
||||
@code
|
||||
class MyNotifier : public wxArchiveNotifier
|
||||
@@ -493,15 +401,13 @@
|
||||
};
|
||||
@endcode
|
||||
|
||||
The meta-data changes are done in your notifier's
|
||||
#OnEntryUpdated() method,
|
||||
then #SetNotifier() is called before
|
||||
CopyEntry():
|
||||
The meta-data changes are done in your notifier's #OnEntryUpdated() method,
|
||||
then #SetNotifier() is called before CopyEntry():
|
||||
|
||||
@code
|
||||
auto_ptrwxArchiveInputStream arc(factory-NewStream(in));
|
||||
auto_ptrwxArchiveOutputStream outarc(factory-NewStream(out));
|
||||
auto_ptrwxArchiveEntry entry;
|
||||
auto_ptr<wxArchiveInputStream> arc(factory-NewStream(in));
|
||||
auto_ptr<wxArchiveOutputStream> outarc(factory-NewStream(out));
|
||||
auto_ptr<wxArchiveEntry> entry;
|
||||
MyNotifier notifier;
|
||||
|
||||
outarc-CopyArchiveMetaData(*arc);
|
||||
@@ -522,6 +428,5 @@
|
||||
changing the entry name can be done this way too and it works on seekable
|
||||
streams as well as non-seekable.
|
||||
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
|
Reference in New Issue
Block a user