/*
 *  $Id: macros.c 28502 2025-09-04 16:57:58Z yeti-dn $
 *  Copyright (C) 2003-2024 David Necas (Yeti), Petr Klapetek.
 *  E-mail: yeti@gwyddion.net, klapetek@gwyddion.net.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
 *  later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include <glib.h>

#include "libgwyddion/macros.h"

static gpointer
ensure_debug_timer(G_GNUC_UNUSED gpointer arg)
{
    return g_timer_new();
}

/**
 * gwy_debug_gnu:
 * @domain: Log domain.
 * @fileline: File and line info.
 * @funcname: Function name.
 * @format: Message format.
 * @...: Message parameters.
 *
 * Print a debugging message.
 *
 * To be used via gwy_debug(), should not be used directly.
 **/
void
gwy_debug_gnu(const gchar *domain,
              const gchar *fileline,
              const gchar *funcname,
              const gchar *format,
              ...)
{
    static GOnce debug_timer_once = G_ONCE_INIT;
    gchar *fmt2;
    va_list args;
    gchar tbuf[24];
    GTimer *timer;

    timer = (GTimer*)g_once(&debug_timer_once, ensure_debug_timer, NULL);
    va_start(args, format);
    g_snprintf(tbuf, sizeof(tbuf), "%.6f", g_timer_elapsed(timer, NULL));
    fmt2 = g_strconcat(fileline, ": ", funcname, ": (", tbuf, ") ", format, NULL);
    g_logv(domain, G_LOG_LEVEL_DEBUG, fmt2, args);
    va_end(args);
    g_free(fmt2);
}

/**
 * SECTION: macros
 * @title: Macros
 * @short_description: General utility macros
 * @see_also: <link linkend="libgwyddion-utils">utils</link> -- utility functions
 **/

/**
 * GWY_SWAP:
 * @t: A C type.
 * @x: A variable of type @t to swap with @x.
 * @y: A variable of type @t to swap with @y.
 *
 * Swaps two variables (more precisely lhs and rhs expressions) of type @t in a single statement.
 *
 * Both @x and @y are evaluated multiple times as both lhs and rhs expressions. If their evaluation has any side
 * effect the result is undefined.
 */

/**
 * GWY_ORDER:
 * @t: A C type.
 * @x: A variable of type @t to possibly swap with @x.
 * @y: A variable of type @t to possibly swap with @y.
 *
 * Ensures ascending order of two variables (more precisely lhs and rhs expressions) of type @t in a single statement.
 *
 * The macro makes @y not smaller than @x. They may be still equal or their relation can be undefined (if either is
 * NaN).
 *
 * Both @x and @y are evaluated multiple times as both lhs and rhs expressions. If their evaluation has any side
 * effect the result is undefined.
 */

/**
 * GWY_CLAMP:
 * @x: The value to clamp.
 * @low: The minimum value allowed.
 * @hi: The maximum value allowed.
 *
 * Ensures that @x is between the limits set by @low and @hi.
 *
 * This macro differs from GLib's CLAMP() by G_UNLIKELY() assertions on the tests that @x is smaller than @low and
 * larger than @hi.  This makes @x already being in the right range the fast code path.
 *
 * It is supposed to be used on results of floating-point operations that should fall to a known range but may
 * occasionaly fail to due to rounding errors and in similar situations.  Under normal circumstances, use CLAMP().
 **/

/**
 * gwy_clear:
 * @array: Pointer to an array of values to clear.
 * @n: Number of items to clear.
 *
 * Fills a memory block representing an array with zeroes.
 *
 * This is a shorthand for memset(), with the number of bytes to fill calculated from the type of the pointer.
 * See gwy_clear1() for a more convenient macro for clearing a single variable.
 **/

/**
 * gwy_clear1:
 * @var: A variable name (or other l-value expression). The argument is the variable itself, not a pointer to it.
 *
 * Fills the memory occupied by a single variable with zeroes.
 *
 * This is a shorthand for memset(), with the number of bytes to fill calculated from the type of the variable.
 * See gwy_clear() for clearing arrays and/or passing the address already as a pointer.
 **/

/**
 * gwy_assign:
 * @dest: Pointer to the destination array of values. This argument may be evaluated several times.
 * @source: Pointer to the source array of values.
 * @n: Number of items to copy.
 *
 * Copies items from one memory block representing an array to another.
 *
 * This is a shorthand for memcpy(), with the number of bytes to fill calculated from the type of the @dest pointer
 * (the type of @source does not enter the calculation!)
 *
 * As with memcpy(), the memory blocks may not overlap.
 **/

