/* -*- mode: c++; c-basic-offset:4 -*-
    utils/kleo_assert.h

    This file is part of Kleopatra, the KDE keymanager
    SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#ifndef __KLEOPATRA_UTILS_KLEO_ASSERT_H__
#define __KLEOPATRA_UTILS_KLEO_ASSERT_H__

#include <Libkleo/Exception>

#include <assert.h>

#define S(x) #x
#define S_(x) S(x)
#define S_LINE S_(__LINE__)

#define kleo_assert_fail_impl( cond, file, line )                       \
    throw Kleo::Exception( gpg_error( GPG_ERR_INTERNAL ),               \
                           "assertion \"" #cond "\" failed at " file ":" line )
#define kleo_assert_fail_impl_func( cond, file, line, func )            \
    throw Kleo::Exception( gpg_error( GPG_ERR_INTERNAL ),               \
                           std::string( "assertion \"" #cond "\" failed in " ) + func + " (" file ":" line ")" )

#define kleo_assert_impl( cond, file, line )                  \
    if ( cond ) {}                                            \
    else kleo_assert_fail_impl( cond, file, line )
#define kleo_assert_impl_func( cond, file, line, func )       \
    if ( cond ) {}                                            \
    else kleo_assert_fail_impl_func( cond, file, line, func )

// from glibc's assert.h:
/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
   which contains the name of the function currently being defined.
   This is broken in G++ before version 2.6.
   C9x has a similar variable called __func__, but prefer the GCC one since
   it demangles C++ function names.  */

#if defined (__GNUC_PREREQ)
# define KLEO_GNUC_PREREQ __GNUC_PREREQ
#elif defined (__MINGW_GNUC_PREREQ)
# define KLEO_GNUC_PREREQ __MINGW_GNUC_PREREQ
#else
# define KLEO_GNUC_PREREQ(maj, min) 0
#endif

#if KLEO_GNUC_PREREQ(2, 6)
# define kleo_assert( cond ) kleo_assert_impl_func( cond, __FILE__, S_LINE, __PRETTY_FUNCTION__ )
# define kleo_assert_fail( cond ) kleo_assert_fail_impl_func( cond, __FILE__, S_LINE, __PRETTY_FUNCTION__ )
# define notImplemented() throw Exception( gpg_error( GPG_ERR_NOT_IMPLEMENTED ), __PRETTY_FUNCTION__ )
#elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
# define kleo_assert( cond ) kleo_assert_impl_func( cond, __FILE__, S_LINE, __func__ )
# define kleo_assert_fail( cond ) kleo_assert_fail_impl_func( cond, __FILE__, S_LINE, __func__ )
# define notImplemented() throw Exception( gpg_error( GPG_ERR_NOT_IMPLEMENTED ), __func__ )
#endif

#undef KLEO_GNUC_PREREQ

#ifndef kleo_assert
# define kleo_assert( cond ) kleo_assert_impl( cond, __FILE__, S_LINE )
#endif

#ifndef kleo_assert_fail
# define kleo_assert_fail( cond ) kleo_assert_fail_impl( cond, __FILE__, S_LINE )
#endif

#ifndef notImplemented
# define notImplemented() kleo_assert( !"Sorry, not yet implemented" )
#endif

#endif /* __KLEOPATRA_UTILS_KLEO_ASSERT_H__ */
