LCOV - code coverage report
Current view: top level - main/source - main_commands.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.5_covts Lines: 0.0 % 202 0
Test Date: 2026-05-28 21:31:40 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /* File: main_commands.c; Copyright and License: see below */
       2              : 
       3              : #include "main_commands.h"
       4              : #include "gui_main.h"
       5              : #include "gui_error_info_printer.h"
       6              : #include "io_exporter.h"
       7              : #include "io_importer.h"
       8              : #include "ctrl_controller.h"
       9              : #include "u8/u8_trace.h"
      10              : #include "u8/u8_log.h"
      11              : #include <gtk/gtk.h>
      12              : #include <stdbool.h>
      13              : #include <assert.h>
      14              : 
      15              : static io_data_file_t single_big_data_file;  /*!< a data_file struct, placed in the data segment due to its >5MB size */
      16              : 
      17            0 : u8_error_t main_commands_init ( main_commands_t *this_, bool start_gui, int argc, char **argv )
      18              : {
      19            0 :     U8_TRACE_BEGIN();
      20            0 :     u8_error_t result = U8_ERROR_NONE;
      21              : 
      22            0 :     (*this_).argc = argc;
      23            0 :     (*this_).argv = argv;
      24              : 
      25              :     /* initialize the base libraries: gobject, gio, glib, gdk and gtk */
      26            0 :     if ( start_gui )
      27              :     {
      28            0 :         gtk_init();
      29              :         /* if this program was not terminated, gtk init was successful. */
      30              :     }
      31              :     else
      32              :     {
      33            0 :         const gboolean success = gtk_init_check();
      34            0 :         if ( ! success )
      35              :         {
      36            0 :             U8_LOG_WARNING("gtk could not be initialized.");
      37              :             /* no error here, if no gui requested - test fail otherwise */
      38              :         }
      39              :     }
      40              : 
      41            0 :     U8_TRACE_INFO("starting DB and its controller...");
      42            0 :     U8_TRACE_INFO_INT("sizeof(io_data_file_t)/B:",sizeof(io_data_file_t));
      43            0 :     (*this_).data_file = &single_big_data_file;
      44            0 :     io_data_file_init( (*this_).data_file );
      45              : 
      46            0 :     U8_TRACE_END_ERR( result );
      47            0 :     return result;
      48              : }
      49              : 
      50            0 : void main_commands_destroy ( main_commands_t *this_ )
      51              : {
      52            0 :     U8_TRACE_BEGIN();
      53              : 
      54            0 :     U8_TRACE_INFO("stopping DB and its controller...");
      55            0 :     io_data_file_destroy( (*this_).data_file );
      56              : 
      57            0 :     U8_TRACE_END();
      58            0 : }
      59              : 
      60            0 : u8_error_t main_commands_repair ( main_commands_t *this_,
      61              :                                   const char *data_file_path,
      62              :                                   bool check_only,
      63              :                                   utf8stream_writer_t *out_english_report )
      64              : {
      65            0 :     U8_TRACE_BEGIN();
      66            0 :     assert( data_file_path != NULL );
      67            0 :     const bool do_repair = ( ! check_only );
      68            0 :     u8_error_t result = U8_ERROR_NONE;
      69              : 
      70            0 :     U8_TRACE_INFO("opening DB...");
      71              :     u8_error_info_t err_info;
      72              :     data_stat_t stat;
      73            0 :     data_stat_init( &stat );
      74            0 :     result |= io_data_file_open( (*this_).data_file, data_file_path, check_only, &stat, &err_info );
      75            0 :     data_stat_trace( &stat );
      76            0 :     data_stat_destroy( &stat );
      77            0 :     if ( result != U8_ERROR_NONE )
      78              :     {
      79            0 :         result |= main_commands_private_report_error_on_open( this_, result, data_file_path, out_english_report );
      80              :     }
      81            0 :     result |= main_commands_private_report_error_info( this_, &err_info, out_english_report );
      82              : 
      83            0 :     U8_TRACE_INFO("reparing/testing...");
      84            0 :     utf8stream_writer_write_str( out_english_report, "\n\n" );
      85            0 :     result |= ctrl_controller_repair_database( io_data_file_get_controller_ptr( (*this_).data_file ),
      86              :                                                do_repair,
      87              :                                                NULL,
      88              :                                                NULL,
      89              :                                                out_english_report
      90              :                                              );
      91            0 :     utf8stream_writer_write_str( out_english_report, "\n" );
      92            0 :     U8_TRACE_INFO("reparing/testing finished.");
      93              : 
      94            0 :     U8_TRACE_INFO("closing DB...");
      95            0 :     io_data_file_close( (*this_).data_file );
      96              : 
      97            0 :     U8_TRACE_END_ERR( result );
      98            0 :     return result;
      99              : }
     100              : 
     101            0 : u8_error_t main_commands_start_gui ( main_commands_t *this_,
     102              :                                      const char *data_file_path,
     103              :                                      utf8stream_writer_t *out_english_report )
     104              : {
     105            0 :     U8_TRACE_BEGIN();
     106            0 :     u8_error_t result = U8_ERROR_NONE;
     107              : 
     108            0 :     U8_TRACE_TIMESTAMP();
     109            0 :     U8_TRACE_INFO("opening DB...");
     110            0 :     if ( NULL != data_file_path )
     111              :     {
     112              :         u8_error_info_t err_info;
     113              :         data_stat_t stat;
     114            0 :         data_stat_init( &stat );
     115            0 :         result |= io_data_file_open_writeable( (*this_).data_file, data_file_path, &stat, &err_info );
     116            0 :         data_stat_trace( &stat );
     117            0 :         data_stat_destroy( &stat );
     118            0 :         if ( result != U8_ERROR_NONE )
     119              :         {
     120            0 :             result |= main_commands_private_report_error_on_open( this_, result, data_file_path, out_english_report );
     121              :         }
     122            0 :         result |= main_commands_private_report_error_info( this_, &err_info, out_english_report );
     123              :     }
     124              : 
     125            0 :     U8_TRACE_TIMESTAMP();
     126            0 :     U8_TRACE_INFO("running GUI...");
     127            0 :     gui_main( (*this_).data_file, (*this_).argc, (*this_).argv );
     128            0 :     U8_TRACE_INFO("GUI stopped.");
     129              : 
     130            0 :     U8_TRACE_TIMESTAMP();
     131            0 :     U8_TRACE_INFO("closing DB...");
     132            0 :     io_data_file_close( (*this_).data_file );
     133              : 
     134            0 :     U8_TRACE_END_ERR( result );
     135            0 :     return result;
     136              : }
     137              : 
     138            0 : u8_error_t main_commands_export ( main_commands_t *this_,
     139              :                                   const char *data_file_path,
     140              :                                   io_file_format_t export_format,
     141              :                                   const char *export_directory,
     142              :                                   utf8stream_writer_t *out_english_report )
     143              : {
     144            0 :     U8_TRACE_BEGIN();
     145            0 :     assert( data_file_path != NULL );
     146            0 :     assert( export_directory != NULL );
     147            0 :     u8_error_t export_err = U8_ERROR_NONE;
     148              : 
     149            0 :     U8_TRACE_INFO("opening DB...");
     150              :     u8_error_info_t err_info;
     151              :     data_stat_t stat;
     152            0 :     data_stat_init( &stat );
     153            0 :     export_err |= io_data_file_open_read_only( (*this_).data_file, data_file_path, &stat, &err_info );
     154            0 :     data_stat_trace( &stat );
     155            0 :     data_stat_destroy( &stat );
     156            0 :     if ( export_err != U8_ERROR_NONE )
     157              :     {
     158            0 :         export_err |= main_commands_private_report_error_on_open( this_, export_err, data_file_path, out_english_report );
     159              :     }
     160            0 :     export_err |= main_commands_private_report_error_info( this_, &err_info, out_english_report );
     161              : 
     162            0 :     U8_TRACE_INFO("exporting DB...");
     163            0 :     U8_TRACE_INFO_STR( "chosen folder:", export_directory );
     164            0 :     const char *document_filename = io_data_file_get_filename_const( (*this_).data_file );
     165            0 :     if ( io_data_file_is_open( (*this_).data_file ) )
     166              :     {
     167              :         static data_database_reader_t db_reader;
     168            0 :         data_database_reader_init( &db_reader, io_data_file_get_database_ptr( (*this_).data_file ) );
     169              :         static io_exporter_t exporter;
     170            0 :         io_exporter_init( &exporter, &db_reader );
     171              :         {
     172              :             data_stat_t export_stat;
     173            0 :             data_stat_init ( &export_stat );
     174            0 :             export_err = io_exporter_export_files( &exporter, export_format, export_directory, document_filename, &export_stat );
     175            0 :             export_err |= main_commands_private_report_stat( this_, &export_stat, "exported", out_english_report );
     176            0 :             data_stat_trace( &export_stat );
     177            0 :             data_stat_destroy ( &export_stat );
     178              :         }
     179            0 :         io_exporter_destroy( &exporter );
     180            0 :         data_database_reader_destroy( &db_reader );
     181              :     }
     182              :     else
     183              :     {
     184            0 :         export_err = U8_ERROR_NO_DB;
     185              :     }
     186              : 
     187            0 :     U8_TRACE_INFO("closing DB...");
     188            0 :     io_data_file_close( (*this_).data_file );
     189              : 
     190            0 :     U8_TRACE_END_ERR( export_err );
     191            0 :     return export_err;
     192              : }
     193              : 
     194            0 : u8_error_t main_commands_import ( main_commands_t *this_,
     195              :                                   const char *data_file_path,
     196              :                                   io_import_mode_t import_mode,
     197              :                                   const char *import_file_path,
     198              :                                   utf8stream_writer_t *out_english_report )
     199              : {
     200            0 :     U8_TRACE_BEGIN();
     201            0 :     assert( data_file_path != NULL );
     202            0 :     assert( import_file_path != NULL );
     203            0 :     u8_error_t import_err = U8_ERROR_NONE;
     204              : 
     205            0 :     U8_TRACE_INFO("opening DB...");
     206              :     u8_error_info_t err_info;
     207              :     data_stat_t stat;
     208            0 :     data_stat_init( &stat );
     209            0 :     import_err |= io_data_file_open_writeable( (*this_).data_file, data_file_path, &stat, &err_info );
     210            0 :     data_stat_trace( &stat );
     211            0 :     data_stat_destroy( &stat );
     212            0 :     if ( import_err != U8_ERROR_NONE )
     213              :     {
     214            0 :         import_err |= main_commands_private_report_error_on_open( this_, import_err, data_file_path, out_english_report );
     215              :     }
     216            0 :     import_err |= main_commands_private_report_error_info( this_, &err_info, out_english_report );
     217              : 
     218            0 :     U8_TRACE_INFO("importing data...");
     219            0 :     U8_TRACE_INFO_STR( "chosen data:", import_file_path );
     220            0 :     if ( io_data_file_is_open( (*this_).data_file ) )
     221              :     {
     222              :         static data_database_reader_t db_reader;
     223            0 :         data_database_reader_init( &db_reader, io_data_file_get_database_ptr( (*this_).data_file ) );
     224              :         static io_importer_t importer;
     225            0 :         io_importer_init( &importer, &db_reader, io_data_file_get_controller_ptr( (*this_).data_file ));
     226              :         {
     227              :             data_stat_t import_stat;
     228            0 :             data_stat_init ( &import_stat );
     229              :             u8_error_info_t err_info;
     230            0 :             import_err = io_importer_import_file( &importer, import_mode, import_file_path, &import_stat, &err_info, out_english_report );
     231            0 :             import_err |= main_commands_private_report_stat( this_, &import_stat, "imported", out_english_report );
     232            0 :             import_err |= main_commands_private_report_error_info( this_, &err_info, out_english_report );
     233            0 :             data_stat_trace( &import_stat );
     234            0 :             data_stat_destroy ( &import_stat );
     235              :         }
     236            0 :         io_importer_destroy( &importer );
     237            0 :         data_database_reader_destroy( &db_reader );
     238              :     }
     239              :     else
     240              :     {
     241            0 :         import_err = U8_ERROR_NO_DB;
     242              :     }
     243              : 
     244            0 :     U8_TRACE_INFO("closing DB...");
     245            0 :     io_data_file_close( (*this_).data_file );
     246              : 
     247              :     {
     248            0 :         utf8stream_writer_write_str( out_english_report, "\nplease test the integrity of the database_file:\n" );
     249            0 :         utf8stream_writer_write_str( out_english_report, "crystal-facet-uml -t " );
     250            0 :         utf8stream_writer_write_str( out_english_report, data_file_path );
     251            0 :         utf8stream_writer_write_str( out_english_report, "\n\n" );
     252              :     }
     253              : 
     254            0 :     U8_TRACE_END_ERR( import_err );
     255            0 :     return import_err;
     256              : }
     257              : 
     258              : static const char *const series[DATA_STAT_SERIES_MAX] = {
     259              :     [DATA_STAT_SERIES_CREATED]  = " new/exp",
     260              :     [DATA_STAT_SERIES_MODIFIED] = "modified",
     261              :     [DATA_STAT_SERIES_DELETED]  = " deleted",
     262              :     [DATA_STAT_SERIES_IGNORED]  = " ignored",
     263              :     [DATA_STAT_SERIES_WARNING]  = "warnings",
     264              :     [DATA_STAT_SERIES_ERROR]    = "  errors",
     265              : };
     266              : 
     267              : static const char *const tables[DATA_STAT_TABLE_MAX] = {
     268              :     [DATA_TABLE_VOID] = "life",
     269              :     [DATA_TABLE_CLASSIFIER] = "clas",
     270              :     [DATA_TABLE_FEATURE] = "feat",
     271              :     [DATA_TABLE_RELATIONSHIP] = "rel",
     272              :     [DATA_TABLE_DIAGRAMELEMENT] = "d_ele",
     273              :     [DATA_TABLE_DIAGRAM] = "diag",
     274              : };
     275              : 
     276            0 : u8_error_t main_commands_private_report_stat ( main_commands_t *this_,
     277              :                                                const data_stat_t *stat,
     278              :                                                const char* mode_name,
     279              :                                                utf8stream_writer_t *out_english_report )
     280              : {
     281            0 :     U8_TRACE_BEGIN();
     282            0 :     assert( stat != NULL );
     283            0 :     assert( mode_name != NULL );
     284            0 :     assert( out_english_report != NULL );
     285            0 :     u8_error_t write_err = U8_ERROR_NONE;
     286              : 
     287              :     /* HEADLINE */
     288            0 :     write_err |= utf8stream_writer_write_str( out_english_report, "\n\t" );
     289              : 
     290            0 :     for ( int tables_idx = 0; tables_idx < DATA_STAT_TABLE_MAX; tables_idx ++ )
     291              :     {
     292            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\t" );
     293            0 :         write_err |= utf8stream_writer_write_str( out_english_report, tables[tables_idx] );
     294              :     }
     295            0 :     write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     296              : 
     297              :     /* TABLE */
     298            0 :     for ( int series_idx = 0; series_idx < DATA_STAT_SERIES_MAX; series_idx ++ )
     299              :     {
     300            0 :         const uint_fast32_t s_cnt = data_stat_get_series_count( stat, series_idx );
     301              : 
     302            0 :         if ( series_idx == DATA_STAT_SERIES_CREATED )
     303              :         {
     304            0 :             write_err |= utf8stream_writer_write_str( out_english_report, mode_name );
     305              :         }
     306              :         else
     307              :         {
     308            0 :             write_err |= utf8stream_writer_write_str( out_english_report, series[series_idx] );
     309              :         }
     310            0 :         write_err |= utf8stream_writer_write_str( out_english_report, ": " );
     311              : 
     312            0 :         for ( int tables_idx = 0; tables_idx < DATA_STAT_TABLE_MAX; tables_idx ++ )
     313              :         {
     314            0 :             write_err |= utf8stream_writer_write_str( out_english_report, "\t" );
     315            0 :             const uint_fast32_t cnt = data_stat_get_count( stat, tables_idx, series_idx );
     316            0 :             if ( cnt != 0 )
     317              :             {
     318            0 :                 write_err |= utf8stream_writer_write_int( out_english_report, cnt );
     319              :             }
     320              :         }
     321              : 
     322            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\t: " );
     323            0 :         write_err |= utf8stream_writer_write_int( out_english_report, s_cnt );
     324            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     325              :     }
     326              : 
     327              :     /* ROW OF SUMS */
     328            0 :     write_err |= utf8stream_writer_write_str( out_english_report, "     SUM:" );
     329            0 :     for ( int tables_idx = 0; tables_idx < DATA_STAT_TABLE_MAX; tables_idx ++ )
     330              :     {
     331            0 :         const uint_fast32_t t_cnt = data_stat_get_table_count( stat, tables_idx );
     332            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\t" );
     333            0 :         write_err |= utf8stream_writer_write_int( out_english_report, t_cnt );
     334              :     }
     335            0 :     const uint_fast32_t total = data_stat_get_total_count( stat );
     336            0 :     write_err |= utf8stream_writer_write_str( out_english_report, "\t: " );
     337            0 :     write_err |= utf8stream_writer_write_int( out_english_report, total );
     338            0 :     write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     339              : 
     340            0 :     U8_TRACE_END_ERR( write_err );
     341            0 :     return write_err;
     342              : }
     343              : 
     344            0 : u8_error_t main_commands_private_report_error_on_open ( main_commands_t *this_,
     345              :                                                         const u8_error_t error,
     346              :                                                         const char* file_name,
     347              :                                                         utf8stream_writer_t *out_english_report )
     348              : {
     349            0 :     U8_TRACE_BEGIN();
     350            0 :     assert( file_name != NULL );
     351            0 :     assert( out_english_report != NULL );
     352            0 :     u8_error_t write_err = U8_ERROR_NONE;
     353              : 
     354            0 :     if ( U8_ERROR_NO_DB == error )
     355              :     {
     356              :         /* Most likely the parent directory of database is read only */
     357            0 :         write_err |= utf8stream_writer_write_str( out_english_report,
     358              :                                                   "error: not possible to create a temporary database file for "
     359              :                                                 );
     360            0 :         write_err |= utf8stream_writer_write_str( out_english_report, file_name );
     361            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     362              :     }
     363            0 :     else if ( U8_ERROR_LOCKED_BY_TEMP_FILE == error )
     364              :     {
     365              :         /* Most likely the parent directory of database is read only */
     366            0 :         write_err |= utf8stream_writer_write_str( out_english_report,
     367              :                                                   "error: a temporary database file locks "
     368              :         );
     369            0 :         write_err |= utf8stream_writer_write_str( out_english_report, file_name );
     370            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     371            0 :         write_err |= utf8stream_writer_write_str( out_english_report,
     372              :                                                   "if the file is not used concurrently, either open that .tmp-cfu file or delete it.\n"
     373              :                                                 );
     374              :     }
     375              :     else
     376              :     {
     377            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "error opening database_file " );
     378            0 :         write_err |= utf8stream_writer_write_str( out_english_report, file_name );
     379            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     380              :     }
     381              : 
     382            0 :     U8_TRACE_END_ERR( write_err );
     383            0 :     return write_err;
     384              : }
     385              : 
     386            0 : u8_error_t main_commands_private_report_error_info ( main_commands_t *this_,
     387              :                                                      const u8_error_info_t *error_info,
     388              :                                                      utf8stream_writer_t *out_english_report )
     389              : {
     390            0 :     U8_TRACE_BEGIN();
     391            0 :     assert( error_info != NULL );
     392            0 :     assert( out_english_report != NULL );
     393            0 :     u8_error_t write_err = U8_ERROR_NONE;
     394              : 
     395            0 :     if ( u8_error_info_is_error( error_info ) )
     396              :     {
     397              :         char info_string_buf[80];
     398            0 :         utf8stringbuf_t info_string = UTF8STRINGBUF(info_string_buf);
     399            0 :         utf8stringbuf_clear( &info_string );
     400              :         {
     401              :             gui_error_info_printer_t my_err_info_printer;
     402            0 :             gui_error_info_printer_init( &my_err_info_printer );
     403            0 :             write_err |= gui_error_info_printer_show_error_info( &my_err_info_printer, error_info, info_string );
     404            0 :             gui_error_info_printer_destroy( &my_err_info_printer );
     405              :         }
     406            0 :         write_err |= utf8stream_writer_write_str( out_english_report, utf8stringbuf_get_string( &info_string ) );
     407            0 :         write_err |= utf8stream_writer_write_str( out_english_report, "\n" );
     408              :     }
     409              : 
     410            0 :     U8_TRACE_END_ERR( write_err );
     411            0 :     return write_err;
     412              : }
     413              : 
     414              : 
     415              : /*
     416              : Copyright 2016-2026 Andreas Warnke
     417              : 
     418              : Licensed under the Apache License, Version 2.0 (the "License");
     419              : you may not use this file except in compliance with the License.
     420              : You may obtain a copy of the License at
     421              : 
     422              :     http://www.apache.org/licenses/LICENSE-2.0
     423              : 
     424              : Unless required by applicable law or agreed to in writing, software
     425              : distributed under the License is distributed on an "AS IS" BASIS,
     426              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     427              : See the License for the specific language governing permissions and
     428              : limitations under the License.
     429              : */
        

Generated by: LCOV version 2.0-1