Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 50 additions & 58 deletions include/c2pa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

namespace c2pa
{
// TODO-TMN: Remove this and do full naming
using namespace std;

typedef C2paSignerInfo SignerInfo;
Expand Down Expand Up @@ -77,17 +78,17 @@ namespace c2pa
/// @details Implement this interface to make your own context
class C2PA_CPP_API IContextProvider {
public:
virtual ~IContextProvider() = default;
virtual ~IContextProvider() noexcept = default;

/// @brief Get the underlying C2PA context pointer for FFI operations.
/// @return Pointer to C2paContext, or nullptr if not available.
/// @note Provider retains ownership; pointer valid for provider's lifetime.
[[nodiscard]] virtual C2paContext* c_context() const = 0;

/// @brief Check if this provider has a valid context.
/// @return true if context is available, false otherwise.
[[nodiscard]] virtual bool has_context() const noexcept = 0;

protected:
IContextProvider() = default;
IContextProvider(const IContextProvider&) = default;
Expand All @@ -104,41 +105,41 @@ namespace c2pa
public:
/// @brief Create default settings.
Settings();

/// @brief Create settings from a configuration string.
/// @param data Configuration data in JSON or TOML format.
/// @param format Format of the data ("json" or "toml").
/// @throws C2paException if parsing fails.
Settings(const string& data, const string& format);

// Move semantics
Settings(Settings&&) noexcept;
Settings& operator=(Settings&&) noexcept;

// Non-copyable
Settings(const Settings&) = delete;
Settings& operator=(const Settings&) = delete;
~Settings();

~Settings() noexcept;

/// @brief Set a single configuration value by path.
/// @param path Dot-separated path to the setting (e.g., "verify.verify_after_sign").
/// @param json_value JSON-encoded value to set.
/// @return Reference to this Settings for method chaining.
/// @throws C2paException if the path or value is invalid.
Settings& set(const string& path, const string& json_value);

/// @brief Merge configuration from a string.
/// @param data Configuration data in JSON or TOML format.
/// @param format Format of the data ("json" or "toml").
/// @return Reference to this Settings for method chaining.
/// @throws C2paException if parsing fails.
Settings& update(const string& data, const string& format);

/// @brief Get the raw C FFI settings pointer.
/// @return Pointer to C2paSettings, or nullptr if not initialized.
[[nodiscard]] C2paSettings* c_settings() const noexcept;

private:
C2paSettings* settings_;
};
Expand All @@ -153,79 +154,78 @@ namespace c2pa
class C2PA_CPP_API ContextBuilder {
public:
ContextBuilder();
~ContextBuilder();
~ContextBuilder() noexcept;

// Move semantics
ContextBuilder(ContextBuilder&&) noexcept;
ContextBuilder& operator=(ContextBuilder&&) noexcept;

// Non-copyable
ContextBuilder(const ContextBuilder&) = delete;
ContextBuilder& operator=(const ContextBuilder&) = delete;

/// @brief Configure with Settings object.
/// @param settings Settings to use (will be copied).
/// @return Reference to this ContextBuilder for method chaining.
ContextBuilder& with_settings(const Settings& settings);

/// @brief Configure with JSON string.
/// @param json JSON configuration string.
/// @return Reference to this ContextBuilder for method chaining.
/// @throws C2paException if JSON is invalid.
ContextBuilder& with_json(const string& json);

/// @brief Configure with TOML string.
/// @param toml TOML configuration string.
/// @return Reference to this ContextBuilder for method chaining.
/// @throws C2paException if TOML is invalid.
ContextBuilder& with_toml(const string& toml);

/// @brief Build the immutable Context.
/// @return Shared pointer to the new Context.
/// @throws C2paException if context creation fails.
/// @note This consumes the builder. After calling create_context(), the builder is in a moved-from state.
[[nodiscard]] ContextProviderPtr create_context();
[[nodiscard]] ContextProviderPtr create_context(); // TODO-TMN: Make consuming?

private:
C2paContextBuilder* context_builder_;
C2paContextBuilder* context_builder;
};

/// @brief Create a Context with default settings.
/// @return Shared pointer to the new Context.
/// @throws C2paException if context creation fails.
[[nodiscard]] static ContextProviderPtr create();

/// @brief Create a Context from JSON configuration.
/// @param json JSON configuration string.
/// @return Shared pointer to the new Context.
/// @throws C2paException if JSON is invalid or context creation fails.
[[nodiscard]] static ContextProviderPtr from_json(const string& json);

/// @brief Create a Context from TOML configuration.
/// @param toml TOML configuration string.
/// @return Shared pointer to the new Context.
/// @throws C2paException if TOML is invalid or context creation fails.
[[nodiscard]] static ContextProviderPtr from_toml(const string& toml);

// Non-copyable, non-moveable (managed via shared_ptr)
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
Context(Context&&) = delete;
Context& operator=(Context&&) = delete;
~Context() override;

~Context() noexcept override;

// IContextProvider implementation
[[nodiscard]] C2paContext* c_context() const override;
[[nodiscard]] bool has_context() const noexcept override;

/// @brief Internal constructor (use static factory methods instead).
/// @note This is public to allow std::make_shared but should not be called directly.
explicit Context(C2paContext* ctx);

private:
C2paContext* context_;

friend class Builder;
};

