/************************************************************************
*
* alg_test.cpp - definitions of class X members
*
* $Id: alg_test.cpp 349035 2005-11-25 23:17:58Z sebor $
*
************************************************************************
*
* Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
* Software division. 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 <stddef.h> // for size_t
#include <stdlib.h> // for rand()
#include <string.h> // for strlen()
#include <ctype.h> // for toupper()
#include <alg_test.h>
#ifdef _RWSTDDEBUG
// use own assertion mechanism for better diagnostic output
# undef assert
# define assert(expr) _RWSTD_ASSERT(expr)
#else
# include <assert.h> // for assert()
#endif // _RWSTDDEBUG
/* static */ size_t X::count_;
/* static */ int X::id_gen_; // generates unique non-zero ids
/* static */ int (*X::_gen_)() ; // extern "C++" int (*)()
/* static */ size_t X::n_total_def_ctor_;
/* static */ size_t X::n_total_copy_ctor_;
/* static */ size_t X::n_total_dtor_;
/* static */ size_t X::_n_total_op_assign_ ;
/* static */ size_t X::_n_total_op_eq_;
/* static */ size_t X::n_total_op_lt_;
// default values of pointers
/* static */ size_t* X::def_ctor_throw_ptr_ = &X::def_ctor_throw_count_;
/* static */ size_t* X::copy_ctor_throw_ptr_ = &X::copy_ctor_throw_count_;
/* static */ size_t* X::dtor_throw_ptr_ = &X::dtor_throw_count_;
/* static */ size_t* X::op_assign_throw_ptr_ = &X::op_assign_throw_count_;
/* static */ size_t* X::op_eq_throw_ptr_ = &X::op_eq_throw_count_;
/* static */ size_t* X::op_lt_throw_ptr_ = &X::op_lt_throw_count_;
// exception throwing initially disabled
/* static */ size_t X::def_ctor_throw_count_ = size_t (-1);
/* static */ size_t X::copy_ctor_throw_count_ = size_t (-1);
/* static */ size_t X::dtor_throw_count_ = size_t (-1);
/* static */ size_t X::op_assign_throw_count_ = size_t (-1);
/* static */ size_t X::op_eq_throw_count_ = size_t (-1);
/* static */ size_t X::op_lt_throw_count_ = size_t (-1);
X::X ()
: id_ (++id_gen_), origin_ (id_), src_id_ (id_), val_ (0),
n_copy_ctor_ (0), n_op_assign_ (0), n_op_eq_ (0), n_op_lt_ (0)
{
// increment the total number of invocations of the default ctor
// (do so even if the function throws an exception below)
++n_total_def_ctor_;
#ifndef _RWSTD_NO_EXCEPTIONS
if (def_ctor_throw_ptr_ && n_total_def_ctor_ == *def_ctor_throw_ptr_) {
DefCtor ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
// initialize the object's value
if (_gen_)
val_ = _gen_ ();
// increment the number of successfully constructed objects
++count_;
}
X::X (const X &rhs)
: id_ (++id_gen_), origin_ (rhs.origin_), src_id_ (rhs.id_),
val_ (rhs.val_),
n_copy_ctor_ (0), n_op_assign_ (0), n_op_eq_ (0), n_op_lt_ (0)
{
// verify id validity
assert (rhs.id_ && rhs.id_ < id_gen_);
// increment the number of times `rhs' has been copied
// (do so even if the function throws an exception below)
++_RWSTD_CONST_CAST (X*, &rhs)->n_copy_ctor_;
// increment the total number of invocations of the copy ctor
// (do so even if the function throws an exception below)
++n_total_copy_ctor_;
#ifndef _RWSTD_NO_EXCEPTIONS
// throw an exception if the number of calls
// to the copy ctor reaches the given value
if (copy_ctor_throw_ptr_ && n_total_copy_ctor_ == *copy_ctor_throw_ptr_) {
CopyCtor ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
// increment the number of successfully constructed objects
++count_;
}
X::~X ()
{
// verify id validity
assert (id_ && id_ <= id_gen_);
// increment the total number of invocations of the dtor
// (do so even if the function throws an exception below)
++n_total_dtor_;
#ifndef _RWSTD_NO_EXCEPTIONS
// throw an exception if the number of calls
// to the class dtor reaches the given value
if (dtor_throw_ptr_ && n_total_dtor_ == *dtor_throw_ptr_) {
Dtor ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
// decrement the number of objects in existence
--count_;
// invalidate id
_RWSTD_CONST_CAST (int&, this->id_) = 0;
}
X&
X::operator= (const X &rhs)
{
// verify id validity and uniqueness
assert (id_ && id_ <= id_gen_);
assert (rhs.id_ && rhs.id_ <= id_gen_);
assert (this == &rhs || id_ != rhs.id_);
// increment the total number of invocations of the operator
// (do so even if the function throws an exception below)
++n_total_op_assign_;
// increment the number of times the object has been assigned to
// (do so even if the function throws an exception below)
++n_op_assign_;
#ifndef _RWSTD_NO_EXCEPTIONS
// throw an exception if the number of calls to
// the assignment operator reaches the given value
if (op_assign_throw_ptr_ && n_total_op_assign_ == *op_assign_throw_ptr_) {
OpAssign ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
// overwrite value and source id only when the operation
// is successful (i.e., only when it doesn't throw)
origin_ = rhs.origin_;
src_id_ = rhs.id_;
val_ = rhs.val_;
return *this;
}
bool
X::operator== (const X &rhs) const
{
// verify id validity and uniqueness
assert (id_ && id_ <= id_gen_);
assert (rhs.id_ && rhs.id_ <= id_gen_);
assert (this == &rhs || id_ != rhs.id_);
// increment the number of times each distinct object
// has been used as the argument to operator==
// (do so even if the function throws an exception below)
++_RWSTD_CONST_CAST (X*, this)->n_op_eq_;
if (this != &rhs)
++_RWSTD_CONST_CAST (X*, &rhs)->n_op_eq_;
// increment the total number of invocations of the operator
// (do so even if the function throws an exception below)
++n_total_op_eq_;
#ifndef _RWSTD_NO_EXCEPTIONS
// throw an exception if the number of calls
// to operator== reaches the given value
if (op_eq_throw_ptr_ && n_total_op_eq_ == *op_eq_throw_ptr_) {
OpEq ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
return val_ == rhs.val_;
}
bool
X::operator< (const X &rhs) const
{
// verify id validity and uniqueness
assert (id_ && id_ <= id_gen_);
assert (rhs.id_ && rhs.id_ <= id_gen_);
assert (this == &rhs || id_ != rhs.id_);
// increment the number of times each distinct object
// has been used as the argument to operator<
// (do so even if the function throws an exception below)
++_RWSTD_CONST_CAST (X*, this)->n_op_lt_;
if (this != &rhs)
++_RWSTD_CONST_CAST (X*, &rhs)->n_op_lt_;
// increment the total number of invocations of the operator
// (do so even if the function throws an exception below)
++n_total_op_lt_;
#ifndef _RWSTD_NO_EXCEPTIONS
// throw an exception if the number of calls
// to operator== reaches the given value
if (op_lt_throw_ptr_ && n_total_op_lt_ == *op_lt_throw_ptr_) {
OpLt ex;
ex.id_ = id_;
throw ex;
}
#endif // _RWSTD_NO_EXCEPTIONS
return val_ < rhs.val_;
}
bool X::
is_count (size_t n_copy_ctor,
size_t n_op_assign,
size_t n_op_eq,
size_t n_op_lt) const
{
// verify id validity
assert (id_ && id_ <= id_gen_);
return (size_t (-1) == n_copy_ctor || n_copy_ctor_ == n_copy_ctor)
&& (size_t (-1) == n_op_assign || n_op_assign_ == n_op_assign)
&& (size_t (-1) == n_op_eq || n_op_eq_ == n_op_eq)
&& (size_t (-1) == n_op_lt || n_op_lt_ == n_op_lt);
}
/* static */ bool X::
is_total (size_t cnt,
size_t n_def_ctor,
size_t n_copy_ctor,
size_t n_op_assign,
size_t n_op_eq,
size_t n_op_lt)
{
return (size_t (-1) == cnt || count_ == cnt)
&& (size_t (-1) == n_def_ctor || n_total_def_ctor_ == n_def_ctor)
&& (size_t (-1) == n_copy_ctor || n_total_copy_ctor_ == n_copy_ctor)
&& (size_t (-1) == n_op_assign || n_total_op_assign_ == n_op_assign)
&& (size_t (-1) == n_op_eq || n_total_op_eq_ == n_op_eq)
&& (size_t (-1) == n_op_lt || n_total_op_lt_ == n_op_lt);
}
/* static void
X::reset_totals ()
{
n_total_def_ctor_ =
n_total_copy_ctor_ =
n_total_dtor_ =
n_total_op_assign_ =
n_total_op_eq_ =
n_total_op_lt_ = 0;
}*/
typedef unsigned char UChar;
// used to initialize an array of objects of type X
static const char *xinit_begin;
static int xinit ()
{
if (xinit_begin)
return UChar (*xinit_begin++);
return 0;
}
/* static */ X*
X::from_char (const char *str, size_t len /* = -1 */)
{
// handle null pointers
if (!str)
return 0;
// compute the length of the character array if not specified
if (size_t (-1) == len)
len = strlen (str);
// set the global pointer to point to the beginning of `str'
xinit_begin = str;
// save the previous pointer to the initializer function
int (*gen_save)() = X::_gen_;
// set the generating function
X::_gen_ = xinit;
X *array = 0;
_TRY {
// allocate and construct `len' elements, initializing
// each from the character array `str' (via `xinit')
array = new X [len];
}
_CATCH (...) {
// restore the original initializer function and rethrow
X::_gen_ = gen_save;
_RETHROW;
}
// restore the original initializer function
X::_gen_ = gen_save;
return array;
}
_TEST_EXPORT
/* static */ int
X::compare (const X *x, const char *str, size_t len /* = -1 */)
{
if (!str)
return x == 0;
if (size_t (-1) == len)
len = strlen (str);
for (size_t i = 0; i != len; ++i) {
const int val = UChar (str [i]);
if (val != x [i].val_)
return x [i].val_ - val;
}
return 0;
}
_TEST_EXPORT
/* static */ int
X::compare (const char *str, const X *x, size_t len /* = -1 */)
{
return -X::compare (x, str, len);
}
_TEST_EXPORT
/* static */ int
X::compare (const X *x, const X *y, size_t count)
{
for (size_t i = 0; i != count; ++i) {
if (x [i].val_ != y [i].val_)
return x [i].val_ - y [i].val_;
}
return 0;
}
/* static */ size_t UnaryPredicate::n_total_op_fcall_;
_TEST_EXPORT
UnaryPredicate::
UnaryPredicate ()
{
// no-op
}
_TEST_EXPORT
UnaryPredicate::
UnaryPredicate (const UnaryPredicate&)
{
// no-op
}
_TEST_EXPORT
UnaryPredicate& UnaryPredicate::
operator= (const UnaryPredicate&)
{
return *this;
}
_TEST_EXPORT
/* virtual */ UnaryPredicate::~UnaryPredicate ()
{
// no-op
}
_TEST_EXPORT
/* virtual */ bool UnaryPredicate::
operator()(const X&) const
{
++n_total_op_fcall_;
return true;
}
/* static */ size_t BinaryPredicate::n_total_op_fcall_;
_TEST_EXPORT
BinaryPredicate::
BinaryPredicate (bool ignore_case)
: ignore_case_ (ignore_case)
{
// no-op
}
BinaryPredicate::
BinaryPredicate (const BinaryPredicate &rhs)
: ignore_case_ (rhs.ignore_case_)
{
// no-op
}
_TEST_EXPORT BinaryPredicate& BinaryPredicate::
operator= (const BinaryPredicate &rhs)
{
ignore_case_ = rhs.ignore_case_;
return *this;
}
_TEST_EXPORT /* virtual */ BinaryPredicate::~BinaryPredicate ()
{
// no-op
}
_TEST_EXPORT /* virtual */ bool BinaryPredicate::
operator()(const X &lhs, const X &rhs) const
{
++n_total_op_fcall_;
if (lhs == rhs)
return true;
if (ignore_case_) {
const int lval = lhs.val_;
const int rval = rhs.val_;
if ( lval < 0 || lval > int (_RWSTD_UCHAR_MAX)
|| rval < 0 || rval > int (_RWSTD_UCHAR_MAX))
return false;
const int lup = toupper (lval);
const int rup = toupper (rval);
return _RWSTD_EOF != lup && lup == rup;
}
return false;
}
// generate a unique sequential number starting from 0
_TEST_EXPORT int gen_seq ()
{
static int val;
return ++val;
}
// generate numbers in the sequence 0, 0, 1, 1, 2, 2, 3, 3, etc...
_TEST_EXPORT int gen_seq_2lists ()
{
static int vals [2];
return vals [0] += ++vals [1] % 2;
}
// generate a sequence of subsequences (i.e., 0, 1, 2, 3, 4, 0, 1, 2, etc...)
_TEST_EXPORT int gen_subseq ()
{
static int val;
return val++ % 5;
}
// wrapper around a (possibly) extern "C" int rand()
// extern "C++"
_TEST_EXPORT int gen_rnd ()
{
return rand ();
}
//defination of fun
_TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_assign_()
{
return &X::_n_total_op_assign_;
}
_TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_eq_()
{
return &X::_n_total_op_eq_;
}
_TEST_EXPORT fptr_gen_* Get_gen_()
{
return &(X::_gen_) ;
}