c2pa-cpp
C++ API for the C2PA SDK
Loading...
Searching...
No Matches
c2pa::detail Namespace Reference

Classes

struct  StreamSeekTraits
 Traits (templated): how to seek and get position for a given stream type. More...
 
struct  StreamSeekTraits< std::iostream >
 
struct  StreamSeekTraits< std::istream >
 
struct  StreamSeekTraits< std::ostream >
 

Functions

bool error_indicates_manifest_not_found (const char *message) noexcept
 True if the C2PA error message indicates no JUMBF / manifest in the asset (ManifestNotFound).
 
std::vector< std::string > c_mime_types_to_vector (const char *const *mime_types, uintptr_t count)
 Converts a C array of C strings to a std::vector of std::string.
 
constexpr std::ios_base::seekdir whence_to_seekdir (C2paSeekMode whence) noexcept
 Maps C2PA seek mode to std::ios seek direction.
 
template<typename Stream >
bool is_stream_usable (Stream *s) noexcept
 Check if stream is in valid state for I/O operations.
 
template<typename Stream >
intptr_t stream_seeker (StreamContext *context, intptr_t offset, C2paSeekMode whence)
 
template<typename Stream >
intptr_t stream_reader (StreamContext *context, uint8_t *buffer, intptr_t size)
 
template<typename Stream , typename Op >
intptr_t stream_op (StreamContext *context, Op op)
 
template<typename Stream >
intptr_t stream_writer (StreamContext *context, const uint8_t *buffer, intptr_t size)
 Writer impl.
 
template<typename Stream >
intptr_t stream_flusher (StreamContext *context)
 Flusher impl.
 
template<typename StreamType >
std::unique_ptr< StreamTypeopen_file_binary (const std::filesystem::path &path)
 Open a binary file stream with error handling.
 
std::string extract_file_extension (const std::filesystem::path &path) noexcept
 Extract file extension without the leading dot.
 
std::string normalize_format (const std::string &format)
 Trim and lowercase a caller-supplied format; empty when format is blank.
 
std::string resolve_format (const std::string &format)
 Resolve a format that must be stated explicitly. These paths never infer the container type from content, so a blank format is rejected.
 
template<typename T >
std::string c_string_to_string (T *c_result)
 Convert C string result to C++ string with cleanup.
 
std::vector< unsigned charto_byte_vector (const unsigned char *data, int64_t size)
 Convert C byte array result to C++ vector.
 

Variables

constexpr const charkDetectFormatFromContent = ""
 Format asking the library to determine the container type from content.
 
constexpr const charkFormatWhitespace = " \t\n\r\f\v"
 ASCII whitespace ignored around a format.
 

Function Documentation

◆ c_mime_types_to_vector()

std::vector< std::string > c2pa::detail::c_mime_types_to_vector ( const char *const mime_types,
uintptr_t  count 
)
inline

Converts a C array of C strings to a std::vector of std::string.

Parameters
mime_typesPointer to an array of C strings (const char*).
countNumber of elements in the array.
Returns
A std::vector containing the strings from the input array.

This function takes ownership of the input array and frees it using c2pa_free_string_array().

48 {
49 std::vector<std::string> result;
50 if (mime_types == nullptr) { return result; }
51
52 try {
53 result.reserve(count);
54 for(uintptr_t i = 0; i < count; i++) {
55 if (mime_types[i] != nullptr) {
56 result.emplace_back(mime_types[i]);
57 }
58 }
59 } catch (...) {
60 c2pa_free_string_array(mime_types, count);
61 throw;
62 }
63
64 c2pa_free_string_array(mime_types, count);
65 return result;
66}

◆ c_string_to_string()

template<typename T >
std::string c2pa::detail::c_string_to_string ( T c_result)
inline

Convert C string result to C++ string with cleanup.

Parameters
c_resultRaw C string from C API
Returns
C++ string (throws if null)
289 {
290 if (c_result == nullptr) {
291 throw C2paException();
292 }
293 std::string str(c_result);
294 c2pa_free(c_result);
295 return str;
296}
Exception class for C2pa errors. This class is used to throw exceptions for errors encountered by the...
Definition c2pa.hpp:87

◆ error_indicates_manifest_not_found()

bool c2pa::detail::error_indicates_manifest_not_found ( const char message)
inlinenoexcept

True if the C2PA error message indicates no JUMBF / manifest in the asset (ManifestNotFound).