Expand Down Expand Up @@ -272,12 +272,12 @@ namespace c2pa
class C2PA_CPP_API CppIStream : public C2paStream
{
public:
C2paStream *c_stream;
C2paStream *c_stream; //TODO-TMN: Review this to encapsulate + grant specific access on need basis + look into smart pointer instead
template <typename IStream>
explicit CppIStream(IStream &istream) {
static_assert(std::is_base_of<std::istream, IStream>::value,
"Stream must be derived from std::istream");
c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(&istream), reader, seeker, writer, flusher);
c_stream = c2pa_create_stream(reinterpret_cast<StreamContext *>(&istream), reader, seeker, writer, flusher);
}

CppIStream(const CppIStream &) = delete;
Expand All @@ -301,7 +301,7 @@ namespace c2pa
class C2PA_CPP_API CppOStream : public C2paStream
{
public:
C2paStream *c_stream;
C2paStream *c_stream; //TODO-TMN: Review this to encapsulate + grant specific access on need basis + look into smart pointer instead
template <typename OStream>
explicit CppOStream(OStream &ostream) {
static_assert(std::is_base_of<std::ostream, OStream>::value, "Stream must be derived from std::ostream");
Expand All @@ -327,7 +327,7 @@ namespace c2pa
class C2PA_CPP_API CppIOStream : public C2paStream
{
public:
C2paStream *c_stream;
C2paStream *c_stream; //TODO-TMN: Review this to encapsulate + grant specific access on need basis + look into smart pointer instead
template <typename IOStream>
CppIOStream(IOStream &iostream) {
static_assert(std::is_base_of<std::iostream, IOStream>::value, "Stream must be derived from std::iostream");
Expand Down Expand Up @@ -355,40 +355,36 @@ namespace c2pa
private:
C2paReader *c2pa_reader;
CppIStream *cpp_stream = nullptr;
ContextProviderPtr context_; // Keeps context alive
ContextProviderPtr context_; // Keeps context alive - TODO-TMN: Rename

public:
// ===== Context-based constructors =====

/// @brief Create a Reader from a context and stream.
/// @param context Context provider to use for this reader.
/// @param format The mime format of the stream.
/// @param stream The input stream to read from.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
Reader(ContextProviderPtr context, const std::string &format, std::istream &stream);

/// @brief Create a Reader from a context and file path.
/// @param context Context provider to use for this reader.
/// @param source_path The path to the file to read.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
Reader(ContextProviderPtr context, const std::filesystem::path &source_path);

// ===== Legacy constructors (DEPRECATED) =====


/// @brief Create a Reader from a stream (uses global settings).
/// @details The validation_status field in the json contains validation results.
/// @param format The mime format of the stream.
/// @param stream The input stream to read from.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
/// @deprecated Use Reader(ContextProviderPtr, format, stream) instead.
[[deprecated("Use Reader(ContextProviderPtr, format, stream) for better thread safety")]]
[[deprecated("Use Reader(ContextProviderPtr, format, stream) instead")]]
Reader(const std::string &format, std::istream &stream);

/// @brief Create a Reader from a file path (uses global settings).
/// @param source_path The path to the file to read.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
/// @deprecated Use Reader(ContextProviderPtr, source_path) instead.
[[deprecated("Use Reader(ContextProviderPtr, source_path) for better thread safety")]]
[[deprecated("Use Reader(ContextProviderPtr, source_path) instead")]]
Reader(const std::filesystem::path &source_path);

// Non-copyable
Expand All @@ -403,7 +399,7 @@ namespace c2pa
}
Reader& operator=(Reader&& other) noexcept {
if (this != &other) {
c2pa_reader_free(c2pa_reader);
c2pa_free(c2pa_reader);
delete cpp_stream;
c2pa_reader = other.c2pa_reader;
cpp_stream = other.cpp_stream;
Expand All @@ -415,9 +411,9 @@ namespace c2pa
}

~Reader();

/// @brief Get the context associated with this Reader.
/// @return Shared pointer to the context, or nullptr if using legacy API.
/// @return Shared pointer to the context, or nullptr if using legacy/context-free API.
[[nodiscard]] inline ContextProviderPtr context() const noexcept {
return context_;
}
Expand Down Expand Up @@ -504,7 +500,7 @@ namespace c2pa
}
Signer& operator=(Signer&& other) noexcept {
if (this != &other) {
c2pa_signer_free(signer);
c2pa_free(signer);
signer = other.signer;
other.signer = nullptr;
}
Expand All @@ -527,11 +523,9 @@ namespace c2pa
{
private:
C2paBuilder *builder;
ContextProviderPtr context_; // Keeps context alive
ContextProviderPtr context_; // Keeps context alive: TODO-TMN: Rename

public:
// ===== Context-based constructors =====

/// @brief Create a Builder from a context with an empty manifest.
/// @param context Context provider to use for this builder.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
Expand All @@ -543,13 +537,11 @@ namespace c2pa
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
Builder(ContextProviderPtr context, const std::string &manifest_json);

// ===== Legacy constructor (DEPRECATED) =====

/// @brief Create a Builder from a manifest JSON string (uses global settings).
/// @param manifest_json The manifest JSON string.
/// @throws C2pa::C2paException for errors encountered by the C2PA library.
/// @deprecated Use Builder(ContextProviderPtr, manifest_json) instead.
[[deprecated("Use Builder(ContextProviderPtr, manifest_json) for better thread safety")]]
[[deprecated("Use Builder(ContextProviderPtr, manifest_json) instead")]]
Builder(const std::string &manifest_json);

// Non-copyable
Expand All @@ -562,7 +554,7 @@ namespace c2pa
}
Builder& operator=(Builder&& other) noexcept {
if (this != &other) {
c2pa_builder_free(builder);
c2pa_free(builder);
builder = other.builder;
context_ = std::move(other.context_);
other.builder = nullptr;
Expand All @@ -573,7 +565,7 @@ namespace c2pa
~Builder();

/// @brief Get the context associated with this Builder.
/// @return Shared pointer to the context, or nullptr if using legacy API.
/// @return Shared pointer to the context, or nullptr if using legacy/context-free API.
[[nodiscard]] inline ContextProviderPtr context() const noexcept {
return context_;
}
Expand Down
Loading
Loading