This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
334 lines
8.4 KiB
C++
334 lines
8.4 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/fileback.cpp
|
|
// Purpose: Back an input stream with memory or a file
|
|
// Author: Mike Wetherell
|
|
// Copyright: (c) 2006 Mike Wetherell
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_FILESYSTEM
|
|
|
|
#include "wx/private/fileback.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/utils.h"
|
|
#include "wx/log.h"
|
|
#endif
|
|
|
|
#include "wx/private/filename.h"
|
|
|
|
// Prefer wxFFile unless wxFile has large file support but wxFFile does not.
|
|
//
|
|
#if wxUSE_FFILE && (defined wxHAS_LARGE_FFILES || !defined wxHAS_LARGE_FILES)
|
|
typedef wxFFile wxBFFile;
|
|
static const bool wxBadSeek = false;
|
|
#else
|
|
typedef wxFile wxBFFile;
|
|
static const wxFileOffset wxBadSeek = wxInvalidOffset;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Backing file implementation
|
|
|
|
class wxBackingFileImpl
|
|
{
|
|
public:
|
|
wxBackingFileImpl(wxInputStream *stream,
|
|
size_t bufsize,
|
|
const wxString& prefix);
|
|
~wxBackingFileImpl();
|
|
|
|
void Release() { if (--m_refcount == 0) delete this; }
|
|
wxBackingFileImpl *AddRef() { m_refcount++; return this; }
|
|
|
|
wxStreamError ReadAt(wxFileOffset pos, void *buffer, size_t *size);
|
|
wxFileOffset GetLength() const;
|
|
|
|
private:
|
|
int m_refcount;
|
|
|
|
wxInputStream *m_stream;
|
|
wxStreamError m_parenterror;
|
|
|
|
char *m_buf;
|
|
size_t m_bufsize;
|
|
size_t m_buflen;
|
|
|
|
wxString m_prefix;
|
|
wxString m_filename;
|
|
wxBFFile m_file;
|
|
wxFileOffset m_filelen;
|
|
};
|
|
|
|
wxBackingFileImpl::wxBackingFileImpl(wxInputStream *stream,
|
|
size_t bufsize,
|
|
const wxString& prefix)
|
|
: m_refcount(1),
|
|
m_stream(stream),
|
|
m_parenterror(wxSTREAM_NO_ERROR),
|
|
m_buf(NULL),
|
|
m_bufsize(bufsize),
|
|
m_buflen(0),
|
|
m_prefix(prefix),
|
|
m_filelen(0)
|
|
{
|
|
wxFileOffset len = m_stream->GetLength();
|
|
|
|
if (len >= 0 && len + size_t(1) < m_bufsize)
|
|
m_bufsize = size_t(len + 1);
|
|
|
|
if (m_bufsize)
|
|
m_buf = new char[m_bufsize];
|
|
}
|
|
|
|
wxBackingFileImpl::~wxBackingFileImpl()
|
|
{
|
|
delete m_stream;
|
|
delete [] m_buf;
|
|
|
|
if (!m_filename.empty())
|
|
wxRemoveFile(m_filename);
|
|
}
|
|
|
|
wxStreamError wxBackingFileImpl::ReadAt(wxFileOffset pos,
|
|
void *buffer,
|
|
size_t *size)
|
|
{
|
|
size_t reqestedSize = *size;
|
|
*size = 0;
|
|
|
|
// size1 is the number of bytes it will read directly from the backing
|
|
// file. size2 is any remaining bytes not yet backed, these are returned
|
|
// from the buffer or read from the parent stream.
|
|
size_t size1, size2;
|
|
|
|
if (pos + reqestedSize <= m_filelen + size_t(0)) {
|
|
size1 = reqestedSize;
|
|
size2 = 0;
|
|
} else if (pos < m_filelen) {
|
|
size1 = size_t(m_filelen - pos);
|
|
size2 = reqestedSize - size1;
|
|
} else {
|
|
size1 = 0;
|
|
size2 = reqestedSize;
|
|
}
|
|
|
|
if (pos < 0)
|
|
return wxSTREAM_READ_ERROR;
|
|
|
|
// read the backing file
|
|
if (size1) {
|
|
if (m_file.Seek(pos) == wxBadSeek)
|
|
return wxSTREAM_READ_ERROR;
|
|
|
|
ssize_t n = m_file.Read(buffer, size1);
|
|
if (n > 0) {
|
|
*size = n;
|
|
pos += n;
|
|
}
|
|
|
|
if (*size < size1)
|
|
return wxSTREAM_READ_ERROR;
|
|
}
|
|
|
|
// read from the buffer or parent stream
|
|
if (size2)
|
|
{
|
|
while (*size < reqestedSize)
|
|
{
|
|
// if pos is further ahead than the parent has been read so far,
|
|
// then read forward in the parent stream
|
|
while (pos - m_filelen + size_t(0) >= m_buflen)
|
|
{
|
|
// if the parent is small enough, don't use a backing file
|
|
// just the buffer memory
|
|
if (!m_stream && m_filelen == 0)
|
|
return m_parenterror;
|
|
|
|
// before refilling the buffer write out the current buffer
|
|
// to the backing file if there is anything in it
|
|
if (m_buflen)
|
|
{
|
|
if (!m_file.IsOpened())
|
|
if (!wxCreateTempFile(m_prefix, &m_file, &m_filename))
|
|
return wxSTREAM_READ_ERROR;
|
|
|
|
if (m_file.Seek(m_filelen) == wxBadSeek)
|
|
return wxSTREAM_READ_ERROR;
|
|
|
|
size_t count = m_file.Write(m_buf, m_buflen);
|
|
m_filelen += count;
|
|
|
|
if (count < m_buflen) {
|
|
wxDELETE(m_stream);
|
|
if (count > 0) {
|
|
wxDELETEA(m_buf);
|
|
m_buflen = 0;
|
|
}
|
|
m_parenterror = wxSTREAM_READ_ERROR;
|
|
return m_parenterror;
|
|
}
|
|
|
|
m_buflen = 0;
|
|
|
|
if (!m_stream) {
|
|
wxDELETEA(m_buf);
|
|
}
|
|
}
|
|
|
|
if (!m_stream)
|
|
return m_parenterror;
|
|
|
|
// refill buffer
|
|
m_buflen = m_stream->Read(m_buf, m_bufsize).LastRead();
|
|
|
|
if (m_buflen < m_bufsize) {
|
|
m_parenterror = m_stream->GetLastError();
|
|
if (m_parenterror == wxSTREAM_NO_ERROR)
|
|
m_parenterror = wxSTREAM_EOF;
|
|
wxDELETE(m_stream);
|
|
}
|
|
}
|
|
|
|
// copy to the user's buffer
|
|
size_t start = size_t(pos - m_filelen);
|
|
size_t len = wxMin(m_buflen - start, reqestedSize - *size);
|
|
|
|
memcpy((char*)buffer + *size, m_buf + start, len);
|
|
*size += len;
|
|
pos += len;
|
|
}
|
|
}
|
|
|
|
return wxSTREAM_NO_ERROR;
|
|
}
|
|
|
|
wxFileOffset wxBackingFileImpl::GetLength() const
|
|
{
|
|
if (m_parenterror != wxSTREAM_EOF) {
|
|
wxLogNull nolog;
|
|
return m_stream->GetLength();
|
|
}
|
|
return m_filelen + m_buflen;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Backing File, the handle part
|
|
|
|
wxBackingFile::wxBackingFile(wxInputStream *stream,
|
|
size_t bufsize,
|
|
const wxString& prefix)
|
|
: m_impl(new wxBackingFileImpl(stream, bufsize, prefix))
|
|
{
|
|
}
|
|
|
|
wxBackingFile::wxBackingFile(const wxBackingFile& backer)
|
|
: m_impl(backer.m_impl ? backer.m_impl->AddRef() : NULL)
|
|
{
|
|
}
|
|
|
|
wxBackingFile& wxBackingFile::operator=(const wxBackingFile& backer)
|
|
{
|
|
if (backer.m_impl != m_impl) {
|
|
if (m_impl)
|
|
m_impl->Release();
|
|
|
|
m_impl = backer.m_impl;
|
|
|
|
if (m_impl)
|
|
m_impl->AddRef();
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
wxBackingFile::~wxBackingFile()
|
|
{
|
|
if (m_impl)
|
|
m_impl->Release();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Input stream
|
|
|
|
wxBackedInputStream::wxBackedInputStream(const wxBackingFile& backer)
|
|
: m_backer(backer),
|
|
m_pos(0)
|
|
{
|
|
}
|
|
|
|
wxFileOffset wxBackedInputStream::GetLength() const
|
|
{
|
|
return m_backer.m_impl->GetLength();
|
|
}
|
|
|
|
wxFileOffset wxBackedInputStream::FindLength() const
|
|
{
|
|
wxFileOffset len = GetLength();
|
|
|
|
if (len == wxInvalidOffset && IsOk()) {
|
|
// read a byte at 7ff...ffe
|
|
wxFileOffset pos = 1;
|
|
pos <<= sizeof(pos) * 8 - 1;
|
|
pos = ~pos - 1;
|
|
char ch;
|
|
size_t size = 1;
|
|
m_backer.m_impl->ReadAt(pos, &ch, &size);
|
|
len = GetLength();
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
size_t wxBackedInputStream::OnSysRead(void *buffer, size_t size)
|
|
{
|
|
if (!IsOk())
|
|
return 0;
|
|
|
|
m_lasterror = m_backer.m_impl->ReadAt(m_pos, buffer, &size);
|
|
m_pos += size;
|
|
return size;
|
|
}
|
|
|
|
wxFileOffset wxBackedInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
|
|
{
|
|
switch (mode) {
|
|
case wxFromCurrent:
|
|
{
|
|
m_pos += pos;
|
|
break;
|
|
}
|
|
case wxFromEnd:
|
|
{
|
|
wxFileOffset len = GetLength();
|
|
if (len == wxInvalidOffset)
|
|
return wxInvalidOffset;
|
|
m_pos = len + pos;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
m_pos = pos;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return m_pos;
|
|
}
|
|
|
|
wxFileOffset wxBackedInputStream::OnSysTell() const
|
|
{
|
|
return m_pos;
|
|
}
|
|
|
|
#endif // wxUSE_FILESYSTEM
|