Skip to content

Maintainer Guide

Codebase architecture, development guidelines, formatting standards, and maintainer documentation index for siddiqsoft::sip2json.


Documentation Index

The maintainer documentation is organized into modular topic guides:

Topic Guide Description
CI/CD Pipelines Azure Pipelines architecture, build matrix, platform triggers, and parameters
CMake Presets Decoupled presets hierarchy, project-base.json, and preset reference
Development Workflow Local building, testing, standalone validation subproject, and macOS toolchain
Build Agent Requirements Prerequisites and configuration for macOS, Linux, and Windows self-hosted agents
Release & Publication GitVersion, SemVer tagging, GitHub Releases, and NuGet package publishing
Documentation Architecture MkDocs Material, Doxygen XML, custom CSS tokens, hooks, and local preview

Codebase Architecture & UML Class Diagram

The following UML class diagram illustrates the primary classes, relationships, and exception hierarchy in siddiqsoft::sip2json. The diagram is auto-generated from the C++ source AST via Doxygen XML. Each node in the diagram links directly to its source header file on GitHub.

classDiagram
    direction TB

    classDef coreClass fill:rgba(35,73,109,0.08),stroke:#23496d,stroke-width:2px;
    classDef utilityClass fill:rgba(15,118,110,0.08),stroke:#0f766e,stroke-width:2px;
    classDef exceptionClass fill:rgba(185,28,28,0.06),stroke:#b91c1c,stroke-width:1.5px;
    classDef enumClass fill:rgba(109,40,217,0.06),stroke:#6d28d9,stroke-width:1.5px;
    classDef externalClass fill:rgba(100,116,139,0.06),stroke:#64748b,stroke-width:1.5px,stroke-dasharray: 4 3;
    classDef highlightClass fill:rgba(2,132,199,0.18),stroke:#0284c7,stroke-width:3px;

    class json["nlohmann::json"] {
        <<external DOM>>
    }
    class json:::externalClass

    class runtime_error["std::runtime_error"] {
        <<external exception>>
    }
    class runtime_error:::externalClass

    class sip2json["siddiqsoft::sip2json"] {
        <<final utility>>
        +parseAsync(string_view& frameBuffer, callback parseCallback, callback errorCallback)$ size_t
        +parse(string_view& buffer)$ vector~sipmessage~
        +parseFromBuffer(string_view& buffer)$ sipmessage
        +serialize(sipmessage& sipm)$ string
    }
    class sip2json:::utilityClass

    class sipmessage["siddiqsoft::sipmessage"] {
        +sipmessage()
        +headers() auto&
        +getHeader(string& key, optional~T~ defaultValue) auto
        +hasHeader(string_view key) bool
        +setUserAgent(string& ua) auto&
        +getUserAgent() auto
        +getContentLength() uint32_t
        +getExpires() uint32_t
        +getContentTypeView() string_view
        +getContentType() string
        +getCallID() auto
        +getMethod() auto
        +getUri() auto
        +getMethodView() string_view
        +getUriView() string_view
        +getReasonView() string_view
        +getCallIDView() string_view
        +getStatusCode() auto
        +getReason() auto
        +body() auto&
        +hasBody() bool
        +getBodyElement(json_pointer& jp, T& defaultValue) T
        +isMessageRequest() bool
        +isMessageResponse() bool
        +setHeader(string& key, T& v) sipmessage&
        +setBody(json_pointer& key, T& v) sipmessage&
    }
    class sipmessage:::coreClass

    class HeaderKeySet["siddiqsoft::HeaderKeySet"] {
        +bool isCanonical
        +bool isMultiLine
        +bool isCustom
        +HeaderKeySet() constexpr
        +canonical() string&
        +lower() string&
        +alt() string&
    }
    class HeaderKeySet:::coreClass

    class SIPMessageType["siddiqsoft::SIPMessageType"] {
        <<enumeration>>
        notspecified
        request = 1
        response = 2
    }
    class SIPMessageType:::enumClass

    class sip2jsonErrors["siddiqsoft::sip2jsonErrors"] {
        <<enumeration>>
        ok = 0
        incomplete_buffer_for_parse
        incomplete_buffer_for_content
        incomplete_buffer_for_header
        invalid_startline
        unsupported_contenttype
        missing_required_element
        invalid_document
        invalid_document_unsupported_method
        invalid_document_unsupported_content
        empty_message
        unknown = 0xFFFFFFFF
    }
    class sip2jsonErrors:::enumClass

    class sip2json_exception["siddiqsoft::sip2json_exception"] {
        +sip2jsonErrors errCode
        +sip2json_exception(string& msg)
    }
    class sip2json_exception:::exceptionClass

    class empty_message_error["siddiqsoft::empty_message_error"]
    class empty_message_error:::exceptionClass
    class incomplete_buffer_for_content_error["siddiqsoft::incomplete_buffer_for_content_error"]
    class incomplete_buffer_for_content_error:::exceptionClass
    class incomplete_buffer_for_header_error["siddiqsoft::incomplete_buffer_for_header_error"]
    class incomplete_buffer_for_header_error:::exceptionClass
    class incomplete_buffer_for_parse_error["siddiqsoft::incomplete_buffer_for_parse_error"]
    class incomplete_buffer_for_parse_error:::exceptionClass
    class invalid_document_error["siddiqsoft::invalid_document_error"]
    class invalid_document_error:::exceptionClass
    class invalid_startline_error["siddiqsoft::invalid_startline_error"]
    class invalid_startline_error:::exceptionClass
    class missing_required_element["siddiqsoft::missing_required_element"]
    class missing_required_element:::exceptionClass
    class unsupported_contenttype_error["siddiqsoft::unsupported_contenttype_error"]
    class unsupported_contenttype_error:::exceptionClass

    json <|-- sipmessage : public inheritance
    runtime_error <|-- sip2json_exception : public inheritance
    sip2json_exception <|-- empty_message_error
    sip2json_exception <|-- incomplete_buffer_for_content_error
    sip2json_exception <|-- incomplete_buffer_for_header_error
    sip2json_exception <|-- incomplete_buffer_for_parse_error
    sip2json_exception <|-- invalid_document_error
    sip2json_exception <|-- invalid_startline_error
    sip2json_exception <|-- missing_required_element
    sip2json_exception <|-- unsupported_contenttype_error

    sip2json ..> sipmessage : produces / consumes
    sip2json ..> sip2json_exception : throws
    sipmessage ..> SIPMessageType : classifies
    sipmessage ..> HeaderKeySet : uses
    sip2json_exception ..> sip2jsonErrors : contains

    link sip2json "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/sip2json.hpp" "Source: include/siddiqsoft/sip2json.hpp"
    link sipmessage "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/sipmessage.hpp" "Source: include/siddiqsoft/sipmessage.hpp"
    link HeaderKeySet "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_header_keys.hpp" "Source: include/siddiqsoft/private/sip2json_header_keys.hpp"
    link sip2json_exception "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link SIPMessageType "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/sipmessage.hpp" "Source: include/siddiqsoft/sipmessage.hpp"
    link sip2jsonErrors "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link empty_message_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link incomplete_buffer_for_content_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link incomplete_buffer_for_header_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link incomplete_buffer_for_parse_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link invalid_document_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link invalid_startline_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link missing_required_element "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link unsupported_contenttype_error "https://github.com/SiddiqSoft/sip2json/blob/master/include/siddiqsoft/private/sip2json_exception.hpp" "Source: include/siddiqsoft/private/sip2json_exception.hpp"
    link json "https://github.com/nlohmann/json" "External: nlohmann/json"
    link runtime_error "https://en.cppreference.com/w/cpp/error/runtime_error" "Standard Library: std::runtime_error"

