LCOV - code coverage report
Current view: top level - io/source/format - io_md_writer.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 93 93 100.0 %
Date: 2024-10-26 21:44:38 Functions: 3 3 100.0 %

          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         144 :         const char peeknext = text[text_current_byte+1];  /* note: only in case current<=0x7f this is a valid code point, 0 at string end */
      67         144 :         if ( current == IO_MD_WRITER_LINEBREAK )
      68             :         {
      69          12 :             if (( peeknext == IO_MD_WRITER_LINEBREAK )
      70           9 :                 || ( peeknext == '+' )  /* list */
      71           9 :                 || ( peeknext == '*' )  /* list */
      72           9 :                 || ( peeknext == '-' )  /* list or heading */
      73           8 :                 || ( peeknext == '=' )  /* heading */
      74           8 :                 || ( peeknext == '#' )  /* heading */
      75           8 :                 || ( peeknext == '0' )  /* ordered list */
      76           8 :                 || ( peeknext == '1' )  /* ordered list */
      77           8 :                 || ( peeknext == '2' )  /* ordered list */
      78           8 :                 || ( peeknext == '3' )  /* ordered list */
      79           8 :                 || ( peeknext == '4' )  /* ordered list */
      80           7 :                 || ( peeknext == '5' )  /* ordered list */
      81           6 :                 || ( peeknext == '6' )  /* ordered list */
      82           6 :                 || ( peeknext == '7' )  /* ordered list */
      83           6 :                 || ( peeknext == '8' )  /* ordered list */
      84           6 :                 || ( peeknext == '9' )  /* ordered list */
      85           6 :                 || ( peeknext == '>' )  /* citation */
      86             :                 /*|| ( peeknext == ' ' )*/  /* list continuation */
      87           5 :                 || ( peeknext == '|' ))  /* table */
      88             : 
      89             :             {
      90           7 :                 const utf8stringview_t str_view = UTF8STRINGVIEW( &(text[text_start_byte]), text_current_byte-text_start_byte );
      91           7 :                 write_err |= io_xml_writer_write_xml_enc_view( (*this_).sink, &str_view );
      92           7 :                 write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_linebreak );
      93           7 :                 text_start_byte = text_current_byte+1;
      94             :             }
      95             :         }
      96         132 :         else if ( current == DATA_TABLE_ALPHANUM_DIAGRAM /* = 'D' */)
      97             :         {
      98             :             /* try to parse an id */
      99          12 :             data_id_t probe_id = DATA_ID_VOID;
     100             :             utf8stringview_t string_to_parse;
     101             :             utf8stringview_t remainder;
     102             :             const utf8error_t region_err
     103          12 :                 = utf8stringview_init_region( &string_to_parse, text, text_current_byte, text_byte_length - text_current_byte );
     104          12 :             if ( region_err == UTF8ERROR_SUCCESS )
     105             :             {
     106          12 :                 data_id_init_by_stringview( &probe_id, &string_to_parse, &remainder );
     107             :             }
     108          12 :             const unsigned int id_length = utf8stringview_get_length( &string_to_parse ) - utf8stringview_get_length( &remainder );
     109             : 
     110          12 :             if ( data_id_is_valid( &probe_id ) )
     111             :             {
     112           5 :                 const bool show_id = utf8stringview_starts_with_str( &remainder, IO_MD_WRITER_LINK_AS_ID );
     113           5 :                 const bool show_name
     114             :                     = show_id
     115             :                     ? false
     116           5 :                     : utf8stringview_starts_with_str( &remainder, IO_MD_WRITER_LINK_AS_NAME );
     117             : 
     118           5 :                 if ( show_id || show_name )
     119           3 :                 {
     120             :                     u8_error_t d_err;
     121           3 :                     d_err = data_database_reader_get_diagram_by_id ( (*this_).db_reader, data_id_get_row_id( &probe_id ), &((*this_).temp_diagram) );
     122           3 :                     if ( d_err == U8_ERROR_NONE )
     123             :                     {
     124             :                         /* write previously parsed characters */
     125           2 :                         const utf8stringview_t str_view = UTF8STRINGVIEW( &(text[text_start_byte]), text_current_byte-text_start_byte );
     126           2 :                         write_err |= io_xml_writer_write_xml_enc_view( (*this_).sink, &str_view );
     127           2 :                         text_start_byte = text_current_byte;
     128             : 
     129             :                         /* write id */
     130           2 :                         char probe_id_str_buf[DATA_ID_MAX_UTF8STRING_SIZE] = "";
     131           2 :                         utf8stringbuf_t probe_id_str = UTF8STRINGBUF( probe_id_str_buf );
     132           2 :                         write_err |= data_id_to_utf8stringbuf ( &probe_id, probe_id_str );
     133           2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_start );
     134           2 :                         write_err |= io_xml_writer_write_xml_enc( (*this_).sink, utf8stringbuf_get_string( probe_id_str ) );
     135           2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_middle );
     136           2 :                         if ( show_id )
     137             :                         {
     138           1 :                             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, utf8stringbuf_get_string( probe_id_str ) );
     139           1 :                             text_current_byte += id_length + sizeof(IO_MD_WRITER_LINK_AS_ID)-1 - 1;
     140             :                         }
     141             :                         else /* show_name */
     142             :                         {
     143           1 :                             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, data_diagram_get_name_const( &((*this_).temp_diagram) ) );
     144           1 :                             text_current_byte += id_length + sizeof(IO_MD_WRITER_LINK_AS_NAME)-1 - 1;
     145             :                         }
     146           2 :                         write_err |= io_xml_writer_write_plain ( (*this_).sink, (*this_).tag_xref_end );
     147           2 :                         text_start_byte = text_current_byte+1;
     148             : 
     149             :                         /* destroy the diagram */
     150           2 :                         data_diagram_destroy( &((*this_).temp_diagram) );
     151             :                     }
     152             :                     else
     153             :                     {
     154           1 :                         U8_TRACE_INFO_INT("id found but diagram does not exist: D", data_id_get_row_id( &probe_id ) );
     155             :                     }
     156             :                 }
     157             :                 else
     158             :                 {
     159           2 :                     U8_TRACE_INFO_INT("id found but #id or #name fragment missing: D", data_id_get_row_id( &probe_id ) );
     160             :                 }
     161             :             }
     162             :         }
     163             : 
     164         144 :         if ( text_current_byte+1 == text_byte_length )
     165             :         {
     166           4 :             write_err |= io_xml_writer_write_xml_enc( (*this_).sink, &(text[text_start_byte]) );
     167             :         }
     168             :     }
     169             : 
     170           4 :     U8_TRACE_END_ERR( write_err );
     171           4 :     return write_err;
     172             : }
     173             : 
     174             : 
     175             : /*
     176             : Copyright 2019-2024 Andreas Warnke
     177             : 
     178             : Licensed under the Apache License, Version 2.0 (the "License");
     179             : you may not use this file except in compliance with the License.
     180             : You may obtain a copy of the License at
     181             : 
     182             :     http://www.apache.org/licenses/LICENSE-2.0
     183             : 
     184             : Unless required by applicable law or agreed to in writing, software
     185             : distributed under the License is distributed on an "AS IS" BASIS,
     186             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     187             : See the License for the specific language governing permissions and
     188             : limitations under the License.
     189             : */

Generated by: LCOV version 1.16