Interface for types that can provide C2PA context functionality.
This interface can be implemented by external libraries to provide custom context implementations (e.g. AdobeContext wrappers). Reader and Builder take the context by reference and use it only at construction; the underlying implementation copies context state into the reader/builder, so the context does not need to outlive them.
- Move semantics
- Move construction and move assignment are defaulted. After move, the moved-from object is left in a valid but unspecified state: is_valid() may be false and c_context() may return nullptr. Implementations that own a C2paContext* (e.g. Context) must set the source's handle to nullptr on move to avoid double-free; callers must not use a moved-from provider without checking is_valid() first.
- Implementation Requirements for is_valid()
- The is_valid() method exists to support implementations that may have:
- Optional or lazy context initialization
- Contexts that can be invalidated or moved
- A "no context" state as part of their lifecycle
- Why Both c_context() and is_valid()?
- While c_context() can return nullptr, is_valid() provides:
- A boolean check without pointer inspection (yes/no answer for intialization)
- Forward compatibility for implementations with complex context lifecycles (lazy load)
- Impact on Reader and Builder
- Reader and Builder constructors validate that a provider both exists and is_valid() returns true before using c_context(). This ensures that:
- External implementations cannot be used in an uninitialized state
- A consistent validation pattern exists across all context-using classes
- Errors are caught early at construction time rather than during operations
- Standard Context Implementation
- The built-in Context class always returns true from is_valid() after successful construction, as it validates the context pointer in its constructor. External implementations may have different invariants.