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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
cmake_minimum_required(VERSION 3.27)

# This is the current version of this C++ project
project(c2pa-c VERSION 0.24.0)
project(c2pa-c VERSION 0.24.1)

# Set the version of the c2pa_rs library used
set(C2PA_VERSION "0.88.0")
Expand Down
26 changes: 25 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ ifdef C2PA_RS_PATH
CMAKE_OPTS += -DC2PA_RS_PATH="$(C2PA_RS_PATH)"
endif

# Sanitizer builds need a compiler-rt that matches the running OS. On macOS 26+
# the Apple clang (Xcode 16) AddressSanitizer runtime can abort at process startup
# with "sanitizer_malloc_mac.inc CHECK failed: ((!asan_init_is_running))"
# before main() runs. If a Homebrew LLVM clang is actually installed, use it for
# sanitizer builds; otherwise fall back to the default toolchain (fine on older
# macOS and on Linux). Override with SAN_CC / SAN_CXX.
# Note: `brew --prefix llvm` prints a path even when llvm is NOT installed, so the
# binary's existence must be verified (-x) before using it.
SAN_CMAKE_OPTS :=
ifeq ($(OS),Darwin)
SAN_CC ?= $(shell c="$$(brew --prefix llvm 2>/dev/null)/bin/clang"; [ -x "$$c" ] && echo "$$c")
SAN_CXX ?= $(shell c="$$(brew --prefix llvm 2>/dev/null)/bin/clang++"; [ -x "$$c" ] && echo "$$c")
ifneq ($(SAN_CC),)
SAN_CMAKE_OPTS += -DCMAKE_C_COMPILER=$(SAN_CC) -DCMAKE_CXX_COMPILER=$(SAN_CXX)
endif
endif

# Default target
all: clean test examples

Expand Down Expand Up @@ -43,7 +60,14 @@ test-release: clean release

# Test with sanitizers (ASAN + UBSAN)
test-san: clean
cmake -S . -B $(DEBUG_BUILD_DIR) -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON $(CMAKE_OPTS)
@if [ -n "$(SAN_CC)" ]; then \
echo "Sanitizer build using $(SAN_CC)"; \
elif [ "$(OS)" = "Darwin" ]; then \
echo "NOTE: using the default toolchain for sanitizers. If tests abort at startup with"; \
echo " 'asan_init_is_running' (Apple clang on macOS 26+), run 'brew install llvm'"; \
echo " or set SAN_CC/SAN_CXX to a clang whose compiler-rt supports this OS."; \
fi
cmake -S . -B $(DEBUG_BUILD_DIR) -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON $(CMAKE_OPTS) $(SAN_CMAKE_OPTS)
cmake --build $(DEBUG_BUILD_DIR)
cd $(DEBUG_BUILD_DIR) && ctest --output-on-failure

Expand Down
303 changes: 288 additions & 15 deletions docs/selective-manifests.md

Large diffs are not rendered by default.

426 changes: 411 additions & 15 deletions docs/working-stores.md

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions include/c2pa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,20 @@ namespace c2pa
/// @note Prefer using the streaming APIs if possible.
void to_archive(const std::filesystem::path &dest_path);

/// @brief Write a single-ingredient archive for the named ingredient.
/// @param ingredient_id The ingredient's `label` if set, otherwise its `instance_id`,
/// as supplied to add_ingredient.
/// @param dest The output stream to write the ingredient archive to.
/// @note Requires the `generate_c2pa_archive` context setting to be enabled
/// (enabled by default).
/// @throws C2paException for errors encountered by the C2PA library.
void write_ingredient_archive(const std::string &ingredient_id, std::ostream &dest);

/// @brief Add an ingredient to this builder from a per-ingredient archive stream.
/// @param archive The input stream containing the archive produced by write_ingredient_archive.
/// @throws C2paException for errors encountered by the C2PA library.
void add_ingredient_from_archive(std::istream &archive);

/// @brief Create a hashed placeholder from the builder.
/// @param reserved_size The size required for a signature from the intended signer (in bytes).
/// @param format The mime format or extension of the asset.
Expand Down
20 changes: 20 additions & 0 deletions src/c2pa_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,26 @@ namespace c2pa
to_archive(*dest);
}

void Builder::write_ingredient_archive(const std::string &ingredient_id, std::ostream &dest)
{
CppOStream c_dest(dest);
int result = c2pa_builder_write_ingredient_archive(builder, ingredient_id.c_str(), c_dest.c_stream);
if (result < 0)
{
throw C2paException();
}
}

void Builder::add_ingredient_from_archive(std::istream &archive)
{
CppIStream c_archive(archive);
int result = c2pa_builder_add_ingredient_from_archive(builder, c_archive.c_stream);
if (result < 0)
{
throw C2paException();
}
}

std::vector<unsigned char> Builder::data_hashed_placeholder(uintptr_t reserve_size, const std::string &format)
{
const unsigned char *c2pa_manifest_bytes = nullptr;
Expand Down
Loading
Loading