Providng a string to the parser is just a convenience. If you know you are
doing local files, provide a LocalFileInputSource. If you know you are
doing URLs, provide a URLInputSource.
If you don't know ahead of time, then yes you are paying a small price. I'm
not convicned that its even a blip on the radar screen myself though. Can
you show some performance traces that show that this particular code is
costing even a percent of a percent of the overall parsing time? If its
not, then I wouldn't want to be inconsistent, since we use exceptions
consistently within the product to report errors, and a malformed URL is an
error.
----------------------------------------
Dean Roddey
Software Weenie
IBM Center for Java Technology - Silicon Valley
[EMAIL PROTECTED]
Eliot Muir <[EMAIL PROTECTED]> on 04/05/2000 05:17:53 PM
Please respond to [EMAIL PROTECTED]
To: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
cc:
Subject: XMLScanner code... is this exception necessary?
In XMLScanner we have the following code....
//
---------------------------------------------------------------------------
void XMLScanner::scanDocument( const XMLCh* const systemId
, const bool reuseValidator)
{
//
// First we try to parse it as a URL. If that fails, we assume its
// a file and try it that way.
//
InputSource* srcToUse = 0;
try
{
//
// Create a temporary URL. Since this is the primary document,
// it has to be fully qualified. If not, then assume we are just
// mistaking a file for a URL.
//
XMLURL tmpURL(systemId);
if (tmpURL.isRelative())
ThrowXML(MalformedURLException,
XML4CExcepts::URL_NoProtocolPresent);
srcToUse = new URLInputSource(tmpURL);
}
catch(const MalformedURLException&)
{
srcToUse = new LocalFileInputSource(systemId);
}
catch(...)
{
// Just rethrow this, since its not our problem
throw;
}
Janitor<InputSource> janSrc(srcToUse);
scanDocument(*srcToUse, reuseValidator);
}
Using exceptions to branch code is quite expensive in C++ - it's better to
use
an if statement if one can i.e. (or am I missing something that throwing
an exception
does that's useful - some one with greater familiarity with the code could
probably speak
on that)
void XMLScanner::scanDocument( const XMLCh* const systemId
, const bool reuseValidator)
{
//
// First we try to parse it as a URL. If that fails, we assume its
// a file and try it that way.
//
InputSource* srcToUse = 0;
XMLURL tmpURL(systemId);
if (!tmpURL.isRelative())
{
srcToUse = new URLInputSource(tmpURL);
}
else
{
srcToUse = new LocalFileInputSource(systemId);
}
Janitor<InputSource> janSrc(srcToUse);
scanDocument(*srcToUse, reuseValidator);
}
I like the Janitor idea - have you considered the concept of a reference
counted class - it's
quite handy since you can have several "smart pointers" pointing to it from
a bunch of different
objects - when no one references the object it destroys itself (a little
bit like Java)
First define the class you want to safely deallocate as inheriting from a
class like COLreference
Then use a "smart pointer" COLreferencePtr to point it i.e
class InputSource : public COLreference
{
:
:
}
void XMLScanner::scanDocument( const XMLCh* const systemId
, const bool reuseValidator)
{
//
// First we try to parse it as a URL. If that fails, we assume its
// a file and try it that way.
//
COLreferencePtr<InputSource> srcToUse = 0;
XMLURL tmpURL(systemId);
if (!tmpURL.isRelative())
{
srcToUse = new URLInputSource(tmpURL);
}
else
{
srcToUse = new LocalFileInputSource(systemId);
}
scanDocument(*srcToUse, reuseValidator);
// now no need to remember to assign a Janitor to look after
de-allocation
// it also has the advantage that serveral smart pointers can be
pointed to the same object
// and thus it never is destroyed before each has finished with it.
}
COLreferencePtr<InputSource> pSource = 0;
pSource = new InputSource;
class COLreference
{
public:
COLreference();
virtual ~COLreference();
void AddRef() const;
void Release() const;
protected:
size_t m_CountOfRef;
};
inline COLreference::COLreference()
: m_CountOfRef(0)
{
// do nothing
}
inline COLreference::~COLreference()
{
COLPRECONDITION(0 == m_CountOfRef);
}
inline void COLreference::AddRef() const
{
((COLreference*)this)->m_CountOfRef++;
}
inline void COLreference::Release() const
{
COLPRECONDITION(m_CountOfRef > 0);
((COLreference*)this)->m_CountOfRef--;
if (0 == m_CountOfRef)
{
delete (COLreference*)this; // good bye cruel world...!
}
}
template<class R>
class COLreferencePtr : public COLinstanceHeap
{
public:
COLreferencePtr(R* Reference = NULL);
~COLreferencePtr();
R* operator=(R* Reference);
R& operator*();
const R& operator*() const;
R* operator->();
const R* operator->() const;
void clone();
R* get() const { return m_Ptr; }
COLreferencePtr<R>& operator=(const COLreferencePtr<R>& Orig);
private:
R* m_Ptr;
};
template<class R>
inline COLreferencePtr<R>::COLreferencePtr(R* Reference)
{
m_Ptr = Reference;
if (m_Ptr != NULL)
{
m_Ptr->AddRef();
}
}
template<class R>
inline COLreferencePtr<R>::~COLreferencePtr()
{
if (m_Ptr)
{
m_Ptr->Release();
}
}
template<class R>
inline R* COLreferencePtr<R>::operator=(R* pReference)
{
// This has to go before - imagine if pReference == m_Ptr
if (pReference != NULL)
{
pReference->AddRef();
}
if (m_Ptr)
{
m_Ptr->Release();
}
m_Ptr = pReference;
return m_Ptr;
}
template<class R>
inline R& COLreferencePtr<R>::operator*()
{
return *m_Ptr;
}
template<class R>
inline const R& COLreferencePtr<R>::operator*() const
{
return *m_Ptr;
}
template<class R>
inline R* COLreferencePtr<R>::operator->()
{
return m_Ptr;
}
template<class R>
inline const R* COLreferencePtr<R>::operator->() const
{
return m_Ptr;
}
template<class R>
inline void COLreferencePtr<R>::clone()
{
if (m_Ptr == NULL)
{
return;
}
COLreference* pClone = m_Ptr->clone();
pClone->AddRef();
m_Ptr->Release();
m_Ptr = (R*)pClone;
}
template<class R>
inline COLreferencePtr<R>& COLreferencePtr<R>::operator=(const
COLreferencePtr<R>& Orig)
{
if (Orig.m_Ptr)
{
Orig.m_Ptr->AddRef();
}
if (m_Ptr)
{
m_Ptr->Release();
}
m_Ptr = Orig.m_Ptr;
return *this;
}
--
Eliot Muir, Technical Director iNTERFACEWARE
mailto:[EMAIL PROTECTED]
Voice 64-21-333068 http://www.interfaceware.com
Makers of iNTERFACEWARE Chameleon
"Program to the iNTERFACE not the implementation"
(See attached file: WINMAIL.DAT)
WINMAIL.DAT
Description: Binary data
