Light update of the exception.cpp:

ExceptionBase& ExceptionBase::operator= (const ExceptionBase& ex) :
if strdup() is failed then copy string to the internal buf_ with truncate.

Farid.

> -----Original Message-----
> From: Farid Zaripov [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, July 12, 2006 7:18 PM
> To: [email protected]
> Subject: RE: design of testuite exceptions (was: Re: svn
> commit: r418319 -
> /incubator/stdcxx/trunk/tests/strings/21.string.io.cpp)
>
>     Martin, I implemented your latest notes about testsuite
> exception (rw_exception.h, exception.cpp). The updated
> version is attached.
/************************************************************************
 *
 * exception.cpp - exceptions testsuite helpers
 *
 * $Id: $
 *
 ************************************************************************
 *
 * Copyright 2006 The Apache Software Foundation or its licensors,
 * as applicable.
 *
 * Copyright 2006 Rogue Wave Software.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 **************************************************************************/

// expand _TEST_EXPORT macros
#define _RWSTD_TEST_SRC

#include <rw_exception.h>
#include <driver.h>   
#include <rw_printf.h>
#include <string.h>         // for strncpy()
#include <malloc.h>         // for free()
#include <stddef.h>         // for size_t
#include <stdarg.h>         // for va_arg(), va_list
#include <new>              // for std::bad_alloc

/**************************************************************************/

Exception::~Exception ()
{
}

/**************************************************************************/

struct ExceptionBase
{
    char  buf_ [256];
    char* what_;

    ExceptionBase ();

    ExceptionBase (const ExceptionBase&);

    ~ExceptionBase ();

    ExceptionBase& operator= (const ExceptionBase&);

private:
    void free_ ();
};

ExceptionBase::ExceptionBase () : what_ (buf_)
{
    buf_ [0] = '\0';
}

ExceptionBase::ExceptionBase (const ExceptionBase& ex) : what_ (buf_)
{
    *this = ex;
}

ExceptionBase::~ExceptionBase ()
{
    free_ ();
}

ExceptionBase& ExceptionBase::operator= (const ExceptionBase& ex)
{
    if (&ex != this) {

        free_ ();

        if (ex.buf_ != ex.what_) {
            what_ = strdup (ex.what_);
            if (!what_) {
                const size_t maxlen = sizeof (buf_) - 1;
                what_ = buf_;
                strncpy (buf_, ex.what_, maxlen);
                buf_ [maxlen] = '\0';
            }
        }
        else
            strncpy (buf_, ex.buf_, sizeof (buf_));
    }

    return *this;
}

void ExceptionBase::free_ ()
{
    if (buf_ != what_) {
        free (what_);
        what_ = buf_;
    }
}

/**************************************************************************/

struct BadAlloc : std::bad_alloc, ExceptionBase
{
    ~BadAlloc () _THROWS (()) {}

    const char* what () const _THROWS (())
    {
        return what_;
    }
};

/**************************************************************************/

struct StreamException : Exception, ExceptionBase
{
    StreamException () : Exception (ex_stream)
    {
    }

    const char* what () const
    {
        return what_;
    }
};

/**************************************************************************/

_TEST_EXPORT int
rw_vasnprintf (char**, size_t*, const char*, va_list);

/**************************************************************************/

static int
_rw_format (char** pbuf, size_t* pbufsize, const char* file, int line,
            const char* function, const char* fmt, va_list va)
{
    const int nchars1 = function ?
        rw_asnprintf (pbuf, pbufsize, "\"%s\", %d, \"%s\" ",
                      file, line, function) :
        rw_asnprintf (pbuf, pbufsize, "\"%s\", %d, ", file, line);

    if (0 > nchars1)
        return nchars1;

    char *tmpbuf = 0;
    size_t tmpsize = 0;

    const int nchars2 = rw_vasnprintf (&tmpbuf, &tmpsize, fmt, va);

    if (0 > nchars2) {
        free (tmpbuf);
        return nchars1;
    }

    const int nchars3 = rw_asnprintf (pbuf, pbufsize, "%{+}%s", tmpbuf);

    free (tmpbuf);

    return 0 > nchars3 ? nchars1 : nchars1 + nchars3;
}

// str should be allocated by malloc() call
// str shouldn't be free after call _rw_init_exception()
static void _rw_init_exception (ExceptionBase& ex, char* str, size_t nchars)
{
    if (nchars < sizeof (ex.buf_)) {
        memcpy (ex.buf_, str, nchars);
        ex.buf_ [nchars] = '\0';
        free (str);
    }
    else
        ex.what_ = str;
}

_TEST_EXPORT void
rw_throw (ExceptionId exid, const char *file, int line,
          const char *function, const char *fmt, ...)
{
    // format string
    char* buf = 0;
    size_t bufsize = 0;

    va_list va;
    va_start (va, fmt);

    const int nchars = _rw_format (&buf, &bufsize, file, line,
                                   function, fmt, va);

    va_end (va);

    switch (exid) {

    case ex_stream:
        {
            StreamException ex;
            _rw_init_exception (ex, buf, nchars);
            throw ex;
        }

    case ex_bad_alloc:
        {
            BadAlloc ex;
            _rw_init_exception (ex, buf, nchars);
            throw ex;
        }

    default:
        free (buf);
        throw ex_unknown;
    }
}

Reply via email to