c2pa-cpp
C++ API for the C2PA SDK
Loading...
Searching...
No Matches
c2pa.hpp
Go to the documentation of this file.
1// Copyright 2024 Adobe. All rights reserved.
2// This file is licensed to you under the Apache License,
3// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4// or the MIT license (http://opensource.org/licenses/MIT),
5// at your option.
6// Unless required by applicable law or agreed to in writing,
7// this software is distributed on an "AS IS" BASIS, WITHOUT
8// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
9// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
10// specific language governing permissions and limitations under
11// each license.
12
13/// @file c2pa.hpp
14/// @brief C++ wrapper for the C2PA C library.
15/// @details This is used for creating and verifying C2PA manifests.
16/// This is an early version, and has not been fully tested.
17/// Thread safety is not guaranteed due to the use of errno and etc.
18
19#ifndef C2PA_H
20#define C2PA_H
21
22// Suppress unused function warning for GCC/Clang
23#ifdef __GNUC__
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wunused-function"
26#endif
27
28// Suppress unused function warning for MSVC
29#ifdef _MSC_VER
30#pragma warning(push)
31#pragma warning(disable : 4505)
32#endif
33
34#include <cerrno>
35#include <filesystem>
36#include <fstream>
37#include <functional>
38#include <istream>
39#include <ostream>
40#include <string>
41#include <vector>
42#include <optional>
43#include <memory>
44#include <utility>
45
46#include "c2pa.h"
47
48// NOOP for now, can use later to define static library
49#define C2PA_CPP_API
50
51namespace c2pa
52{
53 /// @typedef SignerInfo
54 /// @brief Type alias for C2paSignerInfo from the C API.
55 typedef C2paSignerInfo SignerInfo;
56
57 // Forward declarations for context types
58 class Settings;
59 class Context;
60 class IContextProvider;
61 class Signer;
62
63 /// @brief Result codes for C API operations (matches C API return convention).
64 enum class OperationResult : int {
65 Success = 0, ///< Operation succeeded
66 Error = -1 ///< Operation failed (check C2paException for details)
67 };
68
69 /// @brief Stream/FFI error codes (maps to errno values used by the C layer).
70 enum class StreamError : int {
71 InvalidArgument = EINVAL,
72 IoError = EIO,
73 NoBufferSpace = ENOBUFS
74 };
75
76 /// @brief Set errno from StreamError and return error sentinel.
77 /// @param e The StreamError value to convert to errno.
78 /// @return OperationResult::Error (-1) for use as C API error return.
79 inline int stream_error_return(StreamError e) noexcept {
80 errno = static_cast<int>(e);
81 return static_cast<int>(OperationResult::Error);
82 }
83
84 /// @brief Exception class for C2pa errors.
85 /// This class is used to throw exceptions for errors encountered by the C2pa library via c2pa_error().
86 class C2PA_CPP_API C2paException : public std::exception
87 {
88 public:
89 /// @brief Default constructor.
90 /// @details Creates an exception and retrieves the error message from the C2PA library.
92
93 /// @brief Construct an exception with a custom error message.
94 /// @param message The error message.
95 explicit C2paException(std::string message);
96
97 ~C2paException() override = default;
98
99 C2paException(const C2paException&) = default;
100
102
104
106
107 /// @brief Get the exception message.
108 /// @return Null-terminated error message string.
109 const char* what() const noexcept override;
110
111 private:
112 std::string message_;
113 };
114
115 /// @brief Interface for types that can provide C2PA context functionality.
116 /// @details This interface can be implemented by external libraries to provide
117 /// custom context implementations (e.g. AdobeContext wrappers).
118 /// Reader and Builder accept a shared_ptr<IContextProvider> and extend
119 /// the provider's lifetime for as long as the Reader/Builder exists.
120 ///
121 /// @par Progress callback lifetime (post-0322d67)
122 /// If the native C2paContext* held by the provider was configured with a progress
123 /// callback, the provider MUST keep the heap-owned ProgressCallbackFunc alive at
124 /// least as long as the native context. The native side stores only a raw pointer
125 /// into that heap block and will call it until the context is freed. Destroy
126 /// order inside the provider: free the native C2paContext* first (stops further
127 /// callback invocations), then release the callback storage. The built-in
128 /// Context class enforces this via member declaration order; external providers
129 /// that adopt a native context built via ContextBuilder::release() must do the
130 /// same.
131 ///
132 /// @par Move semantics
133 /// Move construction and move assignment are defaulted. After move, the moved-from
134 /// object is left in a valid but unspecified state: is_valid() may be false and
135 /// c_context() may return nullptr. Implementations that own a C2paContext* (e.g. Context)
136 /// must set the source's handle to nullptr on move to avoid double-free; callers must
137 /// not use a moved-from provider without checking is_valid() first.
138 ///
139 /// @par Implementation Requirements for is_valid()
140 /// The is_valid() method exists to support implementations that may have:
141 /// - Optional or lazy context initialization
142 /// - Contexts that can be invalidated or moved
143 /// - A "no context" state as part of their lifecycle
144 ///
145 /// @par Why Both c_context() and is_valid()?
146 /// While c_context() can return nullptr, is_valid() provides:
147 /// 1. A boolean check without pointer inspection (yes/no answer for intialization)
148 /// 2. Forward compatibility for implementations with complex context lifecycles (lazy load)
149 ///
150 /// @par Impact on Reader and Builder
151 /// Reader and Builder constructors validate that a provider both exists and
152 /// is_valid() returns true before using c_context(). This ensures that:
153 /// - External implementations cannot be used in an uninitialized state
154 /// - A consistent validation pattern exists across all context-using classes
155 /// - Errors are caught early at construction time rather than during operations
156 ///
157 /// @par Standard Context Implementation
158 /// The built-in Context class always returns true from is_valid() after
159 /// successful construction, as it validates the context pointer in its constructor.
160 /// External implementations may have different invariants.
162 public:
163 virtual ~IContextProvider() noexcept = default;
164
165 /// @brief Get the underlying C2PA context pointer for FFI operations.
166 /// @return Pointer to C2paContext, or nullptr if not available.
167 /// @note Provider retains ownership; pointer valid for provider's lifetime.
168 [[nodiscard]] virtual C2paContext* c_context() const noexcept = 0;
169
170 /// @brief Check if this provider has a valid context.
171 /// @return true if context is available, false otherwise.
172 /// @note For standard Context objects, this always returns true after construction.
173 /// External implementations may return false to indicate uninitialized or
174 /// invalidated state. Reader and Builder constructors check this before use.
175 /// @warning Implementations must ensure is_valid() == true implies c_context() != nullptr.
176 [[nodiscard]] virtual bool is_valid() const noexcept = 0;
177
178 protected:
179 IContextProvider() = default;
180
182 IContextProvider& operator=(const IContextProvider&) = delete;
183 };
184
185 /// @brief (C2PA SDK) Settings configuration object for creating contexts.
186 /// @details Settings can be configured via JSON strings or programmatically
187 /// via set() and update() methods. Once passed to Context::ContextBuilder,
188 /// the settings are copied into the context and the Settings
189 /// object can be reused or discarded.
190 ///
191 /// @par Validity
192 /// Settings uses is_valid() to indicate whether the object holds a valid underlying
193 /// C settings handle. After move-from, is_valid() is false. set(), update(), and callers
194 /// passing this object to the C API must ensure is_valid() is true or check before use.
196 public:
197 /// @brief Create default settings.
199
200 /// @brief Create settings from a configuration string.
201 /// @param data Configuration data in JSON format.
202 /// @param format Format of the data ("json").
203 /// @throws C2paException if parsing fails.
204 Settings(const std::string& data, const std::string& format);
205
206 // Move semantics
207 Settings(Settings&&) noexcept;
208 Settings& operator=(Settings&&) noexcept;
209
210 // Non-copyable
211 Settings(const Settings&) = delete;
212 Settings& operator=(const Settings&) = delete;
213
214 ~Settings() noexcept;
215
216 /// @brief Check if this Settings object is valid (holds a C settings handle).
217 /// @return true if the object can be used (set, update, c_settings, or passed to Context/ContextBuilder).
218 /// @return false if moved-from (or otherwise invalid). Callers must check before use.
219 [[nodiscard]] bool is_valid() const noexcept;
220
221 /// @brief Set a single configuration value by path.
222 /// @param path Dot-separated path to the setting (e.g., "verify.verify_after_sign").
223 /// @param json_value JSON-encoded value to set.
224 /// @return Reference to this Settings for method chaining.
225 /// @throws C2paException if the path or value is invalid.
226 Settings& set(const std::string& path, const std::string& json_value);
227
228 /// @brief Merge configuration from a JSON string (latest configuration wins).
229 /// @param data Configuration data in JSON format.
230 /// @return Reference to this Settings for method chaining.
231 /// @throws C2paException if parsing fails, or if this object is invalid.
232 /// @note This is the recommended overload when configuration is JSON.
233 Settings& update(const std::string& data) { return update(data, "json"); }
234
235 /// @brief Merge configuration from a std::string (latest configuration wins).
236 /// @param data Configuration data in JSON or TOML format.
237 /// @param format Format of the data ("json" or "toml").
238 /// @return Reference to this Settings for method chaining.
239 /// @throws C2paException if parsing fails, or if this object is invalid.
240 Settings& update(const std::string& data, const std::string& format);
241
242 /// @brief Get the raw C FFI settings pointer.
243 /// @return Pointer to C2paSettings when is_valid() is true; nullptr when invalid.
244 /// @note Callers passing this to the C API should check is_valid() first and treat nullptr as invalid.
245 [[nodiscard]] C2paSettings* c_settings() const noexcept;
246
247 private:
248 C2paSettings* settings_ptr;
249 };
250
251 /// @brief Phase values reported to the ProgressCallbackFunc.
252 ///
253 /// @details A scoped C++ mirror of `C2paProgressPhase` from c2pa.h.
254 /// Values are verified at compile time to match the C enum, so any
255 /// future divergence in c2pa-rs will be caught as a build error.
256 ///
257 /// Phases emitted during a typical sign cycle (in order):
258 /// AddingIngredient → Thumbnail → Hashing → Signing → Embedding →
259 /// (if verify_after_sign) VerifyingManifest → VerifyingSignature →
260 /// VerifyingAssetHash → VerifyingIngredient
261 ///
262 /// Phases emitted during reading:
263 /// Reading → VerifyingManifest → VerifyingSignature →
264 /// VerifyingAssetHash → VerifyingIngredient
265 enum class ProgressPhase : uint8_t {
266 Reading = 0,
272 Thumbnail = 6,
273 Hashing = 7,
274 Signing = 8,
275 Embedding = 9,
277 Writing = 11,
278 FetchingOCSP = 12,
280 };
281
282 /// @brief Type alias for the progress callback passed to ContextBuilder::with_progress_callback().
283 ///
284 /// @details The callback is invoked at each major phase of signing and reading operations.
285 /// Returning false from the callback aborts the operation with an
286 /// OperationCancelled error (equivalent to calling Context::cancel()).
287 ///
288 /// @param phase Current operation phase.
289 /// @param step 1-based step index within the phase.
290 /// 0 = indeterminate (use as liveness signal); resets to 1 at each new phase.
291 /// @param total 0 = indeterminate; 1 = single-shot; >1 = determinate (step/total = fraction).
292 /// @return true to continue the operation, false to request cancellation.
293 ///
294 /// @note The callback must not throw. If it throws, the implementation catches the
295 /// exception and reports cancellation to the underlying library (same as returning
296 /// false); the original exception is not propagated. Prefer returning false or
297 /// using Context::cancel() instead of throwing.
298 ///
299 using ProgressCallbackFunc = std::function<bool(ProgressPhase phase, uint32_t step, uint32_t total)>;
300
301 /// @brief C2PA context implementing IContextProvider.
302 /// @details Context objects manage C2PA SDK configuration and state.
303 /// Contexts can be created via direct construction or the ContextBuilder:
304 ///
305 /// Direct construction:
306 /// @code
307 /// c2pa::Context ctx; // default
308 /// c2pa::Context ctx(settings); // from Settings
309 /// c2pa::Context ctx(json); // from JSON string
310 /// @endcode
311 ///
312 /// ContextBuilder (for multi-step configuration):
313 /// @code
314 /// auto ctx = c2pa::Context::ContextBuilder()
315 /// .with_settings(settings)
316 /// .with_json(json)
317 /// .create_context();
318 /// @endcode
319 ///
320 /// Builder and Reader take the context by reference (IContextProvider&).
321 /// The context object must outlive the Builder or Reader instance.
323 public:
324 /// @brief ContextBuilder for creating customized Context instances.
325 /// @details Provides a builder pattern for configuring contexts with multiple settings.
326 /// Note: create_context() consumes the builder.
327 /// @note For most use cases, prefer direct construction via the Context constructors.
328 /// The ContextBuilder is useful when you need to layer multiple configuration
329 /// sources (e.g. with_settings() followed by with_json()).
331 public:
333 ~ContextBuilder() noexcept;
334
335 // Move semantics
337 ContextBuilder& operator=(ContextBuilder&&) noexcept;
338
339 // Non-copyable
341 ContextBuilder& operator=(const ContextBuilder&) = delete;
342
343 /// @brief Check if the builder is in a valid state.
344 /// @return true if the builder can be used, false if moved from.
345 [[nodiscard]] bool is_valid() const noexcept;
346
347 /// @brief Configure with Settings object.
348 /// @param settings Settings to use (will be copied into the context). Must be valid (is_valid() true).
349 /// @return Reference to this ContextBuilder for method chaining.
350 /// @throws C2paException if settings are invalid or settings.is_valid() is false.
351 ContextBuilder& with_settings(const Settings& settings);
352
353 /// @brief Configure settings with JSON string.
354 /// @param json JSON configuration string.
355 /// @return Reference to this ContextBuilder for method chaining.
356 /// @throws C2paException if JSON is invalid.
357 ContextBuilder& with_json(const std::string& json);
358
359 /// @brief Configure settings from a JSON settings file.
360 /// @param settings_path Full path to the JSON settings file.
361 /// @return Reference to this ContextBuilder for method chaining.
362 /// @throws C2paException if file cannot be read or JSON is invalid.
363 ContextBuilder& with_json_settings_file(const std::filesystem::path& settings_path);
364
365 /// @brief Set a Signer on the context being built.
366 /// @details After this call the source Signer object is consumed and must
367 /// not be reused, as it becomes part to the context and tied to it.
368 /// If settings also contain a signer, the programmatic signer
369 /// set through this API will be used for signing.
370 /// @param signer Signer to put into the context.
371 /// @return Reference to this ContextBuilder for method chaining.
372 /// @throws C2paException if the builder or signer is invalid.
373 ContextBuilder& with_signer(Signer&& signer);
374
375 /// @brief Attach a progress callback to the context being built.
376 ///
377 /// @details The callback is invoked at each major phase of signing and
378 /// reading operations performed with the resulting context.
379 /// Return false from the callback to abort the current operation
380 /// with an OperationCancelled error.
381 ///
382 /// Phases emitted during a typical sign cycle (in order):
383 /// VerifyingIngredient → VerifyingManifest → VerifyingSignature →
384 /// VerifyingAssetHash → Thumbnail → Hashing → Signing → Embedding →
385 /// (if verify_after_sign) VerifyingManifest → … → VerifyingIngredient
386 ///
387 /// Phases emitted during reading:
388 /// Reading → VerifyingManifest → VerifyingSignature →
389 /// VerifyingAssetHash → VerifyingIngredient
390 ///
391 /// @param callback A callable matching ProgressCallbackFunc. The callback is
392 /// heap-allocated and owned by the resulting Context. Calling this method
393 /// more than once on the same builder replaces the previous callback.
394 /// The callable must not throw when invoked (see ProgressCallbackFunc).
395 /// @return Reference to this ContextBuilder for method chaining.
396 /// @throws C2paException if the builder is invalid or the C API call fails.
397 ///
398 ContextBuilder& with_progress_callback(ProgressCallbackFunc callback);
399
400 /// @brief Set a custom HTTP resolver callback on the context being built.
401 /// @details The callback is invoked synchronously whenever the SDK needs to
402 /// make an HTTP request (remote manifest fetch, OCSP, timestamp, etc.).
403 /// The callback receives a C2paHttpRequest and must fill in a C2paHttpResponse.
404 /// The response body must be allocated with malloc(); the underlying native library will call free().
405 /// @param user_data Opaque user pointer passed to every callback invocation (may be nullptr).
406 /// @param callback Function pointer matching C2paHttpResolverCallback.
407 /// @return Reference to this ContextBuilder for method chaining.
408 /// @throws C2paException if the resolver could not be set or callback is null.
409 ContextBuilder& with_http_resolver(void* user_data, C2paHttpResolverCallback callback);
410
411 /// @brief Create a Context from the current builder configuration.
412 /// @return A new Context instance.
413 /// @throws C2paException if context creation fails.
414 /// @note This consumes the builder. After calling this, is_valid() returns false.
415 [[nodiscard]] Context create_context();
416
417 /// @brief Result of ContextBuilder::release(): the raw native builder handle
418 /// paired with the heap-owned progress callback (if any).
419 /// @details The caller takes joint ownership. If `callback_owner` is non-null,
420 /// the native side stores a raw pointer into it and will invoke the
421 /// callback until the native context built from `builder` is freed.
422 /// Therefore `callback_owner` must remain alive at least until the
423 /// native context returned by c2pa_context_builder_build(builder) is
424 /// freed via c2pa_free(). Release order: native context first, then
425 /// `callback_owner` goes out of scope.
427 C2paContextBuilder* builder;
428 std::unique_ptr<ProgressCallbackFunc> callback_owner;
429 };
430
431 /// @brief Release ownership of the underlying C2paContextBuilder handle and
432 /// its progress-callback heap block (if any) to the caller.
433 /// @details After this call is_valid() returns false. The previous
434 /// C2paContextBuilder* overload was unsound when a progress callback
435 /// was pending: the C++ builder destructor would free the heap
436 /// ProgressCallbackFunc while the native side still held its pointer,
437 /// yielding a use-after-free on the first progress tick.
438 /// Callers must keep ReleasedBuilder::callback_owner alive for as
439 /// long as the native context built from ReleasedBuilder::builder
440 /// exists.
441 /// @return ReleasedBuilder holding both the native builder and (optionally)
442 /// the owning unique_ptr for the progress callback. Fields are null
443 /// when moved-from.
444 [[nodiscard]] ReleasedBuilder release() noexcept;
445
446 private:
447 // pending_callback_ is declared before context_builder
448 // so destruction (reverse of declaration) frees context_builder first, while
449 // the callback heap block is still live, then releases pending_callback_.
450 std::unique_ptr<ProgressCallbackFunc> pending_callback_;
451 C2paContextBuilder* context_builder;
452 };
453
454 // Direct construction
455 /// @brief Create a Context with default settings.
456 /// @throws C2paException if context creation fails.
458
459 /// @brief Create a Context configured with a Settings object.
460 /// @param settings Settings configuration to apply. Must be valid (settings.is_valid() true).
461 /// @throws C2paException if settings are invalid, settings.is_valid() is false, or context creation fails.
462 explicit Context(const Settings& settings);
463
464 /// @brief Create a Context configured with a JSON string.
465 /// @param json JSON configuration string.
466 /// @throws C2paException if JSON is invalid or context creation fails.
467 explicit Context(const std::string& json);
468
469 /// @brief Create a Context with a Settings object and a Signer.
470 /// @param settings Settings configuration to apply.
471 /// @param signer Signer to move into the context. Consumed after this call.
472 /// The programmatic Signer from the signer parameter
473 /// takes priority over the Signer in settings, so use this API
474 /// when wanting to explicitly set a Signer (or override the Signer in settings).
475 /// @throws C2paException if settings or signer are invalid, or context creation fails.
476 Context(const Settings& settings, Signer&& signer);
477
478 // Non-copyable, moveable
479 Context(const Context&) = delete;
480 Context& operator=(const Context&) = delete;
481 Context(Context&&) noexcept;
482 Context& operator=(Context&&) noexcept;
483
484 ~Context() noexcept override;
485
486 // IContextProvider implementation
487 /// @brief Get the underlying C2PA context pointer.
488 /// @return C2paContext pointer when is_valid() is true; nullptr when moved-from (is_valid() false).
489 /// @note Callers must check is_valid() before using the result; do not pass nullptr to the C API.
490 [[nodiscard]] C2paContext* c_context() const noexcept override;
491
492 /// @brief Check if this Context has a valid context (validity check for context-like types).
493 /// @return true when the object holds a valid C context; false when moved-from.
494 /// @note After move, is_valid() is false and c_context() returns nullptr.
495 [[nodiscard]] bool is_valid() const noexcept override;
496
497 /// @brief Internal constructor from raw FFI pointer (prefer public constructors).
498 /// @param ctx Raw C2paContext pointer — Context takes ownership.
499 /// @throws C2paException if ctx is nullptr.
500 explicit Context(C2paContext* ctx);
501
502 /// @brief "Adopt" a native context together with its heap-owned progress callback.
503 /// @param ctx Native context pointer. Context takes ownership.
504 /// @param callback Heap-owned progress callback whose raw pointer the native
505 /// context may hold. May be null.
506 Context(C2paContext* ctx,
507 std::unique_ptr<ProgressCallbackFunc> callback) noexcept;
508
509 /// @brief Request cancellation of any in-progress operation on this context.
510 ///
511 /// @details Safe to call from another thread while this Context remains valid
512 /// and is not being destroyed or moved concurrently with this call.
513 /// While a signing or reading operation is running on a valid Context,
514 /// the operation is aborted with an OperationCancelled error at the
515 /// next progress checkpoint. Has no effect if no operation is currently
516 /// in progress, or if this object is moved-from (is_valid() is false).
517 ///
518 void cancel() noexcept;
519
520 private:
521 // Member order matters: `context` is declared before `callback_owner_` so
522 // destruction (reverse of declaration) frees the heap callback block after
523 // the native context has been freed.
524 C2paContext* context;
525
526 /// Heap-owned ProgressCallbackFunc, non-null only when the Context was built
527 /// with a progress callback via ContextBuilder::with_progress_callback().
528 /// Destroyed after `context`.
529 std::unique_ptr<ProgressCallbackFunc> callback_owner_;
530 };
531
532 /// @brief Get the version of the C2PA library.
533 /// @return Version string.
534 std::string C2PA_CPP_API version();
535
536 /// @brief Load C2PA settings from a string in a given format.
537 /// @param data The configuration data to load.
538 /// @param format The mimetype of the string.
539 /// @throws C2paException for errors encountered by the C2PA library.
540 /// @deprecated Use Context constructors or Context::ContextBuilder instead for better thread safety.
541 [[deprecated("Use Context::from_json() or Context::from_settings() instead")]]
542 void C2PA_CPP_API load_settings(const std::string& data, const std::string& format);
543
544 /// @defgroup StreamWrappers Stream wrappers for C2PA C API
545 /// @brief C++ stream types that adapt stream types to C2paStream.
546 ///
547 /// The C2PA C API expects a C2paStream with four callbacks: reader, writer, seeker, flusher.
548 /// The contract for each callback is:
549 /// - reader(context, buffer, size): read up to size bytes into buffer; return bytes read, or -1 on error (set errno).
550 /// - writer(context, buffer, size): write size bytes from buffer; return bytes written, or -1 on error (set errno).
551 /// - seeker(context, offset, whence): seek to offset (whence = Start/Current/End); return new position or -1 (set errno).
552 /// - flusher(context): flush; return 0 on success, -1 on error (set errno).
553
554 /// @brief Input stream IStream wrapper for C2paStream.
555 /// @details This class is used to wrap an input stream for use with the C2PA library.
556 class C2PA_CPP_API CppIStream : public C2paStream
557 {
558 public:
559 /// @brief Pointer to the underlying C2paStream.
560 C2paStream *c_stream;
561
562 /// @brief Construct an input stream wrapper from a std::istream-derived object.
563 /// @tparam IStream Type derived from std::istream.
564 /// @param istream The input stream to wrap (must be open and valid).
565 /// @throws C2paException if stream wrapper creation fails.
566 template <typename IStream>
567 explicit CppIStream(IStream &istream) {
568 static_assert(std::is_base_of<std::istream, IStream>::value,
569 "Stream must be derived from std::istream");
570 // Upcast to std::istream* before type erasure; the callbacks cast the context back to std::istream*
571 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(static_cast<std::istream *>(&istream)), reader, seeker, writer, flusher);
572 if (c_stream == nullptr) {
573 throw C2paException("Failed to create input stream wrapper: is stream open and valid?");
574 }
575 }
576
577 CppIStream(const CppIStream &) = delete;
578
579 CppIStream &operator=(const CppIStream &) = delete;
580
581 CppIStream(CppIStream &&) = delete;
582
584
586
587 private:
588 /// @brief Reader callback implementation.
589 /// @param context Stream context pointer.
590 /// @param buffer Buffer to read into.
591 /// @param size Number of bytes to read.
592 /// @return Number of bytes read, or -1 on error (sets errno).
593 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
594
595 /// @brief Writer callback implementation (not used for input streams).
596 /// @param context Stream context pointer.
597 /// @param buffer Buffer to write from.
598 /// @param size Number of bytes to write.
599 /// @return -1 (always fails for input streams).
600 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
601
602 /// @brief Seeker callback implementation.
603 /// @param context Stream context pointer.
604 /// @param offset Offset to seek to.
605 /// @param whence Seek mode (Start/Current/End).
606 /// @return New stream position, or -1 on error (sets errno).
607 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
608
609 /// @brief Flusher callback implementation (no-op for input streams).
610 /// @param context Stream context pointer.
611 /// @return 0 on success.
612 static intptr_t flusher(StreamContext *context);
613
614 friend class Reader;
615 };
616
617 /// @brief Output stream OStream wrapper for C2paStream.
618 /// @details This class is used to wrap an output stream for use with the C2PA library.
619 class C2PA_CPP_API CppOStream : public C2paStream
620 {
621 public:
622 /// @brief Pointer to the underlying C2paStream.
623 C2paStream *c_stream;
624
625 /// @brief Construct an output stream wrapper from a std::ostream-derived object.
626 /// @tparam OStream Type derived from std::ostream.
627 /// @param ostream The output stream to wrap (must be open and valid).
628 /// @throws C2paException if stream wrapper creation fails.
629 template <typename OStream>
630 explicit CppOStream(OStream &ostream) {
631 static_assert(std::is_base_of<std::ostream, OStream>::value, "Stream must be derived from std::ostream");
632 // Upcast to std::ostream* before type erasure; the callbacks cast the context back to std::ostream*
633 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(static_cast<std::ostream *>(&ostream)), reader, seeker, writer, flusher);
634 if (c_stream == nullptr) {
635 throw C2paException("Failed to create output stream wrapper: is stream open and valid?");
636 }
637 }
638
639 CppOStream(const CppOStream &) = delete;
640
641 CppOStream &operator=(const CppOStream &) = delete;
642
643 CppOStream(CppOStream &&) = delete;
644
646
648
649 private:
650 /// @brief Reader callback implementation (not used for output streams).
651 /// @param context Stream context pointer.
652 /// @param buffer Buffer to read into.
653 /// @param size Number of bytes to read.
654 /// @return -1 (always fails for output streams).
655 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
656
657 /// @brief Writer callback implementation.
658 /// @param context Stream context pointer.
659 /// @param buffer Buffer to write from.
660 /// @param size Number of bytes to write.
661 /// @return Number of bytes written, or -1 on error (sets errno).
662 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
663
664 /// @brief Seeker callback implementation.
665 /// @param context Stream context pointer.
666 /// @param offset Offset to seek to.
667 /// @param whence Seek mode (Start/Current/End).
668 /// @return New stream position, or -1 on error (sets errno).
669 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
670
671 /// @brief Flusher callback implementation.
672 /// @param context Stream context pointer.
673 /// @return 0 on success, -1 on error (sets errno).
674 static intptr_t flusher(StreamContext *context);
675 };
676
677 /// @brief IOStream Class wrapper for C2paStream.
678 /// @details This class is used to wrap an input/output stream for use with the C2PA library.
679 class C2PA_CPP_API CppIOStream : public C2paStream
680 {
681 public:
682 /// @brief Pointer to the underlying C2paStream.
683 C2paStream *c_stream;
684
685 /// @brief Construct an I/O stream wrapper from a std::iostream-derived object.
686 /// @tparam IOStream Type derived from std::iostream.
687 /// @param iostream The I/O stream to wrap (must be open and valid).
688 /// @throws C2paException if stream wrapper creation fails.
689 template <typename IOStream>
690 CppIOStream(IOStream &iostream) {
691 static_assert(std::is_base_of<std::iostream, IOStream>::value, "Stream must be derived from std::iostream");
692 // Upcast to std::iostream* before type erasure; the callbacks cast the context back to std::iostream*
693 c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(static_cast<std::iostream *>(&iostream)), reader, seeker, writer, flusher);
694 if (c_stream == nullptr) {
695 throw C2paException("Failed to create I/O stream wrapper: is stream open and valid?");
696 }
697 }
698
699 CppIOStream(const CppIOStream &) = delete;
700
702
704
706
708
709 private:
710 /// @brief Reader callback implementation.
711 /// @param context Stream context pointer.
712 /// @param buffer Buffer to read into.
713 /// @param size Number of bytes to read.
714 /// @return Number of bytes read, or -1 on error (sets errno).
715 static intptr_t reader(StreamContext *context, uint8_t *buffer, intptr_t size);
716
717 /// @brief Writer callback implementation.
718 /// @param context Stream context pointer.
719 /// @param buffer Buffer to write from.
720 /// @param size Number of bytes to write.
721 /// @return Number of bytes written, or -1 on error (sets errno).
722 static intptr_t writer(StreamContext *context, const uint8_t *buffer, intptr_t size);
723
724 /// @brief Seeker callback implementation.
725 /// @param context Stream context pointer.
726 /// @param offset Offset to seek to.
727 /// @param whence Seek mode (Start/Current/End).
728 /// @return New stream position, or -1 on error (sets errno).
729 static intptr_t seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence);
730
731 /// @brief Flusher callback implementation.
732 /// @param context Stream context pointer.
733 /// @return 0 on success, -1 on error (sets errno).
734 static intptr_t flusher(StreamContext *context);
735 };
736
737 /// @brief Reader class for reading a manifest.
738 /// @details This class is used to read and validate a manifest from a stream or file.
739 /// Resources are managed using RAII; member order ensures cpp_stream (which
740 /// holds a C stream pointing at the ifstream) is destroyed before owned_stream.
742 {
743 private:
744 C2paReader *c2pa_reader;
745 std::unique_ptr<std::ifstream> owned_stream; // Owns file stream when created from path
746 std::unique_ptr<CppIStream> cpp_stream; // Wraps stream for C API; destroyed before owned_stream
747 std::shared_ptr<IContextProvider> context_ref;
748
749 void init_from_context(IContextProvider& context, const std::string &format, std::istream &stream);
750 void init_from_context(IContextProvider& context, const std::filesystem::path &source_path);
751 void init_from_manifest_data_and_stream(IContextProvider& context,
752 const std::string& format,
753 std::istream& image_stream,
754 const std::vector<uint8_t>& manifest_jumbf);
755
756 /// @brief Throw if the Reader holds no valid native handle.
757 void ensure_initialized() const {
758 if (c2pa_reader == nullptr) {
759 throw C2paException("Reader is not initialized");
760 }
761 }
762
763 Reader() : c2pa_reader(nullptr) {}
764
765 public:
766 /// @brief Create a Reader from a context and stream.
767 /// @param context Context provider; used at construction to configure settings.
768 /// @param format The mime format of the stream.
769 /// @param stream The input stream to read from.
770 /// @throws C2paException if context.is_valid() returns false,
771 /// or for other errors encountered by the C2PA library.
772 /// @deprecated Use Reader(std::shared_ptr<IContextProvider>, format, stream) instead.
773 /// The reference overload does not extend the lifetime of the context, which can
774 /// be problematic when progress callbacks fire after the context is destroyed.
775 [[deprecated("Use Reader(std::shared_ptr<IContextProvider>, format, stream) instead. "
776 "The reference overload does not extend the lifetime of the context, which can "
777 "be problematic when progress callbacks fire after the context is destroyed.")]]
778 Reader(IContextProvider& context, const std::string &format, std::istream &stream);
779
780 /// @brief Create a Reader from a context and file path.
781 /// @param context Context provider; used at construction only to configure settings.
782 /// @param source_path The path to the file to read.
783 /// @throws C2paException if context.is_valid() returns false,
784 /// or for other errors encountered by the C2PA library.
785 /// @note Prefer using the streaming APIs if possible.
786 /// @deprecated Use Reader(std::shared_ptr<IContextProvider>, source_path) instead.
787 /// The reference overload does not extend the lifetime of the context, which can
788 /// be problematic when progress callbacks fire after the context is destroyed.
789 [[deprecated("Use Reader(std::shared_ptr<IContextProvider>, source_path) instead. "
790 "The reference overload does not extend the lifetime of the context, which can "
791 "be problematic when progress callbacks fire after the context is destroyed.")]]
792 Reader(IContextProvider& context, const std::filesystem::path &source_path);
793
794 /// @brief Create a Reader from a shared context and stream.
795 /// @details The Reader retains a shared reference to the context, keeping it
796 /// alive for the lifetime of the Reader.
797 /// @param context Shared context provider.
798 /// @param format The mime format of the stream.
799 /// @param stream The input stream to read from.
800 /// @throws C2paException if context is null or context->is_valid() returns false.
801 Reader(std::shared_ptr<IContextProvider> context, const std::string &format, std::istream &stream);
802
803 /// @brief Create a Reader from a shared context and file path.
804 /// @details The Reader retains a shared reference to the context, keeping it
805 /// alive for the lifetime of the Reader.
806 /// @param context Shared context provider.
807 /// @param source_path The path to the file to read.
808 /// @throws C2paException if context is null or context->is_valid() returns false.
809 Reader(std::shared_ptr<IContextProvider> context, const std::filesystem::path &source_path);
810
811 /// @brief Create a Reader from a shared context, image stream, and external JUMBF manifest.
812 /// @details Performs full C2PA binding verification between @p image_stream and the provided
813 /// JUMBF manifest bytes without requiring the manifest to be embedded in the asset.
814 /// Typical use: sidecar .c2pa files, database-stored manifests, in-memory pipelines.
815 /// The Reader retains a shared reference to the context for its lifetime.
816 /// @param context Shared context provider (trust anchors, verification policy).
817 /// @param format MIME type of the image stream (e.g., "image/jpeg").
818 /// @param image_stream Asset data. Must support seeking (used for exclusion-range hashing).
819 /// @param manifest_jumbf Raw JUMBF manifest bytes (e.g., contents of a .c2pa sidecar file).
820 /// @note @p image_stream, @p manifest_jumbf, and @p format need only remain valid for the
821 /// duration of the construction call. The Reader does not retain their references.
822 /// @throws C2paException if context is null,
823 /// context->is_valid() is false,
824 /// manifest_jumbf is empty, or the C2PA library reports an error.
825 Reader(std::shared_ptr<IContextProvider> context,
826 const std::string& format,
827 std::istream& image_stream,
828 const std::vector<uint8_t>& manifest_jumbf);
829
830 /// @brief Create a Reader from a stream (will use global settings if any loaded).
831 /// @details The validation_status field in the JSON contains validation results.
832 /// @param format The mime format of the stream.
833 /// @param stream The input stream to read from.
834 /// @throws C2paException for errors encountered by the C2PA library.
835 /// @deprecated Use Reader(IContextProvider& context, format, stream) instead.
836 [[deprecated("Use Reader(IContextProvider& context, format, stream) instead")]]
837 Reader(const std::string &format, std::istream &stream);
838
839 /// @brief Create a Reader from a file path (will use global settings if any loaded).
840 /// @param source_path The path to the file to read.
841 /// @throws C2paException for errors encountered by the C2PA library.
842 /// @deprecated Use Reader(IContextProvider& context, source_path) instead.
843 /// @note Prefer using the streaming APIs if possible.
844 [[deprecated("Use Reader(IContextProvider& context, source_path) instead")]]
845 Reader(const std::filesystem::path &source_path);
846
847 /// @brief Try to open a Reader from a context and file path when the asset may lack C2PA data.
848 /// @return A Reader if JUMBF (c2pa/manifest) data is present; std::nullopt if none.
849 /// @throws C2paException for errors other than a missing manifest (e.g. invalid asset).
850 /// @throws std::system_error if the file cannot be opened.
851 /// @deprecated Use from_asset(std::shared_ptr<IContextProvider>, source_path) instead.
852 /// The reference overload does not extend the lifetime of the context, which can
853 /// cause a use-after-free crash when progress callbacks fire after the context is
854 /// destroyed.
855 [[deprecated("Use from_asset(std::shared_ptr<IContextProvider>, source_path) instead. "
856 "The reference overload does not extend the lifetime of the context, which can "
857 "be problematic when progress callbacks fire after the context is destroyed.")]]
858 static std::optional<Reader> from_asset(IContextProvider& context, const std::filesystem::path &source_path);
859
860 /// @brief Try to create a Reader from a context and stream when the asset may lack C2PA data.
861 /// @return A Reader if JUMBF (c2pa/manifest) data is present; std::nullopt if none.
862 /// @throws C2paException for errors other than a missing manifest.
863 /// @deprecated Use from_asset(std::shared_ptr<IContextProvider>, format, stream) instead.
864 /// The reference overload does not extend the lifetime of the context, which can
865 /// cause a use-after-free crash when progress callbacks fire after the context is
866 /// destroyed.
867 [[deprecated("Use from_asset(std::shared_ptr<IContextProvider>, format, stream) instead. "
868 "The reference overload does not extend the lifetime of the context, which can "
869 "be problematic when progress callbacks fire after the context is destroyed.")]]
870 static std::optional<Reader> from_asset(IContextProvider& context, const std::string &format, std::istream &stream);
871
872 /// @brief Try to open a Reader from a shared context and file path when the asset may lack C2PA data.
873 /// @details The Reader retains a shared reference to the context if C2PA data is found.
874 /// @return A Reader if JUMBF (c2pa/manifest) data is present; std::nullopt if none.
875 /// @throws C2paException for errors other than a missing manifest.
876 static std::optional<Reader> from_asset(std::shared_ptr<IContextProvider> context, const std::filesystem::path &source_path);
877
878 /// @brief Try to create a Reader from a shared context and stream when the asset may lack C2PA data.
879 /// @details The Reader retains a shared reference to the context if C2PA data is found.
880 /// @return A Reader if JUMBF (c2pa/manifest) data is present; std::nullopt if none.
881 /// @throws C2paException for errors other than a missing manifest.
882 static std::optional<Reader> from_asset(std::shared_ptr<IContextProvider> context, const std::string &format, std::istream &stream);
883
884 // Non-copyable
885 Reader(const Reader&) = delete;
886
887 Reader& operator=(const Reader&) = delete;
888
889 Reader(Reader&& other) noexcept
890 : c2pa_reader(std::exchange(other.c2pa_reader, nullptr)),
891 owned_stream(std::move(other.owned_stream)),
892 cpp_stream(std::move(other.cpp_stream)),
893 context_ref(std::move(other.context_ref)) {
894 }
895
896 Reader& operator=(Reader&& other) noexcept {
897 if (this != &other) {
898 c2pa_free(c2pa_reader);
899 c2pa_reader = std::exchange(other.c2pa_reader, nullptr);
900 owned_stream = std::move(other.owned_stream);
901 cpp_stream = std::move(other.cpp_stream);
902 context_ref = std::move(other.context_ref);
903 }
904 return *this;
905 }
906
908
909 /// @brief Check if the reader was created from an embedded manifest.
910 /// @return true if the manifest was embedded in the asset, false if external.
911 /// @throws C2paException if the Reader holds no valid handle (e.g. it was moved
912 /// from, or a prior with_fragment() failed and consumed it), or for other
913 /// errors encountered by the C2PA library.
914 [[nodiscard]] inline bool is_embedded() const {
915 ensure_initialized();
916 return c2pa_reader_is_embedded(c2pa_reader);
917 }
918
919 /// @brief Returns the remote url of the manifest if this `Reader`
920 /// obtained the manifest remotely
921 /// @return Optional string containing the remote URL, or std::nullopt if manifest was embedded.
922 /// @throws C2paException for errors encountered by the C2PA library.
923 [[nodiscard]] std::optional<std::string> remote_url() const;
924
925 /// @brief Process a BMFF fragment stream with this Reader instance.
926 /// @details Used for fragmented BMFF media (DASH/HLS streaming) where content is split
927 /// into an init/main segment and separate fragment files. The Reader is
928 /// created from the init segment (e.g. Reader(context, "video/mp4", init)),
929 /// then goes through one fragment at a time via this method.
930 /// The underlying native SDK consumes the current reader and
931 /// returns a new one configured with the fragment.
932 /// This method swaps the handle in place and returns *this for chaining
933 /// across fragments as the reading steps go through fragments.
934 /// @param format MIME type of the media (e.g., "video/mp4").
935 /// @param stream The main/init segment.
936 /// @param fragment The current fragment to process.
937 /// @return *this, for chaining across multiple fragments.
938 /// @note @p stream and @p fragment need only remain valid for the duration of this call.
939 /// The Reader does not retain a reference to either after returning.
940 /// @throws C2paException if the C2PA library reports an error.
941 /// On failure the underlying reader handle is consumed and
942 /// this Reader must not be used further.
943 Reader& with_fragment(const std::string& format, std::istream& stream, std::istream& fragment);
944
945 /// @brief Get the manifest as a JSON string.
946 /// @return The manifest as a JSON string.
947 /// @throws C2paException for errors encountered by the C2PA library.
948 std::string json() const;
949
950 /// @brief Get the manifest as a detailed JSON string.
951 /// @details The detailed view more closely resembles the underlying JUMBF
952 /// manifest store. Unlike json(), it exposes the full
953 /// `assertion_store` map for each manifest, including assertions
954 /// that the regular view filters out (such as `c2pa.thumbnail.*`,
955 /// `c2pa.actions.*`, and `c2pa.hash.*`). Use this when building
956 /// redaction URIs or otherwise needing the canonical assertion
957 /// labels embedded in the manifest.
958 /// @return The detailed manifest as a JSON string.
959 /// @throws C2paException for errors encountered by the C2PA library.
960 std::string detailed_json() const;
961
962 /// @brief Get the manifest store as a pretty-printed crJSON string.
963 /// @details crJSON is a standardized JSON format for C2PA manifest data.
964 /// This call is infallible at yields valid empty JSON ("{}") if
965 /// there are no Content Credentials.
966 /// @return The manifest store as a crJSON string.
967 /// @throws C2paException if the underlying C call returns null.
968 std::string crjson() const;
969
970 /// @brief Get a resource from the reader and write it to a file.
971 /// @param uri The URI of the resource.
972 /// @param path The file path to write the resource to.
973 /// @return The number of bytes written.
974 /// @throws C2paException for errors encountered by the C2PA library.
975 /// @note Prefer using the streaming APIs if possible.
976 int64_t get_resource(const std::string &uri, const std::filesystem::path &path);
977
978 /// @brief Get a resource from the reader and write it to an output stream.
979 /// @param uri The URI of the resource.
980 /// @param stream The output stream to write the resource to.
981 /// @return The number of bytes written.
982 /// @throws C2paException for errors encountered by the C2PA library.
983 int64_t get_resource(const std::string &uri, std::ostream &stream);
984
985 /// @brief Get the raw C2paReader pointer.
986 /// @return The raw C2paReader pointer.
987 /// @note This is intended for internal API use and compatibility with C APIs.
988 C2paReader* get_api_internal_raw_reader() const { return c2pa_reader; }
989
990 /// @brief Get a list of mime types that the SDK can read manifests from.
991 /// @return Vector of supported MIME type strings.
992 static std::vector<std::string> supported_mime_types();
993 };
994
995 /// @brief Signer callback function type.
996 /// @details This function type is used to create a callback function for signing.
997 /// The callback receives data to sign and returns the signature.
998 /// @param data The data to sign.
999 /// @return The signature as a vector of bytes.
1000 using SignerFunc = std::vector<unsigned char>(const std::vector<unsigned char> &);
1001
1002 /// @brief Signer class for creating a Signer
1003 /// @details This class is used to create a signer from a signing algorithm, certificate, and TSA URI.
1004 /// Supports both callback-based and direct signing methods.
1006 {
1008
1009 private:
1010 C2paSigner *signer;
1011
1012 /// @brief Transfers ownership of the underlying C2paSigner pointer out
1013 /// of this wrapper, without freeing it.
1014 /// @details Used by ContextBuilder::with_signer() to pass the raw pointer
1015 /// to c2pa_context_builder_set_signer(), which takes ownership on
1016 /// the Rust side via Box::from_raw. After this call the Signer
1017 /// wrapper holds nullptr and its destructor is a no-op.
1018 /// This is not the same as c2pa_signer_free(), which destroys
1019 /// the signer. Similar to std::unique_ptr::release().
1020 /// @return Raw C2paSigner pointer, or nullptr if already released.
1021 C2paSigner* release() noexcept {
1022 return std::exchange(signer, nullptr);
1023 }
1024
1025 /// @brief Validate a TSA URI string.
1026 /// @param tsa_uri The TSA URI to validate.
1027 /// @return Validated C-string pointer.
1028 static const char *validate_tsa_uri(const std::string &tsa_uri);
1029
1030 /// @brief Validate an optional TSA URI.
1031 /// @param tsa_uri The optional TSA URI to validate.
1032 /// @return Validated C-string pointer, or nullptr if nullopt.
1033 static const char *validate_tsa_uri(const std::optional<std::string> &tsa_uri);
1034
1035 public:
1036 /// @brief Create a Signer from a callback function.
1037 /// @param callback The callback function to use for signing.
1038 /// @param alg The signing algorithm to use (e.g., C2paSigningAlg::PS256).
1039 /// @param sign_cert The signing certificate in PEM format.
1040 /// @param tsa_uri The timestamp authority URI for time-stamping.
1041 /// @throws C2paException if signer creation fails.
1042 Signer(SignerFunc *callback, C2paSigningAlg alg, const std::string &sign_cert, const std::string &tsa_uri);
1043
1044 /// @brief Create a signer from a Signer pointer and take ownership of that pointer.
1045 /// @param c_signer The C2paSigner pointer (must be non-null).
1046 Signer(C2paSigner *c_signer) : signer(c_signer) {
1047 if (!c_signer) {
1048 throw C2paException("Signer can not be null");
1049 }
1050 }
1051
1052 /// @brief Create a Signer from signing credentials.
1053 /// @param alg Signing algorithm name (e.g., "ps256", "es256").
1054 /// @param sign_cert Signing certificate in PEM format.
1055 /// @param private_key Private key in PEM format.
1056 /// @param tsa_uri Optional timestamp authority URI.
1057 /// @throws C2paException if signer creation fails.
1058 Signer(const std::string &alg, const std::string &sign_cert, const std::string &private_key, const std::optional<std::string> &tsa_uri = std::nullopt);
1059
1060 Signer(const Signer&) = delete;
1061
1062 Signer& operator=(const Signer&) = delete;
1063
1064 /// @brief Move constructor.
1065 /// @param other Signer to move from.
1066 Signer(Signer&& other) noexcept : signer(std::exchange(other.signer, nullptr)) {
1067 }
1068
1069 Signer& operator=(Signer&& other) noexcept {
1070 if (this != &other) {
1071 c2pa_free(signer);
1072 signer = std::exchange(other.signer, nullptr);
1073 }
1074 return *this;
1075 }
1076
1078
1079 /// @brief Get the size to reserve for a signature for this Signer.
1080 /// @return Reserved size for the signature in bytes.
1081 uintptr_t reserve_size();
1082
1083 /// @brief Get the underlying C2paSigner pointer.
1084 /// @return Pointer to the C2paSigner object.
1085 C2paSigner *c2pa_signer() const noexcept;
1086 };
1087
1088 /// @brief Builder class for creating a manifest.
1089 /// @details This class is used to create a manifest from a json std::string and add resources and ingredients to the manifest.
1091 {
1092 private:
1093 C2paBuilder *builder;
1094 std::shared_ptr<IContextProvider> context_ref;
1095
1096 void init_from_context(IContextProvider& context);
1097 void init_from_context(IContextProvider& context, const std::string &manifest_json);
1098
1099 public:
1100 /// @brief Create a Builder from a context with an empty manifest.
1101 /// @param context Context provider; used at construction to configure settings.
1102 /// @throws C2paException if context.is_valid() returns false,
1103 /// or for other errors encountered by the C2PA library.
1104 /// @deprecated Use Builder(std::shared_ptr<IContextProvider>) instead.
1105 /// The reference overload does not extend the lifetime of the context, which can
1106 /// be problematic when progress callbacks fire after the context is destroyed.
1107 [[deprecated("Use Builder(std::shared_ptr<IContextProvider>) instead. "
1108 "The reference overload does not extend the lifetime of the context, which can "
1109 "be problematic when progress callbacks fire after the context is destroyed.")]]
1110 explicit Builder(IContextProvider& context);
1111
1112 /// @brief Create a Builder from a context and manifest JSON string.
1113 /// @param context Context provider; used at construction to configure settings.
1114 /// @param manifest_json The manifest JSON string.
1115 /// @throws C2paException if context.is_valid() returns false,
1116 /// or for other errors encountered by the C2PA library.
1117 /// @deprecated Use Builder(std::shared_ptr<IContextProvider>, manifest_json) instead.
1118 /// The reference overload does not extend the lifetime of the context, which can
1119 /// be problematic when progress callbacks fire after the context is destroyed.
1120 [[deprecated("Use Builder(std::shared_ptr<IContextProvider>, manifest_json) instead. "
1121 "The reference overload does not extend the lifetime of the context, which can "
1122 "be problematic when progress callbacks fire after the context is destroyed.")]]
1123 Builder(IContextProvider& context, const std::string &manifest_json);
1124
1125 /// @brief Create a Builder from a shared context with an empty manifest.
1126 /// @details The Builder retains a shared reference to the context, keeping it
1127 /// alive for the lifetime of the Builder. This is the preferred
1128 /// constructor when the Context may be destroyed before the Builder.
1129 /// @param context Shared context provider.
1130 /// @throws C2paException if context is null or context->is_valid() returns false.
1131 explicit Builder(std::shared_ptr<IContextProvider> context);
1132
1133 /// @brief Create a Builder from a shared context and manifest JSON string.
1134 /// @details The Builder retains a shared reference to the context, keeping it
1135 /// alive for the lifetime of the Builder.
1136 /// @param context Shared context provider.
1137 /// @param manifest_json The manifest JSON string.
1138 /// @throws C2paException if context is null or context->is_valid() returns false.
1139 Builder(std::shared_ptr<IContextProvider> context, const std::string &manifest_json);
1140
1141 /// @brief Create a Builder from a manifest JSON string (will use global settings if any loaded).
1142 /// @param manifest_json The manifest JSON string.
1143 /// @throws C2paException for errors encountered by the C2PA library.
1144 /// @deprecated Use Builder(IContextProvider& context, manifest_json) instead.
1145 [[deprecated("Use Builder(IContextProvider& context, manifest_json) instead")]]
1146 Builder(const std::string &manifest_json);
1147
1148 /// @brief Create a Builder from a raw C FFI builder.
1149 /// @param builder Raw C2paBuilder pointer to wrap.
1150 /// @throws C2paException if builder is nullptr.
1151 explicit Builder(C2paBuilder *builder);
1152
1153 Builder(const Builder&) = delete;
1154
1155 Builder& operator=(const Builder&) = delete;
1156
1157 Builder(Builder&& other) noexcept
1158 : builder(std::exchange(other.builder, nullptr)),
1159 context_ref(std::move(other.context_ref)) {
1160 }
1161
1162 Builder& operator=(Builder&& other) noexcept {
1163 if (this != &other) {
1164 c2pa_free(builder);
1165 builder = std::exchange(other.builder, nullptr);
1166 context_ref = std::move(other.context_ref);
1167 }
1168 return *this;
1169 }
1170
1172
1173 /// @brief Get the underlying C2paBuilder pointer.
1174 /// @return Pointer managed by this wrapper.
1175 C2paBuilder *c2pa_builder() const noexcept;
1176
1177 /// @brief Set or update the manifest definition.
1178 /// @param manifest_json The manifest JSON string.
1179 /// @return Reference to this Builder for method chaining.
1180 /// @throws C2pa::C2paException for errors encountered by the C2PA library.
1181 Builder& with_definition(const std::string &manifest_json);
1182
1183 /// @brief Set the no-embed flag to prevent embedding the manifest in the asset.
1184 /// @details When set, the manifest will be stored externally rather than embedded.
1185 void set_no_embed();
1186
1187 /// @brief Set the remote URL.
1188 /// @param remote_url The remote URL to set.
1189 /// @throws C2paException for errors encountered by the C2PA library.
1190 void set_remote_url(const std::string &remote_url);
1191
1192 /// @brief Set the base path for loading resources from files.
1193 /// @details When set, resources are loaded from files relative to this path.
1194 /// If not set, resources are loaded from memory.
1195 /// @param base_path The base directory path.
1196 /// @throws C2paException for errors encountered by the C2PA library.
1197 /// @deprecated This method is planned to be deprecated in a future release.
1198 /// Usage should be limited and temporary. Use add_resource instead.
1199 void set_base_path(const std::string &base_path);
1200
1201 /// @brief Add a resource to the builder from a stream.
1202 /// @param uri The URI identifier for the resource.
1203 /// @param source The input stream to read the resource from.
1204 /// @throws C2paException for errors encountered by the C2PA library.
1205 void add_resource(const std::string &uri, std::istream &source);
1206
1207 /// @brief Add a resource to the builder from a file.
1208 /// @param uri The URI identifier for the resource.
1209 /// @param source_path The path to the resource file.
1210 /// @throws C2paException for errors encountered by the C2PA library.
1211 /// @note Prefer using the streaming APIs if possible.
1212 void add_resource(const std::string &uri, const std::filesystem::path &source_path);
1213
1214 /// @brief Add an ingredient to the builder from a stream.
1215 /// @param ingredient_json Any fields of the ingredient you want to define.
1216 /// @param format The mime format of the ingredient.
1217 /// @param source The input stream to read the ingredient from.
1218 /// @throws C2paException for errors encountered by the C2PA library.
1219 void add_ingredient(const std::string &ingredient_json, const std::string &format, std::istream &source);
1220
1221 /// @brief Add an ingredient to the builder from a file.
1222 /// @param ingredient_json Any fields of the ingredient you want to define.
1223 /// @param source_path The path to the ingredient file.
1224 /// @throws C2paException for errors encountered by the C2PA library.
1225 /// @note Prefer using the streaming APIs if possible.
1226 void add_ingredient(const std::string &ingredient_json, const std::filesystem::path &source_path);
1227
1228 /// @brief Add an action to the manifest.
1229 /// @param action_json JSON string containing the action data.
1230 /// @throws C2paException for errors encountered by the C2PA library.
1231 void add_action(const std::string &action_json);
1232
1233 /// @brief Set the intent for this Builder, controlling what kind of manifest to create.
1234 /// @param intent The intent type: Create, Edit, or Update.
1235 /// @param digital_source_type Required for Create intent. Describes how the asset was produced.
1236 /// Defaults to Empty.
1237 /// @throws C2paException if the intent cannot be set.
1238 void set_intent(C2paBuilderIntent intent, C2paDigitalSourceType digital_source_type = Empty);
1239
1240 /// @brief Sign an input stream and write the signed data to an output stream.
1241 /// @param format The mime format of the output stream.
1242 /// @param source The input stream to sign.
1243 /// @param dest The output stream to write the signed data to.
1244 /// @param signer The Signer object to use for signing.
1245 /// @return A vector containing the signed manifest bytes.
1246 /// @throws C2paException for errors encountered by the C2PA library.
1247 /// @deprecated Use sign(const string&, std::istream&, std::iostream&, Signer&) instead.
1248 std::vector<unsigned char> sign(const std::string &format, std::istream &source, std::ostream &dest, Signer &signer);
1249
1250 /// @brief Sign an input stream and write the signed data to an I/O stream.
1251 /// @param format The mime format of the output.
1252 /// @param source The input stream to sign.
1253 /// @param dest The I/O stream to write the signed data to.
1254 /// @param signer The Signer object to use for signing.
1255 /// @return A vector containing the signed manifest bytes.
1256 /// @throws C2paException for errors encountered by the C2PA library.
1257 std::vector<unsigned char> sign(const std::string &format, std::istream &source, std::iostream &dest, Signer &signer);
1258
1259 /// @brief Sign a file and write the signed data to an output file.
1260 /// @param source_path The path to the file to sign.
1261 /// @param dest_path The path to write the signed file to.
1262 /// @param signer The signer object to use for signing.
1263 /// @return A vector containing the signed manifest bytes.
1264 /// @throws C2paException for errors encountered by the C2PA library.
1265 /// @note Prefer using the streaming APIs if possible.
1266 std::vector<unsigned char> sign(const std::filesystem::path &source_path, const std::filesystem::path &dest_path, Signer &signer);
1267
1268 /// @brief Sign using the signer from the Builder's Context.
1269 /// @details The Signer may have been set programmatically via
1270 /// ContextBuilder::with_signer(), or configured in settings JSON.
1271 /// If both programmatic and settings signers are present,
1272 /// the programmatic signer takes priority.
1273 /// @param format The mime format of the output.
1274 /// @param source The input stream to sign.
1275 /// @param dest The I/O stream to write the signed data to.
1276 /// @return A vector containing the signed manifest bytes.
1277 /// @throws C2paException if the context has no signer or on other errors.
1278 std::vector<unsigned char> sign(const std::string &format, std::istream &source, std::iostream &dest);
1279
1280 /// @brief Sign a file using the signer from the Builder's Context.
1281 /// @details The signer may have been set programmatically via
1282 /// ContextBuilder::with_signer(), or configured in settings JSON.
1283 /// If both programmatic and settings signers are present,
1284 /// the programmatic signer takes priority.
1285 /// @param source_path The path to the file to sign.
1286 /// @param dest_path The path to write the signed file to.
1287 /// @return A vector containing the signed manifest bytes.
1288 /// @throws C2paException if the context has no signer or on other errors.
1289 std::vector<unsigned char> sign(const std::filesystem::path &source_path, const std::filesystem::path &dest_path);
1290
1291 /// @brief Create a Builder from an archived Builder stream.
1292 /// @param archive The input stream to read the archive from.
1293 /// @return A new Builder instance loaded from the archive.
1294 /// @throws C2paException for errors encountered by the C2PA library.
1295 static Builder from_archive(std::istream &archive);
1296
1297 /// @brief Create a Builder from an archive.
1298 /// @param archive_path The path to the archive file.
1299 /// @return A new Builder instance loaded from the archive.
1300 /// @throws C2paException for errors encountered by the C2PA library.
1301 /// @note Prefer using the streaming APIs if possible.
1302 static Builder from_archive(const std::filesystem::path &archive_path);
1303
1304 /// @brief Load an archive into this builder.
1305 /// @details Replaces the current definition with the archived builder state.
1306 /// @param archive The input stream to read the archive from.
1307 /// @return Reference to this builder for method chaining.
1308 /// @throws C2paException for errors encountered by the C2PA library.
1309 /// @note This allows setting a context before loading the archive, preserving context settings.
1310 Builder& with_archive(std::istream &archive);
1311
1312 /// @brief Write the builder to an archive stream.
1313 /// @param dest The output stream to write the archive to.
1314 /// @throws C2paException for errors encountered by the C2PA library.
1315 void to_archive(std::ostream &dest);
1316
1317 /// @brief Write the builder to an archive file.
1318 /// @param dest_path The path to write the archive file to.
1319 /// @throws C2paException for errors encountered by the C2PA library.
1320 /// @note Prefer using the streaming APIs if possible.
1321 void to_archive(const std::filesystem::path &dest_path);
1322
1323 /// @brief Write a single-ingredient archive for the named ingredient.
1324 /// @param ingredient_id The ingredient's `label` if set, otherwise its `instance_id`,
1325 /// as supplied to add_ingredient.
1326 /// @param dest The output stream to write the ingredient archive to.
1327 /// @note Requires the `generate_c2pa_archive` context setting to be enabled
1328 /// (enabled by default).
1329 /// @throws C2paException for errors encountered by the C2PA library.
1330 void write_ingredient_archive(const std::string &ingredient_id, std::ostream &dest);
1331
1332 /// @brief Add an ingredient to this builder from a per-ingredient archive stream.
1333 /// @param archive The input stream containing the archive produced by write_ingredient_archive.
1334 /// @throws C2paException for errors encountered by the C2PA library.
1335 void add_ingredient_from_archive(std::istream &archive);
1336
1337 /// @brief Create a hashed placeholder from the builder.
1338 /// @param reserved_size The size required for a signature from the intended signer (in bytes).
1339 /// @param format The mime format or extension of the asset.
1340 /// @return A vector containing the hashed placeholder bytes.
1341 /// @throws C2paException for errors encountered by the C2PA library.
1342 std::vector<unsigned char> data_hashed_placeholder(uintptr_t reserved_size, const std::string &format);
1343
1344 /// @brief Sign a Builder using the specified signer and data hash.
1345 /// @param signer The signer to use for signing.
1346 /// @param data_hash The data hash ranges to sign (must contain hashes unless an asset is provided).
1347 /// @param format The mime format for embedding. Use "c2pa" for an unformatted result.
1348 /// @param asset Optional asset to hash according to the data_hash information.
1349 /// @return A vector containing the signed embeddable data.
1350 /// @throws C2paException for errors encountered by the C2PA library.
1351 std::vector<unsigned char> sign_data_hashed_embeddable(Signer &signer, const std::string &data_hash, const std::string &format, std::istream *asset = nullptr);
1352
1353 /// @brief Convert unformatted manifest data to an embeddable format.
1354 /// @param format The format for embedding.
1355 /// @param data Unformatted manifest data from sign_data_hashed_embeddable using "c2pa" format.
1356 /// @return A formatted copy of the data.
1357 static std::vector<unsigned char> format_embeddable(const std::string &format, std::vector<unsigned char> &data);
1358
1359 /// @brief Check if the given format requires a placeholder embedding step.
1360 /// @details Returns false for BoxHash-capable formats when prefer_box_hash is enabled in
1361 /// the context settings (no placeholder needed — hash covers the full asset).
1362 /// Always returns true for BMFF formats (MP4, etc.) regardless of settings.
1363 /// @param format The MIME type or extension of the asset (e.g. "image/jpeg", "video/mp4").
1364 /// @return true if placeholder() must be called and embedded before sign_embeddable(); false otherwise.
1365 /// @throws C2paException on error.
1366 bool needs_placeholder(const std::string &format);
1367
1368 /// @brief Create a composed placeholder manifest to embed in the asset.
1369 /// @details The signer (and its reserve size) are obtained from the Builder's Context.
1370 /// For BMFF assets, the placeholder includes a BmffHash assertion with
1371 /// default exclusions for the manifest UUID box.
1372 /// Returns empty bytes for formats that do not need a placeholder (BoxHash).
1373 /// The placeholder size is stored internally so sign_embeddable() returns bytes
1374 /// of exactly the same size, enabling in-place patching.
1375 /// @param format The MIME type or extension of the asset (e.g. "image/jpeg", "video/mp4").
1376 /// @return Composed placeholder bytes ready to embed into the asset.
1377 /// @throws C2paException on error.
1378 std::vector<unsigned char> placeholder(const std::string &format);
1379
1380 /// @brief Register the byte ranges where the placeholder was embedded (DataHash workflow).
1381 /// @details Call this after embedding the placeholder bytes into the asset and before
1382 /// update_hash_from_stream(). The exclusions replace the dummy ranges set by
1383 /// placeholder() so the asset hash covers all bytes except the manifest slot.
1384 /// Exclusions are (start, length) pairs in asset byte coordinates.
1385 /// @param exclusions Vector of (start, length) pairs describing the embedded placeholder region.
1386 /// @throws C2paException if no DataHash assertion exists or on other error.
1387 void set_data_hash_exclusions(const std::vector<std::pair<uint64_t, uint64_t>> &exclusions);
1388
1389 /// @brief Compute and store the asset hash by reading a stream.
1390 /// @details Automatically detects the hard binding type from the builder state:
1391 /// - DataHash: uses exclusion ranges already registered via set_data_hash_exclusions().
1392 /// - BmffHash: uses path-based exclusions from the BMFF assertion (UUID box, mdat).
1393 /// - BoxHash: hashes each format-specific box individually.
1394 /// Call set_data_hash_exclusions() before this for DataHash workflows.
1395 /// @param format The MIME type or extension of the asset (e.g. "image/jpeg", "video/mp4").
1396 /// @param stream The asset stream to hash. Must include the embedded placeholder bytes.
1397 /// @throws C2paException on error.
1398 void update_hash_from_stream(const std::string &format, std::istream &stream);
1399
1400 /// @brief Sign and return the final manifest bytes, ready for embedding.
1401 /// @details Operates in two modes:
1402 /// - Placeholder mode (after placeholder()): zero-pads the signed manifest to the
1403 /// pre-committed placeholder size, enabling in-place patching of the asset.
1404 /// - Direct mode (no placeholder): returns the actual signed manifest size.
1405 /// Requires a valid hard binding assertion (set via update_hash_from_stream()).
1406 /// The signer is obtained from the Builder's Context.
1407 /// @param format The MIME type or extension of the asset (e.g. "image/jpeg", "video/mp4").
1408 /// @return Signed manifest bytes ready to embed into the asset.
1409 /// @throws C2paException on error.
1410 std::vector<unsigned char> sign_embeddable(const std::string &format);
1411
1412 /// @brief Get a list of mime types that the Builder supports.
1413 /// @return Vector of supported MIME type strings.
1414 static std::vector<std::string> supported_mime_types();
1415
1416 private:
1417 explicit Builder(std::istream &archive);
1418 };
1419}
1420
1421// Restore warnings
1422#ifdef __GNUC__
1423#pragma GCC diagnostic pop
1424#endif
1425
1426#ifdef _MSC_VER
1427#pragma warning(pop)
1428#endif
1429
1430#endif // C2PA_H
#define C2PA_CPP_API
Definition c2pa.hpp:49
Builder class for creating a manifest.
Definition c2pa.hpp:1091
Builder(const std::string &manifest_json)
Create a Builder from a manifest JSON string (will use global settings if any loaded).
Builder & operator=(const Builder &)=delete
Builder(Builder &&other) noexcept
Definition c2pa.hpp:1157
Builder(C2paBuilder *builder)
Create a Builder from a raw C FFI builder.
Builder(const Builder &)=delete
Builder(std::shared_ptr< IContextProvider > context, const std::string &manifest_json)
Create a Builder from a shared context and manifest JSON string.
C2paBuilder * c2pa_builder() const noexcept
Get the underlying C2paBuilder pointer.
Builder & operator=(Builder &&other) noexcept
Definition c2pa.hpp:1162
Builder(std::shared_ptr< IContextProvider > context)
Create a Builder from a shared context with an empty manifest.
Builder(IContextProvider &context)
Create a Builder from a context with an empty manifest.
Builder(IContextProvider &context, const std::string &manifest_json)
Create a Builder from a context and manifest JSON string.
Exception class for C2pa errors. This class is used to throw exceptions for errors encountered by the...
Definition c2pa.hpp:87
C2paException & operator=(C2paException &&)=default
~C2paException() override=default
C2paException(const C2paException &)=default
const char * what() const noexcept override
Get the exception message.
C2paException(std::string message)
Construct an exception with a custom error message.
C2paException & operator=(const C2paException &)=default
C2paException(C2paException &&)=default
C2paException()
Default constructor.
ContextBuilder for creating customized Context instances.
Definition c2pa.hpp:330
ReleasedBuilder release() noexcept
Release ownership of the underlying C2paContextBuilder handle and its progress-callback heap block (i...
C2PA context implementing IContextProvider.
Definition c2pa.hpp:322
IOStream Class wrapper for C2paStream.
Definition c2pa.hpp:680
CppIOStream & operator=(const CppIOStream &)=delete
CppIOStream(const CppIOStream &)=delete
CppIOStream & operator=(CppIOStream &&)=delete
C2paStream * c_stream
Pointer to the underlying C2paStream.
Definition c2pa.hpp:683
CppIOStream(IOStream &iostream)
Construct an I/O stream wrapper from a std::iostream-derived object.
Definition c2pa.hpp:690
CppIOStream(CppIOStream &&)=delete
Input stream IStream wrapper for C2paStream.
Definition c2pa.hpp:557
CppIStream & operator=(const CppIStream &)=delete
CppIStream(CppIStream &&)=delete
CppIStream & operator=(CppIStream &&)=delete
C2paStream * c_stream
Pointer to the underlying C2paStream.
Definition c2pa.hpp:560
CppIStream(IStream &istream)
Construct an input stream wrapper from a std::istream-derived object.
Definition c2pa.hpp:567
CppIStream(const CppIStream &)=delete
Output stream OStream wrapper for C2paStream.
Definition c2pa.hpp:620
CppOStream(OStream &ostream)
Construct an output stream wrapper from a std::ostream-derived object.
Definition c2pa.hpp:630
CppOStream(CppOStream &&)=delete
CppOStream & operator=(CppOStream &&)=delete
C2paStream * c_stream
Pointer to the underlying C2paStream.
Definition c2pa.hpp:623
CppOStream & operator=(const CppOStream &)=delete
CppOStream(const CppOStream &)=delete
Interface for types that can provide C2PA context functionality.
Definition c2pa.hpp:161
virtual ~IContextProvider() noexcept=default
Reader class for reading a manifest.
Definition c2pa.hpp:742
Reader(std::shared_ptr< IContextProvider > context, const std::filesystem::path &source_path)
Create a Reader from a shared context and file path.
static std::optional< Reader > from_asset(std::shared_ptr< IContextProvider > context, const std::string &format, std::istream &stream)
Try to create a Reader from a shared context and stream when the asset may lack C2PA data.
Reader(std::shared_ptr< IContextProvider > context, const std::string &format, std::istream &image_stream, const std::vector< uint8_t > &manifest_jumbf)
Create a Reader from a shared context, image stream, and external JUMBF manifest.
bool is_embedded() const
Check if the reader was created from an embedded manifest.
Definition c2pa.hpp:914
std::string json() const
Get the manifest as a JSON string.
static std::optional< Reader > from_asset(IContextProvider &context, const std::string &format, std::istream &stream)
Try to create a Reader from a context and stream when the asset may lack C2PA data.
int64_t get_resource(const std::string &uri, const std::filesystem::path &path)
Get a resource from the reader and write it to a file.
Reader(const std::string &format, std::istream &stream)
Create a Reader from a stream (will use global settings if any loaded).
int64_t get_resource(const std::string &uri, std::ostream &stream)
Get a resource from the reader and write it to an output stream.
Reader(std::shared_ptr< IContextProvider > context, const std::string &format, std::istream &stream)
Create a Reader from a shared context and stream.
static std::optional< Reader > from_asset(IContextProvider &context, const std::filesystem::path &source_path)
Try to open a Reader from a context and file path when the asset may lack C2PA data.
Reader(Reader &&other) noexcept
Definition c2pa.hpp:889
Reader(const Reader &)=delete
std::string crjson() const
Get the manifest store as a pretty-printed crJSON string.
Reader & operator=(const Reader &)=delete
std::optional< std::string > remote_url() const
Returns the remote url of the manifest if this Reader obtained the manifest remotely.
Reader & with_fragment(const std::string &format, std::istream &stream, std::istream &fragment)
Process a BMFF fragment stream with this Reader instance.
static std::optional< Reader > from_asset(std::shared_ptr< IContextProvider > context, const std::filesystem::path &source_path)
Try to open a Reader from a shared context and file path when the asset may lack C2PA data.
Reader(IContextProvider &context, const std::string &format, std::istream &stream)
Create a Reader from a context and stream.
Reader & operator=(Reader &&other) noexcept
Definition c2pa.hpp:896
std::string detailed_json() const
Get the manifest as a detailed JSON string.
Reader(const std::filesystem::path &source_path)
Create a Reader from a file path (will use global settings if any loaded).
C2paReader * get_api_internal_raw_reader() const
Get the raw C2paReader pointer.
Definition c2pa.hpp:988
Reader(IContextProvider &context, const std::filesystem::path &source_path)
Create a Reader from a context and file path.
static std::vector< std::string > supported_mime_types()
Get a list of mime types that the SDK can read manifests from.
(C2PA SDK) Settings configuration object for creating contexts.
Definition c2pa.hpp:195
Settings & update(const std::string &data)
Merge configuration from a JSON string (latest configuration wins).
Definition c2pa.hpp:233
C2paSettings * c_settings() const noexcept
Get the raw C FFI settings pointer.
Settings(const std::string &data, const std::string &format)
Create settings from a configuration string.
Settings()
Create default settings.
Settings(Settings &&) noexcept
Settings & update(const std::string &data, const std::string &format)
Merge configuration from a std::string (latest configuration wins).
Signer class for creating a Signer.
Definition c2pa.hpp:1006
Signer & operator=(Signer &&other) noexcept
Definition c2pa.hpp:1069
uintptr_t reserve_size()
Get the size to reserve for a signature for this Signer.
C2paSigner * c2pa_signer() const noexcept
Get the underlying C2paSigner pointer.
Signer(SignerFunc *callback, C2paSigningAlg alg, const std::string &sign_cert, const std::string &tsa_uri)
Create a Signer from a callback function.
Signer(C2paSigner *c_signer)
Create a signer from a Signer pointer and take ownership of that pointer.
Definition c2pa.hpp:1046
Signer & operator=(const Signer &)=delete
Signer(Signer &&other) noexcept
Move constructor.
Definition c2pa.hpp:1066
Signer(const Signer &)=delete
Signer(const std::string &alg, const std::string &sign_cert, const std::string &private_key, const std::optional< std::string > &tsa_uri=std::nullopt)
Create a Signer from signing credentials.
Definition c2pa.hpp:52
OperationResult
Result codes for C API operations (matches C API return convention).
Definition c2pa.hpp:64
@ Success
Operation succeeded.
@ Error
Operation failed (check C2paException for details)
ProgressPhase
Phase values reported to the ProgressCallbackFunc.
Definition c2pa.hpp:265
std::function< bool(ProgressPhase phase, uint32_t step, uint32_t total)> ProgressCallbackFunc
Type alias for the progress callback passed to ContextBuilder::with_progress_callback().
Definition c2pa.hpp:299
int stream_error_return(StreamError e) noexcept
Set errno from StreamError and return error sentinel.
Definition c2pa.hpp:79
C2paSignerInfo SignerInfo
Type alias for C2paSignerInfo from the C API.
Definition c2pa.hpp:55
StreamError
Stream/FFI error codes (maps to errno values used by the C layer).
Definition c2pa.hpp:70
std::vector< unsigned char >(const std::vector< unsigned char > &) SignerFunc
Signer callback function type.
Definition c2pa.hpp:1000
Result of ContextBuilder::release(): the raw native builder handle paired with the heap-owned progres...
Definition c2pa.hpp:426
C2paContextBuilder * builder
Definition c2pa.hpp:427
std::unique_ptr< ProgressCallbackFunc > callback_owner
Definition c2pa.hpp:428