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 |
Top-level static parser, stream deserializer, and wire serializer utility |
siddiqsoft::sipmessage |
include/siddiqsoft/ |
sipmessage.hpp |
Core message container inheriting from nlohmann::json with zero-copy view accessors |
siddiqsoft::HeaderKeySet |
include/siddiqsoft/private/ |
sip2json_header_keys.hpp |
Canonical SIP header normalization, compact alias mapping, and compile-time hashing |
siddiqsoft::SIPMessageType |
include/siddiqsoft/ |
sipmessage.hpp |
Protocol message discriminator (Request = 1, Response = 2) |
siddiqsoft::sip2json_exception |
include/siddiqsoft/private/ |
sip2json_exception.hpp |
Base exception class inheriting from std::runtime_error with sip2jsonErrors payload |
siddiqsoft::sip2jsonErrors |
include/siddiqsoft/private/ |
sip2json_exception.hpp |
Diagnostic error code enumeration for parser and syntax failures |
| Derived Exceptions | include/siddiqsoft/private/ |
sip2json_exception.hpp |
Specialized exception hierarchy (invalid_document_error, empty_message_error, etc.) |
Parser Engine (raw_view) |
include/siddiqsoft/private/ |
sip2json_parser.hpp |
High-throughput streaming parser, zero-copy buffer slicing, CRLF boundary scanning |
| Wire Serializer | include/siddiqsoft/private/ |
sip2json_serializer.hpp |
RFC 3261 compliant text wire serializer |
| SDP Body Parser | include/siddiqsoft/private/ |
sip2json_sdp.hpp |
RFC 4566 Session Description Protocol parser and structured JSON serialization |
| Response Codes | include/siddiqsoft/private/ |
sip2json_response_codes.hpp |
SIP status codes, reason phrases, and classification ranges (1xx-6xx) |
| Protocol Constants | include/siddiqsoft/private/ |
sip2json_constants.hpp |
SIP grammar tokens, method strings, whitespace matchers, CRLF constants |
| DateTime Parser | include/siddiqsoft/private/ |
sip2json_datetime.hpp |
RFC 3261 / RFC 1123 HTTP-date timestamp parser and serializer |
| Utility Functions | include/siddiqsoft/private/ |
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/) also supports Markdown invisible link commentshooks.py [//]: # (@@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:
Option 1: Via CMake Build Target (Recommended)¶
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=ONby default inDebugconfiguration. Formatting runs automatically prior to every local Debug compilation whenever a compatibleclang-formatexecutable 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:
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-formatat the repository root. PressCtrl+K, Ctrl+Dto format the active document, orCtrl+K, Ctrl+Fto format a selection. - Visual Studio Code: Ensure the C/C++ Extension is installed. In
.vscode/:settings.json - CLion: Navigate to Settings > Editor > Code Style > C/C++ and verify Enable ClangFormat is checked. Press
Ctrl+Alt+L(Cmd+Alt+Lon macOS) to format.
Maintainer Pre-Flight Checklist¶
Before submitting a pull request or pushing to master:
- Format Code: Run the bulk clang-format command or
cmake --build <preset> --target format. - Build Cleanly: Compile with zero compiler warnings using your platform preset:
- Execute All Tests: Ensure 100% of tests pass:
- Validate Documentation: Verify zero broken links or markdown syntax errors:
- Major Version Updates: When introducing breaking API changes or preparing a major version release, manually update the
next-version:entry inGitVersion.yml(e.g.next-version: 4.0.0) so GitVersion establishes the new major version baseline.