SolidSyslog coverage report
Current view: top level - Core/Source - SolidSyslogSdValue.c (source / functions) Coverage Total Hit
Test: SolidSyslog Lines: 100.0 % 73 73
Test Date: 2026-11-12 23:14:35 Functions: 100.0 % 12 12
Branches: 100.0 % 32 32

             Branch data     Line data    Source code
       1                 :             : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
       2                 :             :  * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
       3                 :             :  */
       4                 :             : 
       5                 :             : #include "SolidSyslogSdValuePrivate.h"
       6                 :             : 
       7                 :             : #include <stddef.h>
       8                 :             : #include <stdint.h>
       9                 :             : 
      10                 :             : #include "SolidSyslogFormatter.h"
      11                 :             : #include "SolidSyslogUtf8.h"
      12                 :             : 
      13                 :             : static size_t SdValue_DrainPending(struct SolidSyslogSdValue* value, const char* source);
      14                 :             : static void SdValue_WriteBody(struct SolidSyslogSdValue* value, const char* source);
      15                 :             : static inline size_t SdValue_ExpectedLength(char lead);
      16                 :             : static inline void SdValue_EmitUnit(struct SolidSyslogSdValue* value, const char* bytes, size_t count);
      17                 :             : static inline void SdValue_Hold(struct SolidSyslogSdValue* value, const char* bytes, size_t count);
      18                 :             : static inline void SdValue_FlushPendingAsReplacement(struct SolidSyslogSdValue* value);
      19                 :             : static inline void SdValue_FlushPendingIfHeld(struct SolidSyslogSdValue* value);
      20                 :             : 
      21                 :        8286 : void SolidSyslogSdValue_FromFormatter(struct SolidSyslogSdValue* value, struct SolidSyslogFormatter* formatter)
      22                 :             : {
      23                 :        8286 :     value->Formatter = formatter;
      24                 :        8286 :     value->PendingCount = 0;
      25                 :        8286 : }
      26                 :             : 
      27                 :        1406 : void SolidSyslogSdValue_String(struct SolidSyslogSdValue* value, const char* source)
      28                 :             : {
      29                 :        1406 :     size_t bodyStart = SdValue_DrainPending(value, source);
      30                 :        1406 :     SdValue_WriteBody(value, &source[bodyStart]);
      31                 :        1406 : }
      32                 :             : 
      33                 :             : /* Completes a held trailing sequence from the leading continuation bytes of
      34                 :             :  * source, returning the number of source bytes consumed doing so. A completed
      35                 :             :  * codepoint is emitted; a sequence interrupted by a non-continuation byte is
      36                 :             :  * replaced with one U+FFFD; a sequence still incomplete at end-of-source stays
      37                 :             :  * held for the next call. */
      38                 :        1406 : static size_t SdValue_DrainPending(struct SolidSyslogSdValue* value, const char* source)
      39                 :             : {
      40                 :        1406 :     size_t consumed = 0U;
      41         [ +  + ]:        1406 :     if (value->PendingCount > 0U)
      42                 :             :     {
      43                 :           7 :         size_t expected = SdValue_ExpectedLength(value->Pending[0]);
      44   [ +  +  +  + ]:          14 :         while ((value->PendingCount < expected) && SolidSyslogUtf8_IsContinuationByte(source[consumed]))
      45                 :             :         {
      46                 :           7 :             value->Pending[value->PendingCount] = source[consumed];
      47                 :           7 :             value->PendingCount++;
      48                 :           7 :             consumed++;
      49                 :             :         }
      50         [ +  + ]:           7 :         if (value->PendingCount == expected)
      51                 :             :         {
      52                 :           4 :             SdValue_EmitUnit(value, value->Pending, value->PendingCount);
      53                 :           4 :             value->PendingCount = 0;
      54                 :             :         }
      55         [ +  + ]:           3 :         else if (source[consumed] != '\0')
      56                 :             :         {
      57                 :           1 :             SdValue_FlushPendingAsReplacement(value);
      58                 :             :         }
      59                 :             :         else
      60                 :             :         {
      61                 :             :             /* source exhausted mid-sequence - keep the tail for the next call */
      62                 :             :         }
      63                 :             :     }
      64                 :        1406 :     return consumed;
      65                 :             : }
      66                 :             : 
      67                 :             : /* Walks source one UTF-8 unit at a time, emitting each complete unit through
      68                 :             :  * the formatter's escaper. A unit whose continuation bytes run out at
      69                 :             :  * end-of-source is held for the next call rather than emitted. */
      70                 :        1406 : static void SdValue_WriteBody(struct SolidSyslogSdValue* value, const char* source)
      71                 :             : {
      72                 :        1406 :     size_t i = 0U;
      73         [ +  + ]:       23492 :     while (source[i] != '\0')
      74                 :             :     {
      75                 :       22086 :         size_t expected = SdValue_ExpectedLength(source[i]);
      76                 :       22086 :         size_t avail = 1;
      77   [ +  +  +  + ]:       22088 :         while ((avail < expected) && SolidSyslogUtf8_IsContinuationByte(source[i + avail]))
      78                 :             :         {
      79                 :           2 :             avail++;
      80                 :             :         }
      81   [ +  +  +  + ]:       22086 :         if ((avail < expected) && (source[i + avail] == '\0'))
      82                 :             :         {
      83                 :           8 :             SdValue_Hold(value, &source[i], avail);
      84                 :             :         }
      85                 :             :         else
      86                 :             :         {
      87                 :       22078 :             SdValue_EmitUnit(value, &source[i], avail);
      88                 :             :         }
      89                 :       22086 :         i += avail;
      90                 :             :     }
      91                 :        1406 : }
      92                 :             : 
      93                 :             : /* The number of bytes a UTF-8 sequence starting with lead occupies, by its
      94                 :             :  * top-bit structure alone. ASCII, escapable, orphan-continuation and invalid
      95                 :             :  * leads are single-byte units; validity is left to the formatter's escaper. */
      96                 :       22093 : static inline size_t SdValue_ExpectedLength(char lead)
      97                 :             : {
      98                 :       22093 :     size_t length = 1;
      99         [ +  + ]:       22093 :     if (SolidSyslogUtf8_IsTwoByteLead(lead))
     100                 :             :     {
     101                 :           9 :         length = 2;
     102                 :             :     }
     103         [ +  + ]:       22084 :     else if (SolidSyslogUtf8_IsThreeByteLead(lead))
     104                 :             :     {
     105                 :           2 :         length = 3;
     106                 :             :     }
     107         [ +  + ]:       22082 :     else if (SolidSyslogUtf8_IsFourByteLead(lead))
     108                 :             :     {
     109                 :           6 :         length = 4;
     110                 :             :     }
     111                 :             :     else
     112                 :             :     {
     113                 :             :         /* single-byte unit */
     114                 :             :     }
     115                 :       22093 :     return length;
     116                 :             : }
     117                 :             : 
     118                 :             : /* Emits one UTF-8 unit through the formatter's escaper - the single source of
     119                 :             :  * truth for escaping ('"', '\\', ']') and per-byte ill-formed substitution. */
     120                 :       22082 : static inline void SdValue_EmitUnit(struct SolidSyslogSdValue* value, const char* bytes, size_t count)
     121                 :             : {
     122                 :             :     char unit[SDVALUE_MAX_CODEPOINT_BYTES + 1U];
     123         [ +  + ]:       44173 :     for (size_t i = 0U; i < count; i++)
     124                 :             :     {
     125                 :       22091 :         unit[i] = bytes[i];
     126                 :             :     }
     127                 :       22082 :     unit[count] = '\0';
     128                 :       22082 :     SolidSyslogFormatter_EscapedString(value->Formatter, unit, SIZE_MAX);
     129                 :       22082 : }
     130                 :             : 
     131                 :           8 : static inline void SdValue_Hold(struct SolidSyslogSdValue* value, const char* bytes, size_t count)
     132                 :             : {
     133         [ +  + ]:          17 :     for (size_t i = 0U; i < count; i++)
     134                 :             :     {
     135                 :           9 :         value->Pending[i] = bytes[i];
     136                 :             :     }
     137                 :           8 :     value->PendingCount = count;
     138                 :           8 : }
     139                 :             : 
     140                 :             : /* Re-uses the formatter's own ill-formed-byte substitution: a lone
     141                 :             :  * continuation byte decodes to exactly one U+FFFD, so the held tail is replaced
     142                 :             :  * without SdValue duplicating the replacement character. */
     143                 :           4 : static inline void SdValue_FlushPendingAsReplacement(struct SolidSyslogSdValue* value)
     144                 :             : {
     145                 :             :     static const char LONE_CONTINUATION[] = {'\x80', '\0'};
     146                 :           4 :     SolidSyslogFormatter_EscapedString(value->Formatter, LONE_CONTINUATION, SIZE_MAX);
     147                 :           4 :     value->PendingCount = 0;
     148                 :           4 : }
     149                 :             : 
     150                 :         255 : void SolidSyslogSdValue_BoundedString(struct SolidSyslogSdValue* value, const char* source, size_t maxDecodedLength)
     151                 :             : {
     152                 :         255 :     SdValue_FlushPendingIfHeld(value);
     153                 :         255 :     SolidSyslogFormatter_EscapedString(value->Formatter, source, maxDecodedLength);
     154                 :         255 : }
     155                 :             : 
     156                 :        6636 : void SolidSyslogSdValue_Uint32(struct SolidSyslogSdValue* value, uint32_t number)
     157                 :             : {
     158                 :        6636 :     SdValue_FlushPendingIfHeld(value);
     159                 :        6636 :     SolidSyslogFormatter_Uint32(value->Formatter, number);
     160                 :        6636 : }
     161                 :             : 
     162                 :        8259 : void SolidSyslogSdValue_Close(struct SolidSyslogSdValue* value)
     163                 :             : {
     164                 :        8259 :     SdValue_FlushPendingIfHeld(value);
     165                 :        8259 : }
     166                 :             : 
     167                 :             : /* A held incomplete UTF-8 tail is the dangling state of a prior
     168                 :             :  * SolidSyslogSdValue_String call. Any non-SolidSyslogSdValue_String write (or
     169                 :             :  * close) terminates it with one U+FFFD before its own output, so the tail is
     170                 :             :  * never reordered after, or merged into, that output. Only consecutive
     171                 :             :  * SolidSyslogSdValue_String calls continue a tail (streaming continuation). */
     172                 :       15150 : static inline void SdValue_FlushPendingIfHeld(struct SolidSyslogSdValue* value)
     173                 :             : {
     174         [ +  + ]:       15150 :     if (value->PendingCount > 0U)
     175                 :             :     {
     176                 :           3 :         SdValue_FlushPendingAsReplacement(value);
     177                 :             :     }
     178                 :       15150 : }
        

Generated by: LCOV version 2.0-1