Skip to content

feat: S14.07 move header-field callbacks off the formatter#557

Merged
DavidCozens merged 3 commits into
mainfrom
feat/s14-07-header-field-writer
Jun 6, 2026
Merged

feat: S14.07 move header-field callbacks off the formatter#557
DavidCozens merged 3 commits into
mainfrom
feat/s14-07-header-field-writer

Conversation

@DavidCozens

@DavidCozens DavidCozens commented Jun 6, 2026

Copy link
Copy Markdown
Owner

Closes #547. Parent epic: #64.

What changes

Introduces SolidSyslogHeaderField — an opaque, stack-transient US-ASCII writer for
the RFC 5424 HOSTNAME / APP-NAME / PROCID header fields. It wraps the message-buffer
formatter and exposes only:

  • _PrintUsAscii(source, maxLength) — printable-US-ASCII (!..~) filter, everything
    else (space included) substituted, NUL-stopped, bounded by maxLength and the field
    width.
  • _Uint32(value) — for PROCID.

These fields use the PRINTUSASCII charset (a different rule from SD escaping), so this is a
dedicated writer rather than a reuse of SolidSyslogSdValue.

  • The three header-field callbacks change from SolidSyslogStringFunction to
    SolidSyslogHeaderFieldFunction (void(struct SolidSyslogHeaderField*, void* context)),
    in its own header, with paired context fields on SolidSyslogConfig and the
    MessageFormatter context.
  • MessageFormatter builds one SolidSyslogHeaderField per field (cap = field-storage
    size − 1, preserving the old scratch-formatter's null-slot width) and passes it — the
    scratch-field + re-filter path is gone.
  • The Posix/Windows hostname & processId helpers and every BDD header-field callback move
    to the new shape.
  • SolidSyslogStringFunction.h is retired — it was the last public consumer of
    SolidSyslogFormatter, clearing the way for S14.08 to make the formatter fully private.

Output is byte-for-byte identical — existing tests stand (including the 255 / 48 / 128
field-truncation cases). SolidSyslogHeaderField itself is TDD'd by a new 10-test unit.

Surprises handled

  • PosixMessageQueueBuffer coincidentally reused the PROCID helper to stamp its queue name
    with the pid; decoupled to a direct getpid() + Formatter_Uint32 rather than route a
    queue name through the header-field helper (which would force a Platform source to include
    a Core/Source-private header).
  • ~16 positional SolidSyslogConfig{} test literals silently misaligned once three context
    fields were interleaved (store landing in a void* context slot) — fixed.

Acceptance criteria

  • Header-field output unchanged byte-for-byte (existing tests stand)
  • Non-printable / space substitution preserved (the _PrintUsAsciiString rule)
  • NULL callback → NILVALUE - as today
  • Callbacks carry void* context
  • SolidSyslogStringFunction.h removed and no references remain

Out of scope

  • Moving SolidSyslogFormatter.h out of the public interface (S14.08), with the wholesale
    CLAUDE.md header-table revision.

Checks

Debug green (1469 tests); BddTargetTests 66/66. clang-format applied; cppcheck-MISRA exit 0
(14 suppression anchors moved: SolidSyslog.c 11.8 ×8, MessageFormatter.c 11.8 ×5 + 5.7
20→21; misra_renumber.py clean). The Windows hostname/processId helper tests are updated
but only build in the Windows CI lane.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Migrated hostname, app-name and process-id formatting to a new header-field writer API and added per-call context support; preserved byte-identical output.
  • Tests
    • Added/updated tests validating header-field ASCII printing, truncation, shared budget behavior, and numeric formatting.
  • Documentation
    • Updated RFC‑5424 compliance notes and DEVLOG entry describing the callback migration and safety fixes.

DavidCozens and others added 2 commits June 6, 2026 09:06
Introduce SolidSyslogHeaderField — an opaque, stack-transient US-ASCII writer
for the RFC 5424 HOSTNAME / APP-NAME / PROCID header fields. It wraps the
message-buffer formatter and exposes only a PRINTUSASCII append (printable
US-ASCII '!'..'~', everything else — space included — substituted) bounded to
the field width, plus a Uint32 for PROCID. The PRINTUSASCII charset is a
different rule from SD escaping, hence a dedicated writer rather than reusing
SolidSyslogSdValue.

Change the three header-field callbacks from SolidSyslogStringFunction to the
new SolidSyslogHeaderFieldFunction (void(SolidSyslogHeaderField*, void* context))
with paired context fields on SolidSyslogConfig and the MessageFormatter
context. MessageFormatter now builds one HeaderField per field (capped at the
field width) and passes it; the scratch-field formatter + re-filter is gone.
The Posix/Windows hostname & processId helpers and every BDD header-field
callback move to the new shape. SolidSyslogStringFunction.h is retired — it was
the last public consumer of SolidSyslogFormatter, clearing the way for S14.08.

PosixMessageQueueBuffer, which reused the PROCID helper to stamp its queue name
with the pid, now formats getpid() directly rather than depend on the
header-field helper. Output is byte-for-byte identical; existing tests stand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 228ea6ea-c2a9-44d9-9736-14f4cd1f1224

📥 Commits

Reviewing files that changed from the base of the PR and between 2fdb69e and 044eff1.

📒 Files selected for processing (3)
  • Core/Source/SolidSyslogHeaderField.c
  • DEVLOG.md
  • Tests/SolidSyslogHeaderFieldTest.cpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • Tests/SolidSyslogHeaderFieldTest.cpp
  • Core/Source/SolidSyslogHeaderField.c

📝 Walkthrough

Walkthrough

This PR migrates HOSTNAME/APP-NAME/PROCID header callbacks from formatter/string callbacks to a new SolidSyslogHeaderField writer with per-call void* context, updates core config/initialization to carry function+context, rewires MessageFormatter to build header fields, ports platform/target helpers, and adjusts/extends tests and build files.

Changes

Header-field callback migration

Layer / File(s) Summary
Header-field writer abstraction and implementation
Core/Interface/SolidSyslogHeaderField.h, Core/Interface/SolidSyslogHeaderFieldFunction.h, Core/Source/SolidSyslogHeaderFieldPrivate.h, Core/Source/SolidSyslogHeaderField.c, Core/Source/CMakeLists.txt
Adds opaque SolidSyslogHeaderField, SolidSyslogHeaderField_PrintUsAscii and SolidSyslogHeaderField_Uint32, private struct with Remaining budget, FromFormatter wrapper, and adds the new source to the static lib.
Callback function type and configuration
Core/Interface/SolidSyslogHeaderFieldFunction.h, Core/Interface/SolidSyslogConfig.h, Core/Source/SolidSyslogPrivate.h
Defines SolidSyslogHeaderFieldFunction typedef, replaces SolidSyslogStringFunction fields with header-field function+context pairs in SolidSyslogConfig, and updates TU null handler declaration.
Core initialization and null callback
Core/Source/SolidSyslog.c, Core/Source/SolidSyslogStatic.c
Installs configured header-field callbacks plus context during initialise, resets to SolidSyslog_NullHeaderField with NULL contexts, and updates installation helpers to store both pointer and context.
Message formatter integration
Core/Source/SolidSyslogMessageFormatter.h, Core/Source/SolidSyslogMessageFormatter.c
Refactors MessageFormatter to create a SolidSyslogHeaderField per field (maxSize-1), invoke provided header-field function with (field, context), and emit NIL when no output was produced.
POSIX platform implementations
Platform/Posix/Interface/SolidSyslogPosixHostname.h, Platform/Posix/Source/SolidSyslogPosixHostname.c, Platform/Posix/Interface/SolidSyslogPosixProcessId.h, Platform/Posix/Source/SolidSyslogPosixProcessId.c, Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c
Update POSIX hostname/procid APIs to (field, context), write via header-field API, add <unistd.h> and in one place use direct getpid() for queue naming.
Windows platform implementations
Platform/Windows/Interface/SolidSyslogWindowsHostname.h, Platform/Windows/Source/SolidSyslogWindowsHostname.c, Platform/Windows/Interface/SolidSyslogWindowsProcessId.h, Platform/Windows/Source/SolidSyslogWindowsProcessId.c
Port Windows hostname/procid helpers to the header-field API and updated includes/forward declarations.
BDD target callbacks
Bdd/Targets/Common/BddTargetAppName.h, Bdd/Targets/Common/BddTargetAppName.c, Bdd/Targets/Common/BddTargetFreeRtosPipeline.h, Bdd/Targets/Common/BddTargetFreeRtosPipeline.c, Bdd/Targets/FreeRtos/main.c, Bdd/Targets/FreeRtosLwip/main.c
Refactors BDD app-name and FreeRTOS hostname callbacks to accept (field, context) and emit via header-field writer (context ignored).
Test infrastructure and coverage
Tests/StringFake.h, Tests/StringFake.c, Tests/StringFakeTest.cpp, Tests/SolidSyslogHeaderFieldTest.cpp, Tests/CMakeLists.txt
Update test fakes to new signature, add comprehensive unit tests for header-field writer (sanitization, truncation, shared budget, Uint32 behavior), and include the new tests in build.
Test suite updates
Tests/* (many files)
Adjust numerous test initializers and fixtures to construct SolidSyslogHeaderField instances, pass (field, context) to callsites, and update SolidSyslogConfig aggregate initializers to match new field order.
Docs and metadata
DEVLOG.md, docs/rfc-compliance.md, misra_suppressions.txt
Document S14.07 migration and follow-up, update RFC matrix row, and retarget MISRA suppression line numbers.

Sequence Diagram(s)

(omitted — changes are primarily API migration and internal wiring; no additional diagram provided)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • DavidCozens/solid-syslog#502: Extracted MessageFormatter/context work; this PR adapts that extraction to header-field callbacks.
  • DavidCozens/solid-syslog#150: Introduced Windows hostname/processId using the old formatter callback; this PR migrates those helpers to header-field callbacks.
  • DavidCozens/solid-syslog#113: Prior callback-plumbing refactor; this PR completes migration by replacing string-function callbacks with header-field writer callbacks.

"A rabbit with a tiny pen,
Writes header fields again and again,
ASCII kept clean and tight,
Callbacks carry context right,
Hopping tests all pass tonight 🐇"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: S14.07 move header-field callbacks off the formatter' accurately summarizes the primary change: refactoring header-field callbacks to use a new SolidSyslogHeaderField writer instead of SolidSyslogFormatter.
Description check ✅ Passed The PR description comprehensively covers purpose (issue #547, epic #64), detailed changes (new SolidSyslogHeaderField API, callback signature updates, affected files), test evidence (byte-for-byte identical output, 1469 debug tests pass, 66 BDD tests pass), and areas affected (Core, Platform/Posix, Platform/Windows, Bdd, Tests).
Linked Issues check ✅ Passed The PR implementation fully satisfies issue #547 objectives: introduces SolidSyslogHeaderField with _PrintUsAscii and _Uint32 methods [#547], refactors callbacks from SolidSyslogStringFunction to SolidSyslogHeaderFieldFunction with context support [#547], updates MessageFormatter and platform helpers [#547], removes SolidSyslogStringFunction.h [#547], and maintains byte-for-byte identical output [#547].
Out of Scope Changes check ✅ Passed All changes align with PR scope: SolidSyslogHeaderField introduction, callback migration, SolidSyslogStringFunction retirement, and platform helper updates directly address issue #547. The PR correctly excludes moving SolidSyslogFormatter to private (S14.08), and the PosixMessageQueueBuffer change (direct getpid() instead of header-field routing) is a necessary decoupling to avoid circular dependencies—in scope as a clarification of the helper's proper usage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/s14-07-header-field-writer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1506 passed)
   🚦   build-freertos-host-tdd-plustcp: 100% successful (✔️ 1857 passed)
   🚦   build-linux-clang: 100% successful (✔️ 1440 passed)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1440 passed)
   🚦   integration-linux-openssl: 100% successful (✔️ 16 passed)
   🚦   integration-linux-mbedtls: 100% successful (✔️ 14 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 16 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 48 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 88% successful (✔️ 45 passed, 🙈 6 skipped)
   🚦   bdd-freertos-qemu-plustcp: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   bdd-freertos-qemu-lwip: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 1285 passed)
   🚦   build-linux-tunable-override: 100% successful (✔️ 1440 passed)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Core/Source/SolidSyslogHeaderField.c`:
- Around line 28-34: SolidSyslogHeaderField_Uint32 currently subtracts
HeaderField_Consumed from field->Remaining without protecting against the
formatter emitting more bytes than the remaining budget; change
SolidSyslogHeaderField_Uint32 to first record size_t before =
SolidSyslogFormatter_Length(field->Formatter) and size_t beforeRemaining =
field->Remaining, skip calling SolidSyslogFormatter_Uint32 entirely if
beforeRemaining == 0, otherwise call the formatter, compute size_t consumed =
HeaderField_Consumed(field, before) and then if (consumed >= beforeRemaining)
set field->Remaining = 0 else subtract consumed from field->Remaining; this
prevents size_t underflow and enforces the header-field width while still
accounting for actual bytes produced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6e398ec-f2f1-44cb-999e-ba40944eb2ac

📥 Commits

Reviewing files that changed from the base of the PR and between 26f663d and 2fdb69e.

📒 Files selected for processing (43)
  • Bdd/Targets/Common/BddTargetAppName.c
  • Bdd/Targets/Common/BddTargetAppName.h
  • Bdd/Targets/Common/BddTargetFreeRtosPipeline.c
  • Bdd/Targets/Common/BddTargetFreeRtosPipeline.h
  • Bdd/Targets/FreeRtos/main.c
  • Bdd/Targets/FreeRtosLwip/main.c
  • Core/Interface/SolidSyslogConfig.h
  • Core/Interface/SolidSyslogHeaderField.h
  • Core/Interface/SolidSyslogHeaderFieldFunction.h
  • Core/Interface/SolidSyslogStringFunction.h
  • Core/Source/CMakeLists.txt
  • Core/Source/SolidSyslog.c
  • Core/Source/SolidSyslogHeaderField.c
  • Core/Source/SolidSyslogHeaderFieldPrivate.h
  • Core/Source/SolidSyslogMessageFormatter.c
  • Core/Source/SolidSyslogMessageFormatter.h
  • Core/Source/SolidSyslogPrivate.h
  • Core/Source/SolidSyslogStatic.c
  • DEVLOG.md
  • Platform/Posix/Interface/SolidSyslogPosixHostname.h
  • Platform/Posix/Interface/SolidSyslogPosixProcessId.h
  • Platform/Posix/Source/SolidSyslogPosixHostname.c
  • Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c
  • Platform/Posix/Source/SolidSyslogPosixProcessId.c
  • Platform/Windows/Interface/SolidSyslogWindowsHostname.h
  • Platform/Windows/Interface/SolidSyslogWindowsProcessId.h
  • Platform/Windows/Source/SolidSyslogWindowsHostname.c
  • Platform/Windows/Source/SolidSyslogWindowsProcessId.c
  • Tests/Bdd/Targets/BddTargetAppNameTest.cpp
  • Tests/Bdd/Targets/BddTargetServiceThreadTest.cpp
  • Tests/CMakeLists.txt
  • Tests/SolidSyslogHeaderFieldTest.cpp
  • Tests/SolidSyslogMessageFormatterTest.cpp
  • Tests/SolidSyslogPoolTest.cpp
  • Tests/SolidSyslogPosixMessageQueueBufferTest.cpp
  • Tests/SolidSyslogTest.cpp
  • Tests/SolidSyslogWindowsHostnameTest.cpp
  • Tests/SolidSyslogWindowsProcessIdTest.cpp
  • Tests/StringFake.c
  • Tests/StringFake.h
  • Tests/StringFakeTest.cpp
  • docs/rfc-compliance.md
  • misra_suppressions.txt
💤 Files with no reviewable changes (1)
  • Core/Interface/SolidSyslogStringFunction.h

Comment thread Core/Source/SolidSyslogHeaderField.c
A header-field callback is arbitrary user code that may make any number of
mixed _PrintUsAscii / _Uint32 appends on one field, so the field-width budget
must hold across calls. _Uint32 subtracted the consumed bytes from Remaining
unconditionally, underflowing size_t when a number overran the remainder. Skip
the write once the field is full and clamp Remaining to zero instead of
underflowing. Two tests cover the mixed-append cap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1508 passed)
   🚦   build-freertos-host-tdd-plustcp: 100% successful (✔️ 1859 passed)
   🚦   build-linux-clang: 100% successful (✔️ 1442 passed)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1442 passed)
   🚦   integration-linux-openssl: 100% successful (✔️ 16 passed)
   🚦   integration-linux-mbedtls: 100% successful (✔️ 14 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 16 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 48 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 88% successful (✔️ 45 passed, 🙈 6 skipped)
   🚦   bdd-freertos-qemu-plustcp: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   bdd-freertos-qemu-lwip: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 1287 passed)
   🚦   build-linux-tunable-override: 100% successful (✔️ 1442 passed)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

@DavidCozens DavidCozens merged commit 678547f into main Jun 6, 2026
27 checks passed
@DavidCozens DavidCozens deleted the feat/s14-07-header-field-writer branch June 6, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S14.07: Move header-field callbacks off the formatter

1 participant