/**
 * GWY_FREE_SI_VALUE_FORMAT:
 * @vf: A value format to free or %NULL.
 *
 * Frees and nulls a value format if it exists.
 *
 * If @vf is not %NULL, gwy_value_format_free() is called on it and %NULL is assigned to the variable.  In all
 * cases @vf will be %NULL at the end.
 *
 * A useful property of this macro is its idempotence.
 **/

/**
 * GWY_FREE:
 * @ptr: A pointer to free or %NULL.
 *
 * Frees and nulls a pointer if it exists.
 *
 * The memory must have been allocated using one of the g_new() and g_malloc() class of functions.
 *
 * If @ptr is not %NULL, g_free() is called on it and %NULL is assigned to the variable.  In all cases @ptr will be
 * %NULL at the end.
 *
 * A useful property of this macro is its idempotence.
 **/

/**
 * GWY_FREE_STRING:
 * @str: A #GString pointer to free or %NULL.
 *
 * Frees and nulls a pointer to a GString if it exists.
 *
 * The array memory must have been allocated using g_string_new() or a similar function.
 *
 * If @ptr is not %NULL, g_string_free() is called on it, freeing also string data, and %NULL is assigned to the
 * variable.  In all cases @ptr will be %NULL at the end.
 *
 * A useful property of this macro is its idempotence.
 **/

/**
 * GWY_FREE_ARRAY:
 * @arr: A #GArray pointer to free or %NULL.
 *
 * Frees and nulls a pointer to a GArray if it exists.
 *
 * The array memory must have been allocated using g_array_new() or a similar function.
 *
 * If @ptr is not %NULL, g_array_free() is called on it, freeing also array data, and %NULL is assigned to the
 * variable.  In all cases @ptr will be %NULL at the end.
 *
 * A useful property of this macro is its idempotence.
 **/

/**
 * gwy_debug:
 * @...: Format string, as in printf(), followed by arguments.
 *
 * Emits a debugging message to the program log.
 *
 * The message is amended with additional information such as source file, line number or time (when possible) and
 * emitted at log level %G_LOG_LEVEL_DEBUG via g_log().
 *
 * It should be noted that the default GLib log handler discards %G_LOG_LEVEL_DEBUG messages but the default Gwyddion
 * handler does not.
 *
 * The macro expands to nothing if compiled without DEBUG defined.
 **/

/**
 * gwy_info:
 * @...: Format string, as in printf(), followed by arguments.
 *
 * Emits an informational message.
 *
 * The message is emitted at log level %G_LOG_LEVEL_INFO via g_log().  This macro is primarily meant for reporting of
 * non-fatal issues in file import modules.
 *
 * It should be noted that the default GLib log handler discards %G_LOG_LEVEL_INFO messages but the default Gwyddion
 * handler does not.
 **/

/**
 * GWY_GPARAM_RWE:
 *
 * Standard property flags (read, write, static strings and explicitit notify).
 *
 * Most object properties have the same standard #GParamSpecFlags: %G_PARAM_READWRITE, %G_PARAM_STATIC_STRINGS and
 * %G_PARAM_EXPLICIT_NOTIFY (some of them being combinations of multiple flags themselves). This macro can be used to
 * write them in a concise manner.
 **/

/**
 * gwy_NC:
 * @context: Translation context.
 * @string: Translatable message.
 *
 * Form a source code prefixed translatable message.
 *
 * The macro expands to @context and @string joined by <literal>"\004"</literal>. It is similar to the standard NC_()
 * macro, but it is also very different because NC_() drops the context. The actual translation functions expect you
 * to provide it again. This macro creates a string which carries the context and can be used with a function such
 * as gwy_sgettext() or macro gwy_C().
 **/

/**
 * gwy_C:
 * @string: Translatable message.
 *
 * Translate a prefixed translatable message in the default domain.
 *
 * The macro expands to gwy_sgettext() with the first argument set to GETTEXT_DOMAIN. It thus relies on GETTEXT_DOMAIN
 * being correctly defined where the macro is used. See gwy_sgettext() documentation for a discussion where this can
 * be a useful function and where you should stick to the standard C_() macro.
 **/

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