Source Code Mapping

Component / Class Header File Source Link Purpose & Architectural Role
siddiqsoft::sip2json include/siddiqsoft/sip2json.hpp sip2json.hpp Top-level static parser, stream deserializer, and wire serializer utility
siddiqsoft::sipmessage include/siddiqsoft/sipmessage.hpp sipmessage.hpp Core message container inheriting from nlohmann::json with zero-copy view accessors
siddiqsoft::HeaderKeySet include/siddiqsoft/private/sip2json_header_keys.hpp sip2json_header_keys.hpp Canonical SIP header normalization, compact alias mapping, and compile-time hashing
siddiqsoft::SIPMessageType include/siddiqsoft/sipmessage.hpp sipmessage.hpp Protocol message discriminator (Request = 1, Response = 2)
siddiqsoft::sip2json_exception include/siddiqsoft/private/sip2json_exception.hpp sip2json_exception.hpp Base exception class inheriting from std::runtime_error with sip2jsonErrors payload
siddiqsoft::sip2jsonErrors include/siddiqsoft/private/sip2json_exception.hpp sip2json_exception.hpp Diagnostic error code enumeration for parser and syntax failures
Derived Exceptions include/siddiqsoft/private/sip2json_exception.hpp sip2json_exception.hpp Specialized exception hierarchy (invalid_document_error, empty_message_error, etc.)
Parser Engine (raw_view) include/siddiqsoft/private/sip2json_parser.hpp sip2json_parser.hpp High-throughput streaming parser, zero-copy buffer slicing, CRLF boundary scanning
Wire Serializer include/siddiqsoft/private/sip2json_serializer.hpp sip2json_serializer.hpp RFC 3261 compliant text wire serializer
SDP Body Parser include/siddiqsoft/private/sip2json_sdp.hpp sip2json_sdp.hpp RFC 4566 Session Description Protocol parser and structured JSON serialization
Response Codes include/siddiqsoft/private/sip2json_response_codes.hpp sip2json_response_codes.hpp SIP status codes, reason phrases, and classification ranges (1xx-6xx)
Protocol Constants include/siddiqsoft/private/sip2json_constants.hpp sip2json_constants.hpp SIP grammar tokens, method strings, whitespace matchers, CRLF constants
DateTime Parser include/siddiqsoft/private/sip2json_datetime.hpp sip2json_datetime.hpp RFC 3261 / RFC 1123 HTTP-date timestamp parser and serializer
Utility Functions include/siddiqsoft/private/sip2json_utils.hpp sip2json_utils.hpp Internal whitespace trimming, view slicing, string conversion utilities

