ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_pack.c
Go to the documentation of this file.
1
10#include "mdl_pack.h"
11
12#include <stdint.h>
13#include <stdio.h>
14
15#include "mdl_export.h"
16#include "mdl_fetch.h"
17#include "mdl_fetch_internal.h"
18#include "mdl_sanitize.h"
19#include "mdl_stream_internal.h"
20#include "ra8_attributes.h"
21#include "ra8_err.h"
22
24typedef enum : uint16_t {
28
47 const char* first,
48 const char* second,
49 const char* third)
50{
51 ra8_err_t error = priv_mdl_stream_text(k_ra8_ok, stream, first);
52 error = priv_mdl_stream_text(error, stream, second);
53 return priv_mdl_stream_text(error, stream, third);
54}
55
72RA8_INTERNAL static bool internal_pack_snprintf_fit(int n, size_t cap)
73{
74 return (n >= 0) && ((size_t)n < cap);
75}
76
93internal_pack_metadata(mdl_storage_t* storage, const mdl_export_meta_t* meta, const char* dir)
94{
95 mdl_export_meta_t selected;
96 if (meta != nullptr) {
97 selected = *meta;
98 } else {
99 (void)mdl_meta_load_dir(storage, &selected, dir);
100 }
101 return selected;
102}
103
123 const char* chap_id,
124 const char* ext,
125 ra8_err_t rc)
126{
127 ra8_err_t output_error = internal_pack_text3(diagnostic, " export ", chap_id, ".");
128 output_error = priv_mdl_stream_text(output_error, diagnostic, ext);
129 output_error = priv_mdl_stream_text(output_error, diagnostic, " FAILED (err 0x");
130 output_error = priv_mdl_stream_hex(output_error, diagnostic, (uint32_t)rc);
131 (void)priv_mdl_stream_text(output_error, diagnostic, ")\n");
132}
133
160 mdl_format_t format,
161 const char* dir,
162 const char* chap_id,
163 const char* ext,
164 const mdl_export_meta_t* meta,
166 ra8_io_stream_t* output,
167 ra8_io_stream_t* diagnostic)
168{
169 const ra8_err_t drc = mdl_export_chapter_meta_ws(storage, format, dir, dir, meta, ws);
170 if (drc != k_ra8_ok) {
171 internal_pack_report_failure(diagnostic, chap_id, ext, drc);
172 return 1U;
173 }
174 ra8_err_t output_error = internal_pack_text3(output, " converted ", chap_id, " -> ");
175 output_error = priv_mdl_stream_text(output_error, output, dir);
176 output_error = priv_mdl_stream_text(output_error, output, "/*.");
177 output_error = priv_mdl_stream_text(output_error, output, ext);
178 output_error = priv_mdl_stream_text(output_error, output, "\n");
179 return (output_error == k_ra8_ok) ? 0U : 1U;
180}
181
183 mdl_format_t format,
184 const char* series_dir,
185 const char* chap_id,
186 const mdl_export_meta_t* meta,
188 ra8_io_stream_t* output,
189 ra8_io_stream_t* diagnostic)
190{
191 const char* ext = mdl_format_ext(format);
192 char dir[k_pack_dir_bytes];
193 if (!mdl_path_join(series_dir, chap_id, dir, sizeof(dir))) {
194 (void)internal_pack_text3(diagnostic, " export ", chap_id, ".");
195 (void)internal_pack_text3(diagnostic, "", ext, " path rejected, skipped\n");
196 return 1U;
197 }
198
199 const mdl_export_meta_t m = internal_pack_metadata(storage, meta, dir);
200
201 if (mdl_format_is_dir_output(format)) {
202 return internal_pack_dir_output(storage, format, dir, chap_id, ext, &m, ws, output, diagnostic);
203 }
204 char leaf[k_pack_leaf_bytes];
205 const int ln = snprintf(leaf, sizeof(leaf), "%s.%s", chap_id, ext);
206 char out[k_pack_dir_bytes];
207 if (!internal_pack_snprintf_fit(ln, sizeof(leaf)) ||
208 !mdl_path_join(series_dir, leaf, out, sizeof(out))) {
209 ra8_err_t output_error = internal_pack_text3(diagnostic, " export ", chap_id, ".");
210 output_error = priv_mdl_stream_text(output_error, diagnostic, ext);
211 (void)priv_mdl_stream_text(output_error, diagnostic, " path rejected, skipped\n");
212 return 1U;
213 }
214 const ra8_err_t rc = mdl_export_chapter_meta_ws(storage, format, dir, out, &m, ws);
215 if (rc != k_ra8_ok) {
216 internal_pack_report_failure(diagnostic, chap_id, ext, rc);
217 return 1U;
218 }
219 ra8_err_t output_error = internal_pack_text3(output, " packaged ", chap_id, ".");
220 output_error = priv_mdl_stream_text(output_error, output, ext);
221 output_error = priv_mdl_stream_text(output_error, output, "\n");
222 return (output_error == k_ra8_ok) ? 0U : 1U;
223}
224
226 mdl_format_t format,
227 const char* series_dir,
228 const char* chap_id,
230 ra8_io_stream_t* output,
231 ra8_io_stream_t* diagnostic)
232{
233 return mdl_pack_one_meta(storage, format, series_dir, chap_id, nullptr, ws, output, diagnostic);
234}
235
253 ra8_err_t rc)
254{
255 ra8_err_t output_error =
256 priv_mdl_stream_text(k_ra8_ok, diagnostic, " combine export FAILED (err 0x");
257 output_error = priv_mdl_stream_hex(output_error, diagnostic, (uint32_t)rc);
258 (void)priv_mdl_stream_text(output_error, diagnostic, ")\n");
259}
260
287 mdl_format_t format,
288 const char* dir,
289 const char* ext,
290 const char* mark,
291 const mdl_export_meta_t* meta,
293 ra8_io_stream_t* output,
294 ra8_io_stream_t* diagnostic)
295{
296 const ra8_err_t drc = mdl_export_chapter_meta_ws(storage, format, dir, dir, meta, ws);
297 if (drc != k_ra8_ok) {
299 return 1U;
300 }
301 ra8_err_t output_error = internal_pack_text3(output, " combined", mark, " -> ");
302 output_error = priv_mdl_stream_text(output_error, output, dir);
303 output_error = priv_mdl_stream_text(output_error, output, "/*.");
304 output_error = priv_mdl_stream_text(output_error, output, ext);
305 output_error = priv_mdl_stream_text(output_error, output, "\n");
306 return (output_error == k_ra8_ok) ? 0U : 1U;
307}
308
334 mdl_format_t format,
335 const char* series_dir,
336 const char* combined_rel,
337 bool incomplete,
338 const mdl_export_meta_t* meta,
340 ra8_io_stream_t* output,
341 ra8_io_stream_t* diagnostic)
342{
343 const char* ext = mdl_format_ext(format);
344 const char* mark = incomplete ? " (INCOMPLETE)" : "";
345 char dir[k_pack_dir_bytes];
346 if (!mdl_path_join(series_dir, combined_rel, dir, sizeof(dir))) {
347 (void)
348 internal_pack_text3(diagnostic, " combine export path rejected under ", series_dir, "\n");
349 return 1U;
350 }
351
352 const mdl_export_meta_t m = internal_pack_metadata(storage, meta, dir);
353
354 if (mdl_format_is_dir_output(format)) {
356 format,
357 dir,
358 ext,
359 mark,
360 &m,
361 ws,
362 output,
363 diagnostic);
364 }
365 char leaf[k_pack_leaf_bytes];
366 const int ln = incomplete ? snprintf(leaf, sizeof(leaf), "%s.INCOMPLETE.%s", combined_rel, ext)
367 : snprintf(leaf, sizeof(leaf), "%s.%s", combined_rel, ext);
368 char out[k_pack_dir_bytes];
369 if (!internal_pack_snprintf_fit(ln, sizeof(leaf)) ||
370 !mdl_path_join(series_dir, leaf, out, sizeof(out))) {
371 (void)
372 internal_pack_text3(diagnostic, " combine export path rejected under ", series_dir, "\n");
373 return 1U;
374 }
375 const ra8_err_t rc = mdl_export_chapter_meta_ws(storage, format, dir, out, &m, ws);
376 if (rc != k_ra8_ok) {
378 return 1U;
379 }
380 ra8_err_t output_error = internal_pack_text3(output, " combined", mark, " -> ");
381 output_error = priv_mdl_stream_text(output_error, output, out);
382 output_error = priv_mdl_stream_text(output_error, output, "\n");
383 return (output_error == k_ra8_ok) ? 0U : 1U;
384}
385
387 mdl_format_t format,
388 bool allow_incomplete,
389 const char* series_dir,
390 const char* combined_rel,
391 const mdl_fetch_stats_t* stats,
392 const mdl_export_meta_t* meta,
394 ra8_io_stream_t* output,
395 ra8_io_stream_t* diagnostic)
396{
397 if (stats->chapters_completed == 0U) {
398 return 0U; /* nothing was fetched to package */
399 }
400 const bool incomplete = priv_mdl_fetch_run_incomplete(stats);
401 if (incomplete) {
402 if (!allow_incomplete) {
404 diagnostic,
405 " combine: NOT packaged -- run is "
406 "incomplete (");
407 output_error = priv_mdl_stream_u64(output_error, diagnostic, stats->chapters_failed);
408 output_error = priv_mdl_stream_text(output_error, diagnostic, " chapter(s) / ");
409 output_error = priv_mdl_stream_u64(output_error, diagnostic, stats->pages_failed);
410 output_error = priv_mdl_stream_text(output_error,
411 diagnostic,
412 " page(s) failed); pass --allow-incomplete to force "
413 "a marked archive\n");
414 return (output_error == k_ra8_ok) ? 0U : 1U;
415 }
416 }
417 return internal_pack_combined_dir(storage,
418 format,
419 series_dir,
420 combined_rel,
421 incomplete,
422 meta,
423 ws,
424 output,
425 diagnostic);
426}
427
429 mdl_format_t format,
430 bool allow_incomplete,
431 const char* series_dir,
432 const char* combined_rel,
433 const mdl_fetch_stats_t* stats,
435 ra8_io_stream_t* output,
436 ra8_io_stream_t* diagnostic)
437{
438 return mdl_pack_combined_meta(storage,
439 format,
440 allow_incomplete,
441 series_dir,
442 combined_rel,
443 stats,
444 nullptr,
445 ws,
446 output,
447 diagnostic);
448}
Package a downloaded chapter folder into a reader-openable container.
bool mdl_format_is_dir_output(mdl_format_t fmt)
Whether fmt writes per-page sibling files rather than one container.
Definition mdl_export.c:84
struct mdl_export_workspace mdl_export_workspace_t
Caller-owned bounded arena for all exporter scratch state.
const char * mdl_format_ext(mdl_format_t fmt)
File extension (without dot) for a format, e.g.
Definition mdl_export.c:58
ra8_err_t mdl_export_chapter_meta_ws(mdl_storage_t *storage, mdl_format_t fmt, const char *chapter_dir, const char *out_path, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws)
Package a chapter with explicit metadata and caller-owned workspace.
Definition mdl_export.c:532
ra8_err_t mdl_meta_load_dir(mdl_storage_t *storage, mdl_export_meta_t *meta, const char *dir)
Load metadata from a directory by looking for metadata files.
bool priv_mdl_fetch_run_incomplete(const mdl_fetch_stats_t *stats)
Whether a finished run left anything unfetched (chapter or page).
Definition mdl_fetch.c:115
State-aware chapter/page download orchestrator for the media downloader.
Module-private fetch-loop decisions promoted for host unit tests and the CLI's end-of-run reporting.
mdl_format_t
Artifact format selected by a media-download composition root.
Definition mdl_format.h:35
static void internal_pack_report_failure(ra8_io_stream_t *diagnostic, const char *chap_id, const char *ext, ra8_err_t rc)
Report one chapter's export failure with its error code.
Definition mdl_pack.c:122
static size_t internal_pack_dir_output(mdl_storage_t *storage, mdl_format_t format, const char *dir, const char *chap_id, const char *ext, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package one chapter into a directory-output format (e.g.
Definition mdl_pack.c:159
static size_t internal_pack_combined_dir(mdl_storage_t *storage, mdl_format_t format, const char *series_dir, const char *combined_rel, bool incomplete, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package a combined chapter folder into the selected format.
Definition mdl_pack.c:333
size_t mdl_pack_one(mdl_storage_t *storage, mdl_format_t format, const char *series_dir, const char *chap_id, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package one downloaded chapter folder into format.
Definition mdl_pack.c:225
mdl_pack_size_t
Path buffer sizes for a composed archive leaf and directory.
Definition mdl_pack.c:24
@ k_pack_leaf_bytes
Composed archive/dir leaf name.
Definition mdl_pack.c:25
@ k_pack_dir_bytes
Directory-path buffer.
Definition mdl_pack.c:26
size_t mdl_pack_combined_meta(mdl_storage_t *storage, mdl_format_t format, bool allow_incomplete, const char *series_dir, const char *combined_rel, const mdl_fetch_stats_t *stats, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package a combined page folder into format with rich metadata.
Definition mdl_pack.c:386
static mdl_export_meta_t internal_pack_metadata(mdl_storage_t *storage, const mdl_export_meta_t *meta, const char *dir)
Copy explicit metadata or load it from a combined directory.
Definition mdl_pack.c:93
static size_t internal_pack_combined_dir_output(mdl_storage_t *storage, mdl_format_t format, const char *dir, const char *ext, const char *mark, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Combine-package one directory into a directory-output format.
Definition mdl_pack.c:286
static void internal_pack_report_combine_failure(ra8_io_stream_t *diagnostic, ra8_err_t rc)
Report a combine-export failure with its error code.
Definition mdl_pack.c:252
static bool internal_pack_snprintf_fit(int n, size_t cap)
Test whether an snprintf result fully fit its destination.
Definition mdl_pack.c:72
size_t mdl_pack_combined(mdl_storage_t *storage, mdl_format_t format, bool allow_incomplete, const char *series_dir, const char *combined_rel, const mdl_fetch_stats_t *stats, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package a combined page directory when completion policy permits.
Definition mdl_pack.c:428
size_t mdl_pack_one_meta(mdl_storage_t *storage, mdl_format_t format, const char *series_dir, const char *chap_id, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws, ra8_io_stream_t *output, ra8_io_stream_t *diagnostic)
Package one downloaded chapter folder into format with rich metadata.
Definition mdl_pack.c:182
static ra8_err_t internal_pack_text3(ra8_io_stream_t *stream, const char *first, const char *second, const char *third)
Append three borrowed packaging fragments to one stream.
Definition mdl_pack.c:46
Archive packaging of downloaded page folders for the mdl CLI.
Neutralise untrusted names before they reach a filesystem or XML sink.
bool mdl_path_join(const char *parent, const char *seg, char *out, size_t cap)
Join one safe child segment under a parent directory path.
ra8_err_t priv_mdl_stream_hex(ra8_err_t prior, ra8_io_stream_t *stream, uint32_t value)
Append one hexadecimal error/status value after prior success.
Definition mdl_stream.c:26
ra8_err_t priv_mdl_stream_text(ra8_err_t prior, ra8_io_stream_t *stream, const char *text)
Append text unless an earlier operation already failed.
Definition mdl_stream.c:16
ra8_err_t priv_mdl_stream_u64(ra8_err_t prior, ra8_io_stream_t *stream, uint64_t value)
Append one unsigned integer unless an earlier append failed.
Definition mdl_stream.c:21
Private bounded text helpers over the portable byte-stream contract.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Rich series and chapter metadata for export containers (ComicInfo.xml, EPUB OPF).
Definition mdl_export.h:96
Tallies a fetch run reports back (all zero-initialised by the run).
Definition mdl_fetch.h:65
size_t chapters_completed
Chapters finished (all pages present) this run.
Definition mdl_fetch.h:66
size_t chapters_failed
Chapters left partial by a page failure.
Definition mdl_fetch.h:68
size_t pages_failed
Page fetches that failed or robots refused.
Definition mdl_fetch.h:71
One non-reentrant downloader filesystem dependency bundle.
Definition mdl_storage.h:40
Caller-allocated byte-stream handle binding a sink to its context.