38 {
39 return message != nullptr && std::strstr(message, "ManifestNotFound") != nullptr;
40}

◆ extract_file_extension()

std::string c2pa::detail::extract_file_extension ( const std::filesystem::path &  path)
inlinenoexcept

Extract file extension without the leading dot.

Parameters
pathFilesystem path
Returns
Extension string (e.g., "jpg" not ".jpg")
243 {
244 auto ext = path.extension().string();
245 return ext.empty() ? "" : ext.substr(1);
246}

◆ is_stream_usable()

template<typename Stream >
bool c2pa::detail::is_stream_usable ( Stream s)
inlinenoexcept

Check if stream is in valid state for I/O operations.

80 {
81 return s && !s->bad();
82}

◆ normalize_format()

std::string c2pa::detail::normalize_format ( const std::string &  format)
inline

Trim and lowercase a caller-supplied format; empty when format is blank.

Empty means detection from content, so this alone is enough wherever a blank format is allowed to request that.

260 {
261 const auto first = format.find_first_not_of(kFormatWhitespace);
262 if (first == std::string::npos) {
263 return {}; // Empty or all whitespace.
264 }
265 const auto last = format.find_last_not_of(kFormatWhitespace);
266 std::string normalized(std::string_view(format).substr(first, last - first + 1));
267 std::transform(normalized.begin(), normalized.end(), normalized.begin(),
268 [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
269 return normalized;
270}

◆ open_file_binary()

template<typename StreamType >
std::unique_ptr< StreamType > c2pa::detail::open_file_binary ( const std::filesystem::path &  path)
inline

Open a binary file stream with error handling.

Template Parameters
StreamTypestd::ifstream or std::ofstream
Parameters
pathPath to the file
Returns
Unique pointer to opened stream
229{
230 auto stream = std::make_unique<StreamType>(
231 path,
232 std::ios_base::binary
233 );
234 if (!stream->is_open()) {
235 throw C2paException("Failed to open file: " + path.string());
236 }
237 return stream;
238}

◆ resolve_format()

std::string c2pa::detail::resolve_format ( const std::string &  format)
inline

Resolve a format that must be stated explicitly. These paths never infer the container type from content, so a blank format is rejected.

Returns
format trimmed and lowercased.
Exceptions
C2paExceptionif format is blank.
277 {
278 std::string normalized = normalize_format(format);
279 if (normalized.empty()) {
280 throw C2paException("An explicit format is required.");
281 }
282 return normalized;
283}
std::string normalize_format(const std::string &format)
Trim and lowercase a caller-supplied format; empty when format is blank.
Definition c2pa_internal.hpp:260

◆ stream_flusher()

template<typename Stream >
intptr_t c2pa::detail::stream_flusher ( StreamContext context)

Flusher impl.

216 {
217 return stream_op<Stream>(context, [](Stream* s) {
218 s->flush();
219 return 0;
220 });
221}

◆ stream_op()

template<typename Stream , typename Op >
intptr_t c2pa::detail::stream_op ( StreamContext *  context,
Op  op 
)

Get stream from context, used by writer and flusher. Exceptions must not unwind into Rust/C, so any throw is converted to an IoError return.

186 {
187 try {
188 auto* stream = reinterpret_cast<Stream*>(context);
189 if (!is_stream_usable(stream)) {
190 return stream_error_return(StreamError::IoError);
191 }
192 const intptr_t result = op(stream);
193 if (stream->fail()) {
194 return stream_error_return(StreamError::InvalidArgument);
195 }
196 if (stream->bad()) {
197 return stream_error_return(StreamError::IoError);
198 }
199 return result;
200 } catch (...) {
201 return stream_error_return(StreamError::IoError);
202 }
203}
bool is_stream_usable(Stream *s) noexcept
Check if stream is in valid state for I/O operations.
Definition c2pa_internal.hpp:80
int stream_error_return(StreamError e) noexcept
Set errno from StreamError and return error sentinel.
Definition c2pa.hpp:79

◆ stream_reader()

template<typename Stream >
intptr_t c2pa::detail::stream_reader ( StreamContext context,
uint8_t buffer,
intptr_t  size 
)

Reader impl. Exceptions must not unwind into Rust/C, so any throw is converted to an IoError return.

152 {
153 if (!context || !buffer) {
154 return stream_error_return(StreamError::InvalidArgument);
155 }
156 if (size < 0) {
157 return stream_error_return(StreamError::InvalidArgument);
158 }
159 if (size == 0) {
160 return 0;
161 }
162 try {
163 auto* stream = reinterpret_cast<Stream*>(context);
164 if (!is_stream_usable(stream)) {
165 return stream_error_return(StreamError::IoError);
166 }
167 stream->read(reinterpret_cast<char*>(buffer), size);
168 if (stream->fail()) {
169 if (!stream->eof()) {
170 return stream_error_return(StreamError::InvalidArgument);
171 }
172 }
173 if (stream->bad()) {
174 return stream_error_return(StreamError::IoError);
175 }
176 return static_cast<intptr_t>(stream->gcount());
177 } catch (...) {
178 return stream_error_return(StreamError::IoError);
179 }
180}

◆ stream_seeker()

template<typename Stream >
intptr_t c2pa::detail::stream_seeker ( StreamContext context,
intptr_t  offset,
C2paSeekMode  whence 
)

Seeker impl. Exceptions must not unwind into Rust/C, so any throw is converted to an IoError return.

123 {
124 try {
125 auto* stream = reinterpret_cast<Stream*>(context);
126 if (!is_stream_usable(stream)) {
127 return stream_error_return(StreamError::IoError);
128 }
129 const std::ios_base::seekdir dir = whence_to_seekdir(whence);
130 stream->clear();
131 StreamSeekTraits<Stream>::seek(stream, offset, dir);
132 if (stream->fail()) {
133 return stream_error_return(StreamError::InvalidArgument);
134 }
135 if (stream->bad()) {
136 return stream_error_return(StreamError::IoError);
137 }
138 const int64_t pos = StreamSeekTraits<Stream>::tell(stream);
139 if (pos < 0) {
140 return stream_error_return(StreamError::IoError);
141 }
142 return static_cast<intptr_t>(pos);
143 } catch (...) {
144 return stream_error_return(StreamError::IoError);
145 }
146}

◆ stream_writer()

template<typename Stream >
intptr_t c2pa::detail::stream_writer ( StreamContext context,
const uint8_t buffer,
intptr_t  size 
)

Writer impl.

207 {
208 return stream_op<Stream>(context, [buffer, size](Stream* s) {
209 s->write(reinterpret_cast<const char*>(buffer), size);
210 return size;
211 });
212}

◆ to_byte_vector()

std::vector< unsigned char > c2pa::detail::to_byte_vector ( const unsigned char data,
int64_t  size 
)
inline

Convert C byte array result to C++ vector.

Parameters
dataRaw byte array from C API
sizeSize of the byte array (result from C API call)
Returns
Vector containing the bytes (throws if null or negative size)

This helper extracts the pattern of checking C API results, copying to a vector, and freeing the C-allocated memory. The C API contract is: if result < 0, the operation failed. A null data pointer with size == 0 is a valid empty result (the C API returns null for empty byte arrays).

307 {
308 if (size < 0 || (data == nullptr && size > 0)) {
309 c2pa_free(data); // May be null or allocated, c2pa_free handles both
310 throw C2paException();
311 }
312 if (size == 0) {
313 c2pa_free(data);
314 return {};
315 }
316
317 auto result = std::vector<unsigned char>(data, data + size);
318 c2pa_free(data);
319 return result;
320}

◆ whence_to_seekdir()

constexpr std::ios_base::seekdir c2pa::detail::whence_to_seekdir ( C2paSeekMode  whence)
constexprnoexcept

Maps C2PA seek mode to std::ios seek direction.

69 {
70 switch (whence) {
71 case C2paSeekMode::Start: return std::ios_base::beg;
72 case C2paSeekMode::Current: return std::ios_base::cur;
73 case C2paSeekMode::End: return std::ios_base::end;
74 default: return std::ios_base::beg;
75 }
76}

Variable Documentation

◆ kDetectFormatFromContent

constexpr const char* c2pa::detail::kDetectFormatFromContent = ""
inlineconstexpr

Format asking the library to determine the container type from content.

The C API rejects a null format, so absent must be spelled empty.

◆ kFormatWhitespace

constexpr const char* c2pa::detail::kFormatWhitespace = " \t\n\r\f\v"
inlineconstexpr

ASCII whitespace ignored around a format.

Formats are MIME types or extensions, so non-ASCII spaces are deliberately excluded.