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)

Attachment: WINMAIL.DAT
Description: Binary data

Reply via email to