c2pa-c
C++ API for c2pa-c library
Loading...
Searching...
No Matches
c2pa_internal.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_internal.hpp
14/// @brief Internal implementation details shared across c2pa_cpp source files.
15/// @details This header is private to the library implementation and not installed,
16/// as it is used to share code inside c2pa_cpp SDK.
17
18#ifndef C2PA_INTERNAL_HPP
19#define C2PA_INTERNAL_HPP
20
21#include <cstring>
22#include <fstream>
23#include <filesystem>
24#include <string>
25#include <vector>
26#include <memory>
27
28#include "c2pa.h"
29#include "c2pa.hpp"
30
31namespace c2pa {
32namespace detail {
33
34/// @brief Converts a C array of C strings to a std::vector of std::string.
35/// @param mime_types Pointer to an array of C strings (const char*).
36/// @param count Number of elements in the array.
37/// @return A std::vector containing the strings from the input array.
38/// @details This function takes ownership of the input array and frees it
39/// using c2pa_free_string_array().
40inline std::vector<std::string> c_mime_types_to_vector(const char* const* mime_types, uintptr_t count) {
41 std::vector<std::string> result;
42 if (mime_types == nullptr) { return result; }
43
44 result.reserve(count);
45 for(uintptr_t i = 0; i < count; i++) {
46 result.emplace_back(mime_types[i]);
47 }
48
49 c2pa_free_string_array(mime_types, count);
50 return result;
51}
52
53/// Maps C2PA seek mode to std::ios seek direction.
54constexpr std::ios_base::seekdir whence_to_seekdir(C2paSeekMode whence) noexcept {
55 switch (whence) {
56 case C2paSeekMode::Start: return std::ios_base::beg;
57 case C2paSeekMode::Current: return std::ios_base::cur;
58 case C2paSeekMode::End: return std::ios_base::end;
59 default: return std::ios_base::beg;
60 }
61}
62
63/// Check if stream is in valid state for I/O operations
64template<typename Stream>
65inline bool is_stream_usable(Stream* s) noexcept {
66 return s && !s->bad();
67}
68
69/// Traits (templated): how to seek and get position for a given stream type.
70template<typename Stream>
72
73template<>
74struct StreamSeekTraits<std::istream> {
75 static void seek(std::istream* s, intptr_t offset, std::ios_base::seekdir dir) {
76 s->seekg(offset, dir);
77 }
78 static int64_t tell(std::istream* s) {
79 return static_cast<int64_t>(s->tellg());
80 }
81};
82
83template<>
84struct StreamSeekTraits<std::ostream> {
85 static void seek(std::ostream* s, intptr_t offset, std::ios_base::seekdir dir) {
86 s->seekp(offset, dir);
87 }
88 static int64_t tell(std::ostream* s) {
89 return static_cast<int64_t>(s->tellp());
90 }
91};
92
93template<>
94struct StreamSeekTraits<std::iostream> {
95 static void seek(std::iostream* s, intptr_t offset, std::ios_base::seekdir dir) {
96 s->seekg(offset, dir);
97 s->seekp(offset, dir);
98 }
99 static int64_t tell(std::iostream* s) {
100 return static_cast<int64_t>(s->tellp());
101 }
102};
103
104/// Seeker impl.
105template<typename Stream>
106intptr_t stream_seeker(StreamContext* context, intptr_t offset, C2paSeekMode whence) {
107 auto* stream = reinterpret_cast<Stream*>(context);
108 if (!is_stream_usable(stream)) {
110 }
111 const std::ios_base::seekdir dir = whence_to_seekdir(whence);
112 stream->clear();
113 StreamSeekTraits<Stream>::seek(stream, offset, dir);
114 if (stream->fail()) {
116 }
117 if (stream->bad()) {
119 }
120 const int64_t pos = StreamSeekTraits<Stream>::tell(stream);
121 if (pos < 0) {
123 }
124 return static_cast<intptr_t>(pos);
125}
126
127/// Reader impl.
128template<typename Stream>
129intptr_t stream_reader(StreamContext* context, uint8_t* buffer, intptr_t size) {
130 if (!context || !buffer) {
132 }
133 if (size < 0) {
135 }
136 if (size == 0) {
137 return 0;
138 }
139 auto* stream = reinterpret_cast<Stream*>(context);
140 if (!is_stream_usable(stream)) {
142 }
143 stream->read(reinterpret_cast<char*>(buffer), size);
144 if (stream->fail()) {
145 if (!stream->eof()) {
147 }
148 }
149 if (stream->bad()) {
151 }
152 return static_cast<intptr_t>(stream->gcount());
153}
154
155/// Get stream from context, used by writer and flusher.
156template<typename Stream, typename Op>
157intptr_t stream_op(StreamContext* context, Op op) {
158 auto* stream = reinterpret_cast<Stream*>(context);
159 if (!is_stream_usable(stream)) {
161 }
162 const intptr_t result = op(stream);
163 if (stream->fail()) {
165 }
166 if (stream->bad()) {
168 }
169 return result;
170}
171
172/// Writer impl.
173template<typename Stream>
174intptr_t stream_writer(StreamContext* context, const uint8_t* buffer, intptr_t size) {
175 return stream_op<Stream>(context, [buffer, size](Stream* s) {
176 s->write(reinterpret_cast<const char*>(buffer), size);
177 return size;
178 });
179}
180
181/// Flusher impl.
182template<typename Stream>
184 return stream_op<Stream>(context, [](Stream* s) {
185 s->flush();
186 return 0;
187 });
188}
189
190/// @brief Open a binary file stream with error handling
191/// @tparam StreamType std::ifstream or std::ofstream
192/// @param path Path to the file
193/// @return Unique pointer to opened stream
194template<typename StreamType>
195inline std::unique_ptr<StreamType> open_file_binary(const std::filesystem::path &path)
196{
197 auto stream = std::make_unique<StreamType>(
198 path,
199 std::ios_base::binary
200 );
201 if (!stream->is_open()) {
202 throw C2paException("Failed to open file: " + path.string());
203 }
204 return stream;
205}
206
207/// @brief Extract file extension without the leading dot
208/// @param path Filesystem path
209/// @return Extension string (e.g., "jpg" not ".jpg")
210inline std::string extract_file_extension(const std::filesystem::path &path) noexcept {
211 auto ext = path.extension().string();
212 return ext.empty() ? "" : ext.substr(1);
213}
214
215/// @brief Convert C string result to C++ string with cleanup
216/// @param c_result Raw C string from C API
217/// @return C++ string (throws if null)
218template<typename T>
219inline std::string c_string_to_string(T* c_result) {
220 if (c_result == nullptr) {
221 throw C2paException();
222 }
223 std::string str(c_result);
225 return str;
226}
227
228/// @brief Convert C byte array result to C++ vector
229/// @param data Raw byte array from C API
230/// @param size Size of the byte array (result from C API call)
231/// @return Vector containing the bytes (throws if null or negative size)
232/// @details This helper extracts the pattern of checking C API results,
233/// copying to a vector, and freeing the C-allocated memory.
234/// The C API contract is: if result < 0 or data == nullptr, the operation failed.
235inline std::vector<unsigned char> to_byte_vector(const unsigned char* data, int64_t size) {
236 if (size < 0 || data == nullptr) {
237 c2pa_free(data); // May be null or allocated, c2pa_free handles both
238 throw C2paException();
239 }
240
241 auto result = std::vector<unsigned char>(data, data + size);
243 return result;
244}
245
246} // namespace detail
247} // namespace c2pa
248
249#endif // C2PA_INTERNAL_HPP
C++ wrapper for the C2PA C library.
Exception class for C2pa errors. This class is used to throw exceptions for errors encountered by the...
Definition c2pa.hpp:86
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.
Definition c2pa_internal.hpp:40
intptr_t stream_writer(StreamContext *context, const uint8_t *buffer, intptr_t size)
Writer impl.
Definition c2pa_internal.hpp:174
intptr_t stream_op(StreamContext *context, Op op)
Get stream from context, used by writer and flusher.
Definition c2pa_internal.hpp:157
std::string extract_file_extension(const std::filesystem::path &path) noexcept
Extract file extension without the leading dot.
Definition c2pa_internal.hpp:210
intptr_t stream_flusher(StreamContext *context)
Flusher impl.
Definition c2pa_internal.hpp:183
constexpr std::ios_base::seekdir whence_to_seekdir(C2paSeekMode whence) noexcept
Maps C2PA seek mode to std::ios seek direction.
Definition c2pa_internal.hpp:54
bool is_stream_usable(Stream *s) noexcept
Check if stream is in valid state for I/O operations.
Definition c2pa_internal.hpp:65
std::vector< unsigned char > to_byte_vector(const unsigned char *data, int64_t size)
Convert C byte array result to C++ vector.
Definition c2pa_internal.hpp:235
intptr_t stream_reader(StreamContext *context, uint8_t *buffer, intptr_t size)
Reader impl.
Definition c2pa_internal.hpp:129
std::string c_string_to_string(T *c_result)
Convert C string result to C++ string with cleanup.
Definition c2pa_internal.hpp:219
intptr_t stream_seeker(StreamContext *context, intptr_t offset, C2paSeekMode whence)
Seeker impl.
Definition c2pa_internal.hpp:106
std::unique_ptr< StreamType > open_file_binary(const std::filesystem::path &path)
Open a binary file stream with error handling.
Definition c2pa_internal.hpp:195
Definition c2pa.hpp:51
int stream_error_return(StreamError e) noexcept
Set errno from StreamError and return error sentinel.
Definition c2pa.hpp:78
static void seek(std::iostream *s, intptr_t offset, std::ios_base::seekdir dir)
Definition c2pa_internal.hpp:95
static int64_t tell(std::iostream *s)
Definition c2pa_internal.hpp:99
static int64_t tell(std::istream *s)
Definition c2pa_internal.hpp:78
static void seek(std::istream *s, intptr_t offset, std::ios_base::seekdir dir)
Definition c2pa_internal.hpp:75
static void seek(std::ostream *s, intptr_t offset, std::ios_base::seekdir dir)
Definition c2pa_internal.hpp:85
static int64_t tell(std::ostream *s)
Definition c2pa_internal.hpp:88
Traits (templated): how to seek and get position for a given stream type.
Definition c2pa_internal.hpp:71