// 
// This file is part of MolMeccano, a cross-platform C++ chemical library.
//
// Copyright (C) 2001-2007 Alexey Nikitin
//
#ifndef DBC_H
#define DBC_H

#ifndef TEXT_H
#include "Text.h"
#endif

#ifdef NDEBUG
#define REQUIRE
#else
#define REQUIRE( assertion, condition )  \
            require( assertion, condition, #condition, \
            __FILE__, __LINE__ )
#endif


#ifdef NDEBUG
#define ENSURE
#else
#define ENSURE( assertion, condition )  \
            ensure( assertion, condition, #condition, \
            __FILE__, __LINE__ )
#endif


#ifdef NDEBUG
#define CHECK
#else
#define CHECK( assertion, condition )  \
            check( assertion, condition, #condition, \
            __FILE__, __LINE__ )
#endif

#ifdef NDEBUG
#define INVARIANT
#else
#define INVARIANT  \
            examine_invariant( "Invariant ", invariant(), __FILE__, __LINE__ )
#endif

#ifdef NDEBUG
#define CONTRACT
#else
#define CONTRACT MM::DbC().
#endif

namespace MM
{

class DbC
{
public:
    virtual ~DbC() { }

    class Contract_violation
    {
    public:
        explicit Contract_violation( const Text & s) : message_(s) { }
        const Text & message() const { return message_; }

    private:
        Text  message_;
    };


    virtual bool invariant() const
    {
        return true;
    }

    void require(   const Text &  assertion,
                    bool          condition,
                    const Text &  condition_String,
                    const Text &  file,
                    int           line) const;

    void ensure(    const Text &  assertion,
                    bool          condition,
                    const Text &  condition_String,
                    const Text &  file,
                    int           line) const;

    void check(     const Text &  assertion,
                    bool          condition,
                    const Text &  condition_String,
                    const Text &  file,
                    int           line) const;

    void examine_invariant(   const Text &  type,
                    bool          condition,
                    const Text &  file,
                    int           line) const;

private:

    void examine(   const Text &  type,
                    const Text &  assertion,
                    bool          condition,
                    const Text &  condition_String,
                    const Text &  file,
                    int           line) const;
};

}//MM

#endif//DBC_H
