]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/zipstrm.cpp
fix for always terminating intermediate UniChar String for 4 bytes wchar_t
[wxWidgets.git] / src / common / zipstrm.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: zipstream.cpp
3// Purpose: input stream for ZIP archive access
4// Author: Vaclav Slavik
5// Copyright: (c) 1999 Vaclav Slavik
6// Licence: wxWindows Licence
7/////////////////////////////////////////////////////////////////////////////
8
9#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
10#pragma implementation "zipstrm.h"
11#endif
12
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
21
22#include "wx/log.h"
23#include "wx/intl.h"
24#include "wx/stream.h"
25#include "wx/wfstream.h"
26#include "wx/zipstrm.h"
27#include "wx/utils.h"
28
29/* Not the right solution (paths in makefiles) but... */
30#ifdef __BORLANDC__
31#include "../common/unzip.h"
32#else
33#include "unzip.h"
34#endif
35
36
37wxZipInputStream::wxZipInputStream(const wxString& archive, const wxString& file) : wxInputStream()
38{
39 unz_file_info zinfo;
40
41 m_Pos = 0;
42 m_Size = 0;
43 m_Archive = (void*) unzOpen(archive.mb_str(wxConvFile));
44 if (m_Archive == NULL)
45 {
46 m_lasterror = wxSTREAM_READ_ERROR;
47 return;
48 }
49 // TODO what encoding does ZIP use?
50 if (unzLocateFile((unzFile)m_Archive, file.ToAscii(), 0) != UNZ_OK)
51 {
52 m_lasterror = wxSTREAM_READ_ERROR;
53 return;
54 }
55
56 unzGetCurrentFileInfo((unzFile)m_Archive, &zinfo, (char*) NULL, 0, (void*) NULL, 0, (char*) NULL, 0);
57
58 if (unzOpenCurrentFile((unzFile)m_Archive) != UNZ_OK)
59 {
60 m_lasterror = wxSTREAM_READ_ERROR;
61 return;
62 }
63 m_Size = (size_t)zinfo.uncompressed_size;
64}
65
66
67
68wxZipInputStream::~wxZipInputStream()
69{
70 if (m_Archive)
71 {
72 if (m_Size != 0)
73 unzCloseCurrentFile((unzFile)m_Archive);
74 unzClose((unzFile)m_Archive);
75 }
76}
77
78bool wxZipInputStream::Eof() const
79{
80 wxASSERT_MSG( m_Pos <= (off_t)m_Size,
81 _T("wxZipInputStream: invalid current position") );
82
83 return m_Pos >= (off_t)m_Size;
84}
85
86
87size_t wxZipInputStream::OnSysRead(void *buffer, size_t bufsize)
88{
89 wxASSERT_MSG( m_Pos <= (off_t)m_Size,
90 _T("wxZipInputStream: invalid current position") );
91
92 if ( m_Pos >= (off_t)m_Size )
93 {
94 m_lasterror = wxSTREAM_EOF;
95 return 0;
96 }
97
98 if (m_Pos + bufsize > m_Size)
99 bufsize = m_Size - m_Pos;
100
101 unzReadCurrentFile((unzFile)m_Archive, buffer, bufsize);
102 m_Pos += bufsize;
103
104 return bufsize;
105}
106
107
108
109off_t wxZipInputStream::OnSysSeek(off_t seek, wxSeekMode mode)
110{
111 // NB: since ZIP files don't natively support seeking, we have to
112 // implement a brute force workaround -- reading all the data
113 // between current and the new position (or between beginning of
114 // the file and new position...)
115
116 off_t nextpos;
117
118 switch ( mode )
119 {
120 case wxFromCurrent : nextpos = seek + m_Pos; break;
121 case wxFromStart : nextpos = seek; break;
122 case wxFromEnd : nextpos = m_Size - 1 + seek; break;
123 default : nextpos = m_Pos; break; /* just to fool compiler, never happens */
124 }
125
126 size_t toskip;
127 if ( nextpos > m_Pos )
128 {
129 toskip = nextpos - m_Pos;
130 }
131 else
132 {
133 unzCloseCurrentFile((unzFile)m_Archive);
134 if (unzOpenCurrentFile((unzFile)m_Archive) != UNZ_OK)
135 {
136 m_lasterror = wxSTREAM_READ_ERROR;
137 return m_Pos;
138 }
139 toskip = nextpos;
140 }
141
142 if ( toskip > 0 )
143 {
144 const size_t BUFSIZE = 4096;
145 size_t sz;
146 char buffer[BUFSIZE];
147 while ( toskip > 0 )
148 {
149 sz = wxMin(toskip, BUFSIZE);
150 unzReadCurrentFile((unzFile)m_Archive, buffer, sz);
151 toskip -= sz;
152 }
153 }
154
155 m_Pos = nextpos;
156 return m_Pos;
157}
158
159#endif
160 // wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB