LCOV - code coverage report
Current view: top level - io/source/format - io_md_writer.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.64.2_covts Lines: 100.0 % 75 75
Test Date: 2025-06-21 07:03:58 Functions: 100.0 % 3 3

            Line data    Source code
       1              : /* File: io_md_writer.c; Copyright and License: see below */
       2              : 
       3              : #include "format/io_md_writer.h"
       4              : #include "utf8stringbuf/utf8stringview.h"
       5              : #include "u8/u8_trace.h"
       6              : #include "u8/u8_log.h"
       7              : #include <stdio.h>
       8              : #include <stdbool.h>
       9              : #include <assert.h>
      10              : 
      11              : /* Note, this is no full markdown syntax support - but it helps keeping markdown in shape */
      12              : static const char IO_MD_WRITER_LINEBREAK = '\n';
      13              : static const char IO_MD_WRITER_LINK_AS_ID[] = "#id";
      14              : static const char IO_MD_WRITER_LINK_AS_NAME[] = "#name";
      15              : 
      16            3 : void io_md_writer_init ( io_md_writer_t *this_,
      17              :                          data_database_reader_t *db_reader,
      18              :                          const char * tag_linebreak,
      19              :                          const char * tag_xref_start,
      20              :                          const char * tag_xref_middle,
      21              :                          const char * tag_xref_end,
      22              :                          io_xml_writer_t *sink )
      23              : {
      24            3 :     U8_TRACE_BEGIN();
      25            3 :     assert( NULL != db_reader );
      26            3 :     assert( NULL != tag_linebreak );
      27            3 :     assert( NULL != tag_xref_start );
      28            3 :     assert( NULL != tag_xref_middle );
      29            3 :     assert( NULL != tag_xref_end );
      30            3 :     assert( NULL != sink );
      31              : 
      32            3 :     (*this_).db_reader = db_reader;
      33            3 :     (*this_).tag_linebreak = tag_linebreak;
      34            3 :     (*this_).tag_xref_start = tag_xref_start;
      35            3 :     (*this_).tag_xref_middle = tag_xref_middle;
      36            3 :     (*this_).tag_xref_end = tag_xref_end;
      37            3 :     (*this_).sink = sink;
      38              : 
      39            3 :     U8_TRACE_END();
      40            3 : }
      41              : 
      42            3 : void io_md_writer_destroy( io_md_writer_t *this_ )
      43              : {
      44            3 :     U8_TRACE_BEGIN();
      45              : 
      46            3 :     (*this_).sink = NULL;
      47            3 :     (*this_).db_reader = NULL;
      48              : 
      49            3 :     U8_TRACE_END();
      50            3 : }
      51              : 
      52            4 : u8_error_t io_md_writer_transform ( io_md_writer_t *this_, const char *text )
      53              : {
      54            4 :     U8_TRACE_BEGIN();
      55            4 :     assert ( NULL != text );
      56            4 :     assert ( NULL != (*this_).db_reader );
      57            4 :     assert ( NULL != (*this_).sink );
      58              : 
      59            4 :     unsigned int text_start_byte = 0;
      60            4 :     const unsigned int text_byte_length = utf8string_get_length( text );
      61            4 :     u8_error_t write_err = U8_ERROR_NONE;
      62              : 
      63          148 :     for ( unsigned int text_current_byte = 0; text_current_byte < text_byte_length; text_current_byte ++ )
      64              :     {
      65          144 :         const char current = text[text_current_byte];  /* note: only in case current<=0x7f this is a valid code point */
      66              : #if 0
      67              :         const char peeknext = text[text_current_byte+1];  /* note: only in case current<=0x7f this is a valid code point, 0 at string end */
      68              : #endif
      69          144 :         if ( current == IO_MD_WRITER_LINEBREAK )
      70              :         {
      71              : #if 0
      72              :             if (( peeknext == IO_MD_WRITER_LINEBREAK )
      73              :                 || ( peeknext == '+' )  /* list */
      74              :                 || ( peeknext == '*' )  /* list */
      75              :                 || ( peeknext == '-' )  /* list or heading */
      76              :                 || ( peeknext == '=' )  /* heading */
      77              :                 || ( peeknext == '#' )  /* heading */
      78              :                 || ( peeknext == '0' )  /* ordered list */
      79              :                 || ( peeknext == '1' )  /* ordered list */
      80              :                 || ( peeknext == '2' )  /* ordered list */
      81              :                 || ( peeknext == '3' )  /* ordered list */
      82              :                 || ( peeknext == '4' )  /* ordered list */
      83              :                 || ( peeknext == '5' )  /* ordered list */
      84              :                 || ( peeknext == '6' )  /* ordered list */
      85              :                 || ( peeknext == '7' )  /* ordered list */
      86              :                 || ( peeknext == '8' )  /* ordered list */
      87              :                 || ( peeknext == '9' )  /* ordered list */
      88              :                 || ( peeknext == '>' )  /* citation */
      89              :                 /*|| ( peeknext == ' ' )*/  /* list continuation */
      90              :                 || ( peeknext == '|' ))  /* table */
      91              : #endif
      92              :             {
      93           12 :                 const utf8stringview_t str_view = UTF8STRINGVIEW( &(text[text_start_byte]), text_current_byte-text_start_byte );
      94           12 :                 write_err |= io_xml_writer_write_xml_enc_view( (*this_).sink, &str_view );
      95           12 :                 write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_linebreak );
      96           12 :                 text_start_byte = text_current_byte+1;
      97              :             }
      98              :         }
      99          132 :         else if ( current == DATA_TABLE_ALPHANUM_DIAGRAM /* = 'D' */)
     100              :         {
     101              :             /* try to parse an id */
     102           12 :             data_id_t probe_id = DATA_ID_VOID;
     103              :             utf8stringview_t string_to_parse;
     104           12 :             utf8stringview_t remainder = UTF8STRINGVIEW_EMPTY;
     105              :             const utf8error_t region_err
     106           12 :                 = utf8stringview_init_region( &string_to_parse, text, text_current_byte, text_byte_length - text_current_byte );
     107           12 :             if ( region_err == UTF8ERROR_SUCCESS )
     108              :             {
     109           12 :                 data_id_init_by_stringview( &probe_id, &string_to_parse, &remainder );
     110              :             }
     111           12 :             const unsigned int id_length = utf8stringview_get_length( &string_to_parse ) - utf8stringview_get_length( &remainder );
     112              : 
     113           12 :             if ( data_id_is_valid( &probe_id ) )
     114              :             {
     115            5 :                 const bool show_id = utf8stringview_starts_with_str( &remainder, IO_MD_WRITER_LINK_AS_ID );
     116            5 :                 const bool show_name
     117              :                     = show_id
     118              :                     ? false
     119            5 :                     : utf8stringview_starts_with_str( &remainder, IO_MD_WRITER_LINK_AS_NAME );
     120              : 
     121            5 :                 if ( show_id || show_name )
     122            3 :                 {
     123              :                     u8_error_t d_err;
     124            3 :                     d_err = data_database_reader_get_diagram_by_id ( (*this_).db_reader, data_id_get_row_id( &probe_id ), &((*this_).temp_diagram) );
     125            3 :                     if ( d_err == U8_ERROR_NONE )
     126              :                     {
     127              :                         /* write previously parsed characters */
     128            2 :                         const utf8stringview_t str_view = UTF8STRINGVIEW( &(text[text_start_byte]), text_current_byte-text_start_byte );
     129            2 :                         write_err |= io_xml_writer_write_xml_enc_view( (*this_).sink, &str_view );
     130            2 :                         text_start_byte = text_current_byte;
     131              : 
     132              :                         /* write id */
     133            2 :                         char probe_id_str_buf[DATA_ID_MAX_UTF8STRING_SIZE] = "";
     134            2 :                         utf8stringbuf_t probe_id_str = UTF8STRINGBUF( probe_id_str_buf );
     135            2 :                         write_err |= data_id_to_utf8stringbuf ( &probe_id, probe_id_str );
     136            2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_start );
     137            2 :                         write_err |= io_xml_writer_write_xml_enc( (*this_).sink, utf8stringbuf_get_string( &probe_id_str ) );
     138            2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_middle );
     139            2 :                         if ( show_id )
     140              :                         {
     141            1 :                             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, utf8stringbuf_get_string( &probe_id_str ) );
     142            1 :                             text_current_byte += id_length + sizeof(IO_MD_WRITER_LINK_AS_ID)-1 - 1;
     143              :                         }
     144              :                         else /* show_name */
     145              :                         {
     146            1 :                             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, data_diagram_get_name_const( &((*this_).temp_diagram) ) );
     147            1 :                             text_current_byte += id_length + sizeof(IO_MD_WRITER_LINK_AS_NAME)-1 - 1;
     148              :                         }
     149            2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_end );
     150            2 :                         text_start_byte = text_current_byte+1;
     151              : 
     152              :                         /* destroy the diagram */
     153            2 :                         data_diagram_destroy( &((*this_).temp_diagram) );
     154              :                     }
     155              :                     else
     156              :                     {
     157            1 :                         U8_TRACE_INFO_INT("id found but diagram does not exist: D", data_id_get_row_id( &probe_id ) );
     158              :                     }
     159              :                 }
     160              :                 else
     161              :                 {
     162            2 :                     U8_TRACE_INFO_INT("id found but #id or #name fragment missing: D", data_id_get_row_id( &probe_id ) );
     163              :                 }
     164              :             }
     165              :         }
     166              : 
     167          144 :         if ( text_current_byte+1 == text_byte_length )
     168              :         {
     169            4 :             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, &(text[text_start_byte]) );
     170              :         }
     171              :     }
     172              : 
     173            4 :     U8_TRACE_END_ERR( write_err );
     174            4 :     return write_err;
     175              : }
     176              : 
     177              : 
     178              : /*
     179              : Copyright 2019-2025 Andreas Warnke
     180              : 
     181              : Licensed under the Apache License, Version 2.0 (the "License");
     182              : you may not use this file except in compliance with the License.
     183              : You may obtain a copy of the License at
     184              : 
     185              :     http://www.apache.org/licenses/LICENSE-2.0
     186              : 
     187              : Unless required by applicable law or agreed to in writing, software
     188              : distributed under the License is distributed on an "AS IS" BASIS,
     189              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     190              : See the License for the specific language governing permissions and
     191              : limitations under the License.
     192              : */
        

Generated by: LCOV version 2.0-1