Referencing UML Diagrams in Documentation (@@uml-diag: Grammar)

To keep all documentation Markdown files clean, human-editable, and version-controlled, diagrams and tables are never hard-coded or directly pasted as raw Mermaid code blocks. Instead, maintainers embed lightweight, semantic @@uml-diag: or @@uml-diagram: directives.

To ensure 100% Markdown and HTML compatibility (avoiding any GitHub Pages, Jekyll Liquid syntax errors, W3C HTML5 validator warnings, or interference with adjacent Markdown elements), the canonical syntax wraps the directive inside standard HTML comments <!-- @@uml-diagram:... --> or <!-- @@uml-diag:... -->:

Canonical Directive Syntax Alternative Syntax Target Description Example Target
<!-- @@uml-diag:complete --> @@uml-diag:complete Full system UML class diagram System architecture, maintainer guide
<!-- @@uml-diagram:namespace --> @@uml-diagram:namespace Namespace package architecture & boundary diagram Architecture namespace section
<!-- @@uml-diagram:namespace:<name> --> @@uml-diagram:namespace:<name> Specific namespace package (e.g. siddiqsoft) Specific package mapping
<!-- @@uml-diag:<class-name> --> @@uml-diag:<class-name> Targeted class UML diagram (e.g. sip2json, sipmessage, HeaderKeySet) Class reference API pages
<!-- @@uml-diag:class:<class-name> --> @@uml-diag:class:<class-name> Explicit class specifier Class reference API pages
<!-- @@uml-diag:structure --> @@uml-diag:structure Subsystem topology & layered architecture flowchart Subsystem structure overview
<!-- @@uml-diag:control-flow --> @@uml-diag:control-flow Stream parsing linear control-flow sequence diagram Stream mechanics & async parsing
<!-- @@uml-diag:source-table --> @@uml-diag:source-table Source code mapping table with GitHub links Mapping tables
<!-- @@uml-diag:errors --> @@uml-diag:errors Diagnostic exceptions & error code hierarchy Error handling reference

Markdown & HTML Compatibility Guarantees:

  • HTML & CommonMark Compliant: Wrapping in <!-- ... --> represents an isolated HTML block per CommonMark 0.30+ specification, preventing conflicts with Markdown headers, list indentation, tables, or emphasis.
  • GitHub Pages & Jekyll Safe: Unlike template curly braces {{ ... }} which trigger Jekyll Liquid parse errors on GitHub Pages, HTML comments pass through cleanly without causing build failures.
  • Clean Web Repository Browsing: On github.com, HTML comments remain hidden, preventing raw directive text from displaying on unrendered Markdown pages.
  • Flexible Parser: The hook (docs/hooks.py) also supports Markdown invisible link comments [//]: # (@@uml-diag:...), HTML tags <div class="uml-diagram" data-diagram="..."></div>, and bare @@uml-diag:... lines.
  • Automated Clickable Source Links: All generated diagrams automatically include clickable GitHub source links (link ClassName "https://github.com/...").

Source Code Formatting (Clang-Format)

All C++ source code (include/, tests/, and benchmarks/) adheres to the formatting rules defined in .clang-format at the repository root.

The configuration is based on the WebKit style with modern C++20 conventions: * Column Limit: 132 characters * Indentation: 4 spaces (tabs are never used) * Brace Style: WebKit (braces break before functions, classes, and catch/else blocks) * Pointer Alignment: Left (const sipmessage& msg, std::string_view* ptr) * Standard: C++20


How to Bulk Clang-Format the Source Code

Maintainers have multiple ways to format the entire codebase in bulk:

When configured locally, CMake generates a dedicated format (and clang-format) target:

# Format using an active preset build directory:
cmake --build --preset Apple-Clang-Debug --target format

# Or format directly against any existing build folder:
cmake --build build/Apple-Clang-Debug --target format

[!TIP] Automatic Debug Formatting: On non-CI local builds, CMake enables sip2json_ENABLE_CLANG_FORMAT=ON by default in Debug configuration. Formatting runs automatically prior to every local Debug compilation whenever a compatible clang-format executable is detected.


Option 2: Bulk Command-Line via Find (macOS & Linux)

To reformat all C++ header and source files across include/, tests/, and benchmarks/ in one command:

find include tests benchmarks -type f \( -name "*.hpp" -o -name "*.cpp" -o -name "*.h" \) -exec clang-format -i --style=file {} +

To verify formatting without modifying files, pass --dry-run --Werror:

find include tests benchmarks -type f \( -name "*.hpp" -o -name "*.cpp" -o -name "*.h" \) -exec clang-format --dry-run --Werror --style=file {} +

Option 3: Bulk Command-Line via Git (Cross-Platform)

Format all tracked C++ files in the repository using git ls-files:

git ls-files '*.hpp' '*.cpp' '*.h' | xargs clang-format -i --style=file
git ls-files '*.hpp', '*.cpp', '*.h' | ForEach-Object { clang-format -i --style=file $_ }

Option 4: Bulk PowerShell Script (Windows)

On Windows systems without Git bash, run the following PowerShell one-liner:

Get-ChildItem -Path include, tests, benchmarks -Include *.hpp, *.cpp, *.h -Recurse | ForEach-Object {
    clang-format -i --style=file $_.FullName
}

Option 5: Editor & IDE Integration

  • Visual Studio 2022: Visual Studio automatically detects .clang-format at the repository root. Press Ctrl+K, Ctrl+D to format the active document, or Ctrl+K, Ctrl+F to format a selection.
  • Visual Studio Code: Ensure the C/C++ Extension is installed. In .vscode/settings.json:
    {
      "C_Cpp.clang_format_style": "file",
      "editor.formatOnSave": true
    }
    
  • CLion: Navigate to Settings > Editor > Code Style > C/C++ and verify Enable ClangFormat is checked. Press Ctrl+Alt+L (Cmd+Alt+L on macOS) to format.

Maintainer Pre-Flight Checklist

Before submitting a pull request or pushing to master:

  1. Format Code: Run the bulk clang-format command or cmake --build <preset> --target format.
  2. Build Cleanly: Compile with zero compiler warnings using your platform preset:
    cmake --build --preset <preset-name>
    
  3. Execute All Tests: Ensure 100% of tests pass:
    ctest --preset <preset-name> --output-on-failure
    
  4. Validate Documentation: Verify zero broken links or markdown syntax errors:
    mkdocs build --strict
    
  5. Major Version Updates: When introducing breaking API changes or preparing a major version release, manually update the next-version: entry in GitVersion.yml (e.g. next-version: 4.0.0) so GitVersion establishes the new major version baseline.