Fixed a few memory leaks
This commit is contained in:
parent
0e3bfd65e5
commit
8df6cd065b
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Zane U. Ji.
|
||||||
|
*
|
||||||
|
* This file is part of Xml Copy Editor.
|
||||||
|
*
|
||||||
|
* Xml Copy Editor is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* Xml Copy Editor is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Xml Copy Editor; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "threadreaper.h"
|
||||||
|
|
||||||
|
extern wxCriticalSection xmlcopyeditorCriticalSection;
|
||||||
|
|
||||||
|
ThreadReaper::ThreadReaper ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadReaper::~ThreadReaper ()
|
||||||
|
{
|
||||||
|
//wxCriticalSectionLocker lock ( xmlcopyeditorCriticalSection );
|
||||||
|
|
||||||
|
std::vector<boost::shared_ptr<wxThread> >::iterator itr;
|
||||||
|
for ( itr = mList.begin(); itr != mList.end(); itr++)
|
||||||
|
{
|
||||||
|
(**itr).Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadReaper &ThreadReaper::get()
|
||||||
|
{
|
||||||
|
static ThreadReaper reaper;
|
||||||
|
return reaper;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadReaper::add ( wxThread *thread )
|
||||||
|
{
|
||||||
|
// Make sure everything is valid when wxPostMessage is called
|
||||||
|
// and protect mList
|
||||||
|
wxCriticalSectionLocker lock ( xmlcopyeditorCriticalSection );
|
||||||
|
|
||||||
|
mList.push_back ( boost::shared_ptr<wxThread> ( thread ) );
|
||||||
|
|
||||||
|
std::vector<boost::shared_ptr<wxThread> >::iterator itr;
|
||||||
|
for ( itr = mList.begin(); itr != mList.end(); )
|
||||||
|
{
|
||||||
|
if ( (**itr).IsAlive() )
|
||||||
|
itr++;
|
||||||
|
else
|
||||||
|
itr = mList.erase ( itr );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Zane U. Ji.
|
||||||
|
*
|
||||||
|
* This file is part of Xml Copy Editor.
|
||||||
|
*
|
||||||
|
* Xml Copy Editor is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* Xml Copy Editor is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Xml Copy Editor; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef THREADREAPER_H_
|
||||||
|
#define THREADREAPER_H_
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
class ThreadReaper
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ThreadReaper();
|
||||||
|
virtual ~ThreadReaper();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ThreadReaper &get();
|
||||||
|
|
||||||
|
void add ( wxThread *thread );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<boost::shared_ptr<wxThread> > mList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* THREADREAPER_H_ */
|
|
@ -4,7 +4,9 @@
|
||||||
#include "wrapxerces.h"
|
#include "wrapxerces.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "threadreaper.h"
|
||||||
|
|
||||||
|
extern wxCriticalSection xmlcopyeditorCriticalSection;
|
||||||
|
|
||||||
DEFINE_EVENT_TYPE(wxEVT_COMMAND_VALIDATION_COMPLETED);
|
DEFINE_EVENT_TYPE(wxEVT_COMMAND_VALIDATION_COMPLETED);
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ ValidationThread::ValidationThread (
|
||||||
const char *catalogPath,
|
const char *catalogPath,
|
||||||
const char *catalogUtilityPath )
|
const char *catalogUtilityPath )
|
||||||
: wxThread ( wxTHREAD_JOINABLE )
|
: wxThread ( wxTHREAD_JOINABLE )
|
||||||
|
, mStopping ( false )
|
||||||
{
|
{
|
||||||
if ( buffer == NULL )
|
if ( buffer == NULL )
|
||||||
{
|
{
|
||||||
|
@ -35,25 +38,22 @@ void *ValidationThread::Entry()
|
||||||
myCatalogPath,
|
myCatalogPath,
|
||||||
myCatalogUtilityPath ) );
|
myCatalogUtilityPath ) );
|
||||||
|
|
||||||
|
if ( TestDestroy() )
|
||||||
{
|
{
|
||||||
//wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection );
|
return NULL;
|
||||||
if ( TestDestroy() )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
myIsSucceeded = validator->validateMemory (
|
myIsSucceeded = validator->validateMemory (
|
||||||
myBuffer.c_str(),
|
myBuffer.c_str(),
|
||||||
|
myBuffer.size(),
|
||||||
mySystem.c_str(),
|
mySystem.c_str(),
|
||||||
myBuffer.size() );
|
this );
|
||||||
|
|
||||||
if ( TestDestroy() )
|
if ( TestDestroy() )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern wxCriticalSection xmlcopyeditorCriticalSection;
|
|
||||||
wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection );
|
wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection );
|
||||||
|
|
||||||
if ( myIsSucceeded )
|
if ( myIsSucceeded )
|
||||||
|
@ -67,8 +67,18 @@ void *ValidationThread::Entry()
|
||||||
myMessage = validator->getLastError();
|
myMessage = validator->getLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCommandEvent event ( wxEVT_COMMAND_VALIDATION_COMPLETED );
|
if ( !TestDestroy() )
|
||||||
wxPostEvent ( myEventHandler, event );
|
{
|
||||||
|
wxCommandEvent event ( wxEVT_COMMAND_VALIDATION_COMPLETED );
|
||||||
|
wxPostEvent ( myEventHandler, event );
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValidationThread::PendingDelete ()
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
|
||||||
|
ThreadReaper::get().add ( this );
|
||||||
|
}
|
||||||
|
|
|
@ -22,12 +22,21 @@ public:
|
||||||
bool isSucceeded () { return myIsSucceeded; }
|
bool isSucceeded () { return myIsSucceeded; }
|
||||||
const std::pair<int, int> &getPosition() { return myPosition; }
|
const std::pair<int, int> &getPosition() { return myPosition; }
|
||||||
const wxString &getMessage() { return myMessage; }
|
const wxString &getMessage() { return myMessage; }
|
||||||
private:
|
|
||||||
|
void PendingDelete();
|
||||||
|
// Since we can't call wxThread::m_internal->Cancel(), the original
|
||||||
|
// TestDestroy() is useless. Here is the work around.
|
||||||
|
virtual void Cancel() { mStopping = true; }
|
||||||
|
virtual bool TestDestroy() { return mStopping || wxThread::TestDestroy(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
wxEvtHandler *myEventHandler;
|
wxEvtHandler *myEventHandler;
|
||||||
std::string myBuffer, mySystem, myCatalogPath, myCatalogUtilityPath;
|
std::string myBuffer, mySystem, myCatalogPath, myCatalogUtilityPath;
|
||||||
bool myIsSucceeded;
|
bool myIsSucceeded;
|
||||||
std::pair<int, int> myPosition;
|
std::pair<int, int> myPosition;
|
||||||
wxString myMessage;
|
wxString myMessage;
|
||||||
|
|
||||||
|
bool mStopping;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,8 +113,9 @@ bool WrapXerces::validate ( const std::string& fileName )
|
||||||
// tbd: cache grammar
|
// tbd: cache grammar
|
||||||
bool WrapXerces::validateMemory (
|
bool WrapXerces::validateMemory (
|
||||||
const char *buffer,
|
const char *buffer,
|
||||||
|
size_t len,
|
||||||
const char *system,
|
const char *system,
|
||||||
unsigned len )
|
wxThread *thread /*= NULL*/ )
|
||||||
{
|
{
|
||||||
std::auto_ptr<SAX2XMLReader> parser ( XMLReaderFactory::createXMLReader() );
|
std::auto_ptr<SAX2XMLReader> parser ( XMLReaderFactory::createXMLReader() );
|
||||||
|
|
||||||
|
@ -125,7 +126,7 @@ bool WrapXerces::validateMemory (
|
||||||
//parser->setFeature ( XMLUni::fgXercesSchemaFullChecking, true );
|
//parser->setFeature ( XMLUni::fgXercesSchemaFullChecking, true );
|
||||||
parser->setFeature ( XMLUni::fgXercesValidationErrorAsFatal, true );
|
parser->setFeature ( XMLUni::fgXercesValidationErrorAsFatal, true );
|
||||||
parser->setFeature ( XMLUni::fgXercesLoadExternalDTD, true );
|
parser->setFeature ( XMLUni::fgXercesLoadExternalDTD, true );
|
||||||
|
|
||||||
DefaultHandler handler;
|
DefaultHandler handler;
|
||||||
MySAX2Handler mySAX2Handler;
|
MySAX2Handler mySAX2Handler;
|
||||||
parser->setContentHandler ( &handler );
|
parser->setContentHandler ( &handler );
|
||||||
|
@ -138,7 +139,17 @@ bool WrapXerces::validateMemory (
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parser->parse ( source );
|
if ( thread == NULL )
|
||||||
|
{
|
||||||
|
parser->parse ( source );
|
||||||
|
}
|
||||||
|
else if ( !thread->TestDestroy() )
|
||||||
|
{
|
||||||
|
XMLPScanToken token;
|
||||||
|
if ( parser->parseFirst ( source, token ) )
|
||||||
|
while ( (!thread->TestDestroy()) && parser->parseNext ( token ) )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch ( XMLException& e )
|
catch ( XMLException& e )
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,8 @@ class WrapXerces
|
||||||
std::string catalogUtilityPath = "" );
|
std::string catalogUtilityPath = "" );
|
||||||
~WrapXerces();
|
~WrapXerces();
|
||||||
bool validate ( const std::string& fileName );
|
bool validate ( const std::string& fileName );
|
||||||
bool validateMemory ( const char *buffer, const char *system, unsigned len );
|
bool validateMemory ( const char *buffer, size_t len,
|
||||||
|
const char *system, wxThread *thread = NULL );
|
||||||
const wxString &getLastError();
|
const wxString &getLastError();
|
||||||
std::pair<int, int> getErrorPosition();
|
std::pair<int, int> getErrorPosition();
|
||||||
static wxString toString ( const XMLCh *str );
|
static wxString toString ( const XMLCh *str );
|
||||||
|
|
|
@ -3123,7 +3123,7 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
|
||||||
|
|
||||||
statusProgress ( wxEmptyString );
|
statusProgress ( wxEmptyString );
|
||||||
|
|
||||||
char *iconvBuffer = 0;
|
wxCharBuffer iconvBuffer;
|
||||||
size_t iconvBufferLen = 0;
|
size_t iconvBufferLen = 0;
|
||||||
|
|
||||||
char *finalBuffer;
|
char *finalBuffer;
|
||||||
|
@ -3230,21 +3230,21 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
|
||||||
iconvLenMultiplier = 1;
|
iconvLenMultiplier = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t nconv;
|
||||||
|
char *buffer;
|
||||||
size_t iconvBufferLeft, docBufferLeft;
|
size_t iconvBufferLeft, docBufferLeft;
|
||||||
iconvBufferLen = iconvBufferLeft = (docBufferLen - nBOM) * iconvLenMultiplier + 1;
|
iconvBufferLen = iconvBufferLeft = (docBufferLen - nBOM) * iconvLenMultiplier + 1;
|
||||||
docBufferLeft = docBufferLen;
|
docBufferLeft = docBufferLen;
|
||||||
iconvBuffer = new char[iconvBufferLen];
|
iconvBuffer.extend ( iconvBufferLen );
|
||||||
finalBuffer = iconvBuffer; // iconvBuffer will be incremented by iconv
|
finalBuffer = buffer = iconvBuffer.data(); // buffer will be incremented by iconv
|
||||||
size_t nconv;
|
|
||||||
|
|
||||||
nconv = reinterpret_cast < universal_iconv & > ( iconv ) (
|
nconv = reinterpret_cast < universal_iconv & > ( iconv ) (
|
||||||
cd,
|
cd,
|
||||||
&docBuffer,
|
&docBuffer,
|
||||||
&docBufferLeft,
|
&docBufferLeft,
|
||||||
&iconvBuffer,
|
&buffer,
|
||||||
&iconvBufferLeft );
|
&iconvBufferLeft );
|
||||||
|
|
||||||
*iconvBuffer = '\0';
|
*buffer = '\0';
|
||||||
|
|
||||||
iconv_close ( cd );
|
iconv_close ( cd );
|
||||||
|
|
||||||
|
@ -3255,7 +3255,6 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
|
||||||
fileName.c_str(),
|
fileName.c_str(),
|
||||||
wideEncoding.c_str() );
|
wideEncoding.c_str() );
|
||||||
messagePane ( message, CONST_STOP );
|
messagePane ( message, CONST_STOP );
|
||||||
delete[] finalBuffer;
|
|
||||||
delete binaryfile; //delete memorymap;
|
delete binaryfile; //delete memorymap;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,7 @@ XmlCtrl::~XmlCtrl()
|
||||||
|
|
||||||
if ( validationThread != NULL )
|
if ( validationThread != NULL )
|
||||||
{
|
{
|
||||||
validationThread->Kill();
|
validationThread->PendingDelete();
|
||||||
delete validationThread;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -299,6 +299,7 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
|
||||||
PromptGeneratorData *d;
|
PromptGeneratorData *d;
|
||||||
d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor
|
d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor
|
||||||
|
|
||||||
|
int ret;
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
|
||||||
// auxPath req'd?
|
// auxPath req'd?
|
||||||
|
@ -307,15 +308,17 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
|
||||||
ReadFile::run ( d->auxPath, buffer );
|
ReadFile::run ( d->auxPath, buffer );
|
||||||
if ( buffer.empty() )
|
if ( buffer.empty() )
|
||||||
{
|
{
|
||||||
return false;
|
return XML_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string encoding = XmlEncodingHandler::get ( buffer );
|
std::string encoding = XmlEncodingHandler::get ( buffer );
|
||||||
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
|
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
|
||||||
if ( !dtdParser )
|
if ( !dtdParser )
|
||||||
return false;
|
return XML_STATUS_ERROR;
|
||||||
XML_SetBase ( dtdParser, d->auxPath.c_str() );
|
XML_SetBase ( dtdParser, d->auxPath.c_str() );
|
||||||
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
|
ret = XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
|
||||||
|
XML_ParserFree ( dtdParser );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string stdPublicId;
|
std::string stdPublicId;
|
||||||
|
@ -358,7 +361,7 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
|
||||||
std::string encoding = XmlEncodingHandler::get ( buffer );
|
std::string encoding = XmlEncodingHandler::get ( buffer );
|
||||||
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
|
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
|
||||||
if ( !dtdParser )
|
if ( !dtdParser )
|
||||||
return false;
|
return XML_STATUS_ERROR;
|
||||||
|
|
||||||
wxString wideName, wideDir;
|
wxString wideName, wideDir;
|
||||||
wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() );
|
wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() );
|
||||||
|
@ -366,7 +369,9 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
|
||||||
wideDir = fn.GetPath();
|
wideDir = fn.GetPath();
|
||||||
XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) );
|
XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) );
|
||||||
|
|
||||||
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
|
ret = XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
|
||||||
|
XML_ParserFree ( dtdParser );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLCALL XmlPromptGenerator::entitydeclhandler (
|
void XMLCALL XmlPromptGenerator::entitydeclhandler (
|
||||||
|
|
Loading…
Reference in New Issue