journal model (severity, source, value) OK (to complete)
This commit is contained in:
parent
d2ebb27a87
commit
8d510d84be
|
@ -37,6 +37,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <glib-2.0/glib.h>
|
#include <glib-2.0/glib.h>
|
||||||
#include <gtk-4.0/gtk/gtk.h>
|
#include <gtk-4.0/gtk/gtk.h>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
#include <gtk-4.0/gtk/gtk.h>
|
#include <gtk-4.0/gtk/gtk.h>
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -53,7 +54,7 @@ typedef struct disp_list {int value; struct disp_list *suiv;} disp_list ;
|
||||||
/* * * * * - J O U R N A L M E T A R U L E S - * * * *
|
/* * * * * - J O U R N A L M E T A R U L E S - * * * *
|
||||||
*
|
*
|
||||||
* Un seul fsm_journal_event() par fonction
|
* Un seul fsm_journal_event() par fonction
|
||||||
* sauf si elle génère plusieurs autres fonctions d'intérêt (à surveiller)
|
* ? sauf si cette fonction génère plusieurs autres fonctions d'intérêt ?
|
||||||
*
|
*
|
||||||
* S'il y a deux fsm_journal_event() (begin / end) dans une fonction
|
* S'il y a deux fsm_journal_event() (begin / end) dans une fonction
|
||||||
* ils doivent avoir la même étiquette : MESSAGE, SOURCE, TARGET
|
* ils doivent avoir la même étiquette : MESSAGE, SOURCE, TARGET
|
||||||
|
@ -65,7 +66,7 @@ enum severity {CRITICAL, ERROR, WARNING, INFO, MESSAGE, DEBUG, SPEW};
|
||||||
|
|
||||||
enum source {
|
enum source {
|
||||||
SOURCE, TARGET, JOURNAL, FSM, PREFER,
|
SOURCE, TARGET, JOURNAL, FSM, PREFER,
|
||||||
MAIN, APP, WIDGETS,
|
MAIN, APP, WIDGETS, SIGNAL,
|
||||||
MAIN_WINDOW, DIALOG_WINDOW, MODAL_WINDOW, TEXT_WINDOW, AUTO_NOTIFICATION,
|
MAIN_WINDOW, DIALOG_WINDOW, MODAL_WINDOW, TEXT_WINDOW, AUTO_NOTIFICATION,
|
||||||
TOPBAR, TOPBAR_LEFT, TOPBAR_RIGHT, TOPBAR_CENTER,
|
TOPBAR, TOPBAR_LEFT, TOPBAR_RIGHT, TOPBAR_CENTER,
|
||||||
SYNTH_PAGE, STATE_PAGE, RULES_PAGE, MEASURES_PAGE, RESULTS_PAGE,
|
SYNTH_PAGE, STATE_PAGE, RULES_PAGE, MEASURES_PAGE, RESULTS_PAGE,
|
||||||
|
@ -80,9 +81,7 @@ enum source {
|
||||||
SLIDER_A, SLIDER_B, SLIDER_C,
|
SLIDER_A, SLIDER_B, SLIDER_C,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum value {
|
enum value {VALUE}; // to use or not to use ... (plutôt non)
|
||||||
VALUE
|
|
||||||
};
|
|
||||||
|
|
||||||
#define JOURNAL_LOG_MAX_LENGTH 255
|
#define JOURNAL_LOG_MAX_LENGTH 255
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "../include/fsm.h"
|
#include "../include/fsm.h"
|
||||||
|
|
||||||
char *util_read_file (char *filename);
|
char *util_read_file (char *filename);
|
||||||
|
char *concat (const char *str, ...);
|
||||||
|
|
||||||
typedef struct pile {int value; struct pile *prev;} pile; // structure d'un élément
|
typedef struct pile {int value; struct pile *prev;} pile; // structure d'un élément
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "../../include/fsm.h"
|
#include "../../include/fsm.h"
|
||||||
|
#include "../../include/util.h"
|
||||||
#include "../../include/widget.h"
|
#include "../../include/widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,10 +62,10 @@ void fsm_journal_publication_request () {fsm_journal_publish (gg_logs);}
|
||||||
|
|
||||||
void fsm_journal_push (char *message, const char *string_value)
|
void fsm_journal_push (char *message, const char *string_value)
|
||||||
{
|
{
|
||||||
char to_print [JOURNAL_LOG_MAX_LENGTH] = "";
|
// Programmers using the strcat function can easily be recognized as lazy and reckless.
|
||||||
strcat (to_print, message);
|
// (quoted from: The GNU C Library (glibc) manual - 5.5 Concatenating Strings)
|
||||||
strcat (to_print, string_value);
|
|
||||||
fsm_journal_push_front (&gg_logs, message); // to_print); TODO concat strings
|
fsm_journal_push_front (&gg_logs, concat (message, " ", string_value, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL ERROR WARNING INFO MESSAGE DEBUG SPEW 😄️
|
// CRITICAL ERROR WARNING INFO MESSAGE DEBUG SPEW 😄️
|
||||||
|
@ -74,8 +75,21 @@ void fsm_journal_event (char *message, int severity, int source, const char *val
|
||||||
{
|
{
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
severity < SPEW
|
severity <= DEBUG
|
||||||
&& source == MAIN
|
&& source != TREE
|
||||||
|
/* && (
|
||||||
|
source == MAIN
|
||||||
|
|| source == FSM
|
||||||
|
|| source == TOPBAR
|
||||||
|
|| source == DIALOG_WINDOW
|
||||||
|
|| source == MODAL_WINDOW
|
||||||
|
|| source == TEXT_WINDOW
|
||||||
|
|| source == TOPBAR_LEFT
|
||||||
|
|| source == TOPBAR_RIGHT
|
||||||
|
|| source == PREFER
|
||||||
|
)
|
||||||
|
// && strcmp (value, "")
|
||||||
|
&& source != SIGNAL */
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm_journal_push (message, value); // TODO push (message + value)
|
fsm_journal_push (message, value); // TODO push (message + value)
|
||||||
|
@ -118,19 +132,11 @@ static int preferences_have_been_modified = FALSE;
|
||||||
|
|
||||||
void fsm_set_preferences_modified (bool value)
|
void fsm_set_preferences_modified (bool value)
|
||||||
{
|
{
|
||||||
char str1[140] = "fsm/dispatch preferences modified value = ";
|
char str1[] = "fsm/dispatch preferences modified: value = ";
|
||||||
char str2[20]; sprintf(str2, " (%d)\n", value); strcat(str1, str2);
|
char str2[] = "TRUE or FALSE (TODO)"; //sprintf(str2, "%d", value); TODO
|
||||||
fsm_journal_event (str1, INFO, FSM, "");
|
fsm_journal_event (str1, INFO, FSM, str2);
|
||||||
|
|
||||||
fsm_journal_event ("fsm/dispatch preferences modified value = ?",
|
|
||||||
INFO, FSM, "");
|
|
||||||
preferences_have_been_modified = value;
|
preferences_have_been_modified = value;
|
||||||
/*
|
|
||||||
if (value) fsm_journal_event (
|
|
||||||
"fsm/dispatch set preferences modified (TRUE)"); // TODO concat value
|
|
||||||
else fsm_journal_event (
|
|
||||||
"fsm/dispatch set preferences modified (FALSE)");
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fsm_get_preferences_state() {return preferences_have_been_modified;}
|
bool fsm_get_preferences_state() {return preferences_have_been_modified;}
|
||||||
|
@ -208,3 +214,4 @@ void fsm_msg (int choice, int value, char *string, int sub_automaton)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ void fsm_journal_seek (journal jj, long usec, char *message)
|
||||||
// https://en.cppreference.com/w/c/io/fprintf
|
// https://en.cppreference.com/w/c/io/fprintf
|
||||||
// https://nicolasj.developpez.com/articles/libc/string/
|
// https://nicolasj.developpez.com/articles/libc/string/
|
||||||
// https://thelinuxcode.com/pass-string-function-c-language/
|
// https://thelinuxcode.com/pass-string-function-c-language/
|
||||||
|
// https://mefics.org/fr/allocation-dynamique-de-m%C3%A9moire-en-c-fonctions-malloc-calloc/
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void fsm_journal_publish (journal jj)
|
void fsm_journal_publish (journal jj)
|
||||||
|
|
49
src/signal.c
49
src/signal.c
|
@ -36,8 +36,8 @@
|
||||||
|
|
||||||
static void on_auto_notification (char *message)
|
static void on_auto_notification (char *message)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal auto notification()",
|
// message = "-(any auto notification)-"; // test
|
||||||
DEBUG, AUTO_NOTIFICATION, message);
|
fsm_journal_event ("signal (notif.) ", DEBUG, AUTO_NOTIFICATION, message);
|
||||||
/* Ignored (2024-06-06) because I don't know how to get "main_window" easily
|
/* Ignored (2024-06-06) because I don't know how to get "main_window" easily
|
||||||
|
|
||||||
if (window->toast_revealer == NULL) {
|
if (window->toast_revealer == NULL) {
|
||||||
|
@ -103,7 +103,7 @@ void on_bind_user_tree_factory (GtkSignalListItemFactory *factory,
|
||||||
row);
|
row);
|
||||||
gtk_widget_set_margin_start (expander,
|
gtk_widget_set_margin_start (expander,
|
||||||
gtk_tree_list_row_get_depth(row) * 20);
|
gtk_tree_list_row_get_depth(row) * 20);
|
||||||
fsm_journal_event ("signal bind user tree factory()",
|
fsm_journal_event ("signal (tree) bind user tree factory()",
|
||||||
DEBUG, TREE, text);
|
DEBUG, TREE, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ void on_bind_user_tree_factory (GtkSignalListItemFactory *factory,
|
||||||
gboolean on_glarea_render (GtkGLArea *area,
|
gboolean on_glarea_render (GtkGLArea *area,
|
||||||
GdkGLContext *context)
|
GdkGLContext *context)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal glarea render()", DEBUG, GLAREA, "");
|
fsm_journal_event ("signal (GLArea) glarea render()", DEBUG, GLAREA, "(context TODO)");
|
||||||
// Check if the widget is a glarea
|
// Check if the widget is a glarea
|
||||||
if(gtk_gl_area_get_error(area) != NULL) {
|
if(gtk_gl_area_get_error(area) != NULL) {
|
||||||
on_auto_notification("An OpenGL error occured !");
|
on_auto_notification("An OpenGL error occured !");
|
||||||
|
@ -134,7 +134,7 @@ gboolean on_glarea_render (GtkGLArea *area,
|
||||||
/* We need to set up our state when we realize the GtkGLArea widget */
|
/* We need to set up our state when we realize the GtkGLArea widget */
|
||||||
void on_glarea_realize (GtkWidget *widget)
|
void on_glarea_realize (GtkWidget *widget)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal glarea realize()", DEBUG, GLAREA, "");
|
fsm_journal_event ("signal (GLArea) glarea realize()", DEBUG, GLAREA, "");
|
||||||
GError *internal_error = NULL;
|
GError *internal_error = NULL;
|
||||||
|
|
||||||
// Make the GL context current to be able to call the GL API
|
// Make the GL context current to be able to call the GL API
|
||||||
|
@ -160,7 +160,7 @@ void on_glarea_realize (GtkWidget *widget)
|
||||||
/* We should tear down the state when unrealizing */
|
/* We should tear down the state when unrealizing */
|
||||||
void on_glarea_unrealize (GtkWidget *widget)
|
void on_glarea_unrealize (GtkWidget *widget)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal glarea unrealize()", DEBUG, GLAREA, "");
|
fsm_journal_event ("signal (GLArea) glarea unrealize()", DEBUG, GLAREA, "");
|
||||||
GError *internal_error = NULL;
|
GError *internal_error = NULL;
|
||||||
|
|
||||||
// Make the GL context current to be able to call the GL API
|
// Make the GL context current to be able to call the GL API
|
||||||
|
@ -203,11 +203,11 @@ void on_axis_value_change (GtkAdjustment *adjustment, gpointer data)
|
||||||
|
|
||||||
char string_value [10]; sprintf(string_value, " (%d)", axis_value);
|
char string_value [10]; sprintf(string_value, " (%d)", axis_value);
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
case 0 : fsm_journal_event ("signal axis value changed()",
|
case 0 : fsm_journal_event ("signal (axis) X value changed()",
|
||||||
SPEW, SLIDER_X, string_value); break;
|
SPEW, SLIDER_X, string_value); break;
|
||||||
case 1 : fsm_journal_event ("signal axis value changed()",
|
case 1 : fsm_journal_event ("signal (axis) Y value changed()",
|
||||||
SPEW, SLIDER_Y, string_value); break;
|
SPEW, SLIDER_Y, string_value); break;
|
||||||
case 2 : fsm_journal_event ("signal axis value changed()",
|
case 2 : fsm_journal_event ("signal (axis) Z value changed()",
|
||||||
SPEW, SLIDER_Z, string_value); break;
|
SPEW, SLIDER_Z, string_value); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,21 +220,24 @@ void on_axis_value_change (GtkAdjustment *adjustment, gpointer data)
|
||||||
void on_save_current_model_before_editing (GtkWidget *btt_save_current_model,
|
void on_save_current_model_before_editing (GtkWidget *btt_save_current_model,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal save current model()", INFO, BUTTON, "");
|
fsm_journal_event ("signal (dialog) save current model()", INFO, BUTTON, "");
|
||||||
|
on_auto_notification ("save_current_model_before_editing !");
|
||||||
gtk_widget_set_sensitive (GTK_WIDGET (data), TRUE);
|
gtk_widget_set_sensitive (GTK_WIDGET (data), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_discard_current_model_before_editing (GtkWidget *btt_discard_current_model,
|
void on_discard_current_model_before_editing (GtkWidget *btt_discard_current_model,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal discard current model()", INFO, BUTTON, "");
|
fsm_journal_event ("signal (dialog) discard current model()", INFO, BUTTON, "");
|
||||||
|
on_auto_notification ("discard_current_model_before_editing ?");
|
||||||
gtk_window_close (GTK_WINDOW (data));
|
gtk_window_close (GTK_WINDOW (data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_write_current_model (GtkWidget *btt_write_current_model,
|
void on_write_current_model (GtkWidget *btt_write_current_model,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal write current model()", INFO, BUTTON, "");
|
fsm_journal_event ("signal (dialog) write current model()", INFO, BUTTON, "");
|
||||||
|
on_auto_notification ("writing current_model_before_editing 😄️");
|
||||||
gtk_window_close (GTK_WINDOW (data));
|
gtk_window_close (GTK_WINDOW (data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +253,7 @@ static void switch_state_rules_data();
|
||||||
|
|
||||||
void on_toggle_exec_edit (GtkWidget *toggled_button, gpointer user_data)
|
void on_toggle_exec_edit (GtkWidget *toggled_button, gpointer user_data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal toggle exec edit()", INFO, BUTTON, "");
|
fsm_journal_event ("signal (Xec/Ed) toggle exec edit()", INFO, BUTTON, "");
|
||||||
if (fsm_get_exec_edit ()) { // TODO (or NOT ?) et si je ne suis pas sur la page SYNTH
|
if (fsm_get_exec_edit ()) { // TODO (or NOT ?) et si je ne suis pas sur la page SYNTH
|
||||||
|
|
||||||
gtk_button_set_icon_name (GTK_BUTTON (toggled_button),
|
gtk_button_set_icon_name (GTK_BUTTON (toggled_button),
|
||||||
|
@ -281,8 +284,8 @@ void on_toggle_exec_edit (GtkWidget *toggled_button, gpointer user_data)
|
||||||
static void switch_state_rules_data()
|
static void switch_state_rules_data()
|
||||||
{
|
{
|
||||||
int value = fsm_get_state_rules_data();
|
int value = fsm_get_state_rules_data();
|
||||||
char string_value [12]; sprintf(string_value, " (%d)", value);
|
char string_value [12]; sprintf(string_value, "%d", value);
|
||||||
fsm_journal_event ("signal switch state rules data()",
|
fsm_journal_event ("signal (switch) value = ",
|
||||||
DEBUG, SWITCH_STATE_RULES_DATA, string_value);
|
DEBUG, SWITCH_STATE_RULES_DATA, string_value);
|
||||||
switch (value) {
|
switch (value) {
|
||||||
|
|
||||||
|
@ -327,7 +330,7 @@ static void switch_state_rules_data()
|
||||||
|
|
||||||
default :
|
default :
|
||||||
printf("default in signal.on_toggle_state_rule_data()\n");
|
printf("default in signal.on_toggle_state_rule_data()\n");
|
||||||
fsm_journal_event ("signal default in : switch state rules data()",
|
fsm_journal_event ("signal (switch) default in : switch state rules data()",
|
||||||
INFO, SWITCH_STATE_RULES_DATA, "");
|
INFO, SWITCH_STATE_RULES_DATA, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,10 +340,10 @@ static void switch_state_rules_data()
|
||||||
// Les noms d'icônes sont utilisés pour deux fonctions distinctes...
|
// Les noms d'icônes sont utilisés pour deux fonctions distinctes...
|
||||||
void on_toggle_state_rules_data (GtkWidget *toggled_button, gpointer user_data)
|
void on_toggle_state_rules_data (GtkWidget *toggled_button, gpointer user_data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal toggle state rules data()",
|
|
||||||
INFO, BUTTON, "state_rules_data");
|
|
||||||
const char *toggled_button_name
|
const char *toggled_button_name
|
||||||
= gtk_check_button_get_label (GTK_CHECK_BUTTON (toggled_button));
|
= gtk_check_button_get_label (GTK_CHECK_BUTTON (toggled_button));
|
||||||
|
fsm_journal_event ("signal (toggle) <-->",
|
||||||
|
INFO, BUTTON, toggled_button_name);
|
||||||
int is_active = gtk_check_button_get_active (GTK_CHECK_BUTTON (toggled_button));
|
int is_active = gtk_check_button_get_active (GTK_CHECK_BUTTON (toggled_button));
|
||||||
|
|
||||||
if ( ! strcmp (toggled_button_name, "synth")) fsm_set_state_rules_data (SYNTH);
|
if ( ! strcmp (toggled_button_name, "synth")) fsm_set_state_rules_data (SYNTH);
|
||||||
|
@ -357,7 +360,8 @@ void on_toggle_state_rules_data (GtkWidget *toggled_button, gpointer user_data)
|
||||||
|
|
||||||
void on_clicked_topbar_right_search (GtkWidget *btt_menu, gpointer list_box)
|
void on_clicked_topbar_right_search (GtkWidget *btt_menu, gpointer list_box)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal clicked topbar right search()",
|
fsm_journal_event ("signal (topbar R) search()",
|
||||||
|
// fsm_journal_event ("signal clicked topbar right search()",
|
||||||
DEBUG, BUTTON, "");
|
DEBUG, BUTTON, "");
|
||||||
// next line presents the text_window and works only once.\n
|
// next line presents the text_window and works only once.\n
|
||||||
// It should present a menu.\n"); // TODO
|
// It should present a menu.\n"); // TODO
|
||||||
|
@ -367,9 +371,10 @@ void on_clicked_topbar_right_search (GtkWidget *btt_menu, gpointer list_box)
|
||||||
|
|
||||||
void on_clicked_topbar_right_home (GtkWidget *btt_reset, gpointer data)
|
void on_clicked_topbar_right_home (GtkWidget *btt_reset, gpointer data)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal clicked topbar right home()",
|
fsm_journal_event ("signal (topbar R) home()",
|
||||||
|
// fsm_journal_event ("signal clicked topbar right home()",
|
||||||
DEBUG, BUTTON, "");
|
DEBUG, BUTTON, "");
|
||||||
// gtk_window_present (GTK_WINDOW (widget_get_dialog_window()));
|
gtk_window_present (GTK_WINDOW (widget_get_dialog_window()));
|
||||||
// NB works only once. < TODO
|
// NB works only once. < TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +412,7 @@ void on_resetting_XYZ_in_state_page ()
|
||||||
|
|
||||||
void on_situations_box_do_reset (GtkWidget *btt_reset, GtkScrollbar *reset_scrollbar)
|
void on_situations_box_do_reset (GtkWidget *btt_reset, GtkScrollbar *reset_scrollbar)
|
||||||
{
|
{
|
||||||
fsm_journal_event ("signal on_situations_box_do_reset()",
|
fsm_journal_event ("signal situations box do reset()",
|
||||||
DEBUG, BUTTON, "");
|
DEBUG, BUTTON, "");
|
||||||
GtkAdjustment *adj_situ = gtk_scrollbar_get_adjustment (reset_scrollbar);
|
GtkAdjustment *adj_situ = gtk_scrollbar_get_adjustment (reset_scrollbar);
|
||||||
fsm_reset_all_situations_transparencies_at_value (gtk_adjustment_get_value (adj_situ));
|
fsm_reset_all_situations_transparencies_at_value (gtk_adjustment_get_value (adj_situ));
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Gem-graph client *
|
||||||
|
* Main functions *
|
||||||
|
* *
|
||||||
|
* Copyright © 2021 Libre en Communs <contact@a-lec.org> *
|
||||||
|
* Copyright © 2021-2024 Adrien Bourmault <neox@a-lec.org> *
|
||||||
|
* Copyright © 2021-2024 Jean Sirmai <jean@a-lec.org> *
|
||||||
|
* *
|
||||||
|
* This file is part of Gem-graph. *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify it *
|
||||||
|
* under the terms of the GNU Affero General Public License *
|
||||||
|
* as published by the Free Software Foundation, *
|
||||||
|
* either version 3 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 Affero General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Affero General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
|
||||||
|
/* Programmers using the strcat function can easily be recognized as lazy and reckless.
|
||||||
|
* from The GNU C Library (glibc) manual (5.5 Concatenating Strings)
|
||||||
|
*
|
||||||
|
* Whenever a programmer feels the need to use strcat she or he should think twice
|
||||||
|
* and look through the program to see whether the code cannot be rewritten
|
||||||
|
* to take advantage of already calculated results.
|
||||||
|
* The related functions strlcat, strncat, wcscat and wcsncat are almost always unnecessary, too.
|
||||||
|
* Again: it is almost always unnecessary to use functions like strcat. 😄️ */
|
||||||
|
|
||||||
|
|
||||||
|
/* Before calling vprintf or the other functions listed in this section,
|
||||||
|
* you must call va_start (see Variadic Functions) to initialize a pointer to the variable arguments.
|
||||||
|
* Then you can call va_arg to fetch the arguments that you want to handle yourself.
|
||||||
|
* This advances the pointer past those arguments.
|
||||||
|
*
|
||||||
|
* Once your va_list pointer is pointing at the argument of your choice, you are ready to call vprintf.
|
||||||
|
* That argument and all subsequent arguments that were passed to your function
|
||||||
|
* are used by vprintf along with the template that you specified separately. */
|
||||||
|
|
||||||
|
/* A.2 Variadic Functions
|
||||||
|
* ISO C defines a syntax for declaring a function to take a variable number or type of arguments.
|
||||||
|
* (Such functions are referred to as varargs functions or variadic functions.)
|
||||||
|
* However, the language itself provides no mechanism for such functions to access
|
||||||
|
* their non-required arguments; instead, you use the variable arguments macros defined in stdarg.h.
|
||||||
|
*
|
||||||
|
* This section describes how to declare variadic functions, how to write them,
|
||||||
|
* and how to call them properly. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char * // https://sourceware.org/glibc/manual/latest/html_mono/libc.html#Variadic-Prototypes
|
||||||
|
concat (const char *str, ...) // ellipsis (‘…’) A.2.2.2 Receiving the Argument Values
|
||||||
|
{
|
||||||
|
size_t allocated = 100;
|
||||||
|
char *result = malloc (allocated);
|
||||||
|
|
||||||
|
if (result != NULL)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
size_t resultlen = 0;
|
||||||
|
char *newp;
|
||||||
|
|
||||||
|
va_start (ap, str);
|
||||||
|
|
||||||
|
for (const char *s = str; s != NULL; s = va_arg (ap, const char *))
|
||||||
|
{
|
||||||
|
size_t len = strlen (s);
|
||||||
|
|
||||||
|
/* Resize the allocated memory if necessary. */
|
||||||
|
if (resultlen + len + 1 > allocated)
|
||||||
|
{
|
||||||
|
allocated += len;
|
||||||
|
newp = reallocarray (result, allocated, 2);
|
||||||
|
allocated *= 2;
|
||||||
|
if (newp == NULL)
|
||||||
|
{
|
||||||
|
free (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = newp;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (result + resultlen, s, len);
|
||||||
|
resultlen += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate the result string. */
|
||||||
|
result[resultlen++] = '\0';
|
||||||
|
|
||||||
|
/* Resize memory to the optimal size. */
|
||||||
|
newp = realloc (result, resultlen);
|
||||||
|
if (newp != NULL)
|
||||||
|
result = newp;
|
||||||
|
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -31,26 +31,14 @@
|
||||||
#include "../../include/util.h"
|
#include "../../include/util.h"
|
||||||
#include "../../include/base.h"
|
#include "../../include/base.h"
|
||||||
|
|
||||||
static const char *util_str_concat_test (char *a, char *b, int len_a, int len_b) {
|
|
||||||
char *c = malloc (len_a + len_b + 2); // char c[255]; *c = 'K'; c[1] = 'O'; *(c+1) = 'U'; c[2] = '\0'; a[len_a] = '\0'; b[len_b] = '\0';
|
|
||||||
strcpy(c, a);
|
|
||||||
strcpy(c + len_a + 1, b);
|
|
||||||
c[2] = '9'; c[3] = '9';
|
|
||||||
*(c + len_a + len_b) = '\0';
|
|
||||||
// printf ("static void current concat test (%s%s) > %s\n", a, b, c);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void util_trigger_test ()
|
void util_trigger_test ()
|
||||||
{
|
{
|
||||||
if (0) util_pile_test();
|
if (0) util_pile_test();
|
||||||
if (0) util_double_list_test();
|
if (0) util_double_list_test();
|
||||||
if (0) util_sorted_list_test();
|
if (0) util_sorted_list_test();
|
||||||
//int len_a = 11, len_b = 14;
|
|
||||||
char aaa [] = "Hello World", bbb [] = ", what's new ?";
|
char aaa [] = "Hello World", bbb [] = ", what's new ?";
|
||||||
char *c = strcat (aaa, bbb); //c[11 + 14] = '\0';
|
if (0) printf("concat ([%s], [%s], NULL) --> '%s'\n",
|
||||||
if (1) printf("%s <--- strcat () (would 'like to use: strncat() instead...)\n", c);
|
aaa, bbb, concat (aaa, bbb, NULL));
|
||||||
if (1) printf("%s <--- util_str_concat_test()\n", util_str_concat_test(aaa, bbb, 11, 14));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void util_pile_test()
|
void util_pile_test()
|
||||||
|
|
Loading…
Reference in New Issue