ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_state.c
Go to the documentation of this file.
1
9#include "mdl_state.h"
10
11#include <limits.h>
12#include <math.h>
13#include <stdint.h>
14#include <stdio.h>
15#include <string.h>
16
17#include "mdl_state_internal.h"
18#include "ra8_attributes.h"
19
26
44 uint16_t response_status)
45{
46 const bool legacy_unknown = (fetched_at == 0) && (response_status == 0U);
47 const bool http_status = (response_status >= (uint16_t)k_state_http_status_min) &&
48 (response_status <= (uint16_t)k_state_http_status_max);
49 return legacy_unknown || ((fetched_at >= 0) && http_status);
50}
51
53{
54 if (st == nullptr) {
55 return;
56 }
57 memset(st, 0, sizeof(*st));
58 st->version = (uint16_t)k_mdl_state_version;
59}
60
62RA8_PRIV void priv_mdl_state_set_opt(char* dst, size_t cap, const char* val)
63{
64 if (val != nullptr) {
65 (void)snprintf(dst, cap, "%s", val);
66 }
67}
68
70RA8_PRIV bool priv_mdl_state_field_valid(const char* text, size_t cap)
71{
72 if (text == nullptr) {
73 return false;
74 }
75 const size_t len = strnlen(text, cap);
76 return (len < cap) && (strpbrk(text, "\t\r\n") == nullptr);
77}
78
95RA8_PRIV bool priv_mdl_state_relative_path_valid(const char* path, size_t cap)
96{
97 if (!priv_mdl_state_field_valid(path, cap)) {
98 return false;
99 }
100 if (path[0] == '\0') {
101 return true;
102 }
103 if ((path[0] == '/') || (path[0] == '\\')) {
104 return false;
105 }
106 const char* part = path;
107 while (*part != '\0') {
108 const char* end = strpbrk(part, "/\\");
109 const size_t len = (end != nullptr) ? (size_t)(end - part) : strlen(part);
110 if ((len == 0U) || ((len == 2U) && (part[0] == '.') && (part[1] == '.'))) {
111 return false;
112 }
113 if (end == nullptr) {
114 break;
115 }
116 part = end + 1;
117 }
118 return true;
119}
120
136RA8_INTERNAL static bool internal_mdl_state_chapter_number_valid(double number, bool known)
137{
138 return isfinite(number) && (known || ((number == 0.0) && !signbit(number)));
139}
140
143{
144 if ((st->version != (uint16_t)k_mdl_state_version) ||
145 (st->chapter_count > (uint16_t)k_mdl_max_chapters) ||
146 (st->page_rec_count > (uint32_t)k_mdl_max_page_recs) ||
152 !priv_mdl_state_field_valid(st->summary, sizeof(st->summary)) ||
153 !priv_mdl_state_field_valid(st->writer, sizeof(st->writer)) ||
154 !priv_mdl_state_field_valid(st->artist, sizeof(st->artist)) ||
157 !priv_mdl_state_field_valid(st->language, sizeof(st->language)) ||
160 return false;
161 }
162 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
163 const mdl_chapter_rec_t* chapter = &st->chapters[i];
164 if (!priv_mdl_state_field_valid(chapter->chapter_id, sizeof(chapter->chapter_id)) ||
165 !priv_mdl_state_field_valid(chapter->source_url, sizeof(chapter->source_url)) ||
166 !priv_mdl_state_field_valid(chapter->title, sizeof(chapter->title)) ||
168 (chapter->pages_done > chapter->page_count) ||
169 (chapter->complete &&
170 ((chapter->page_count == 0U) || (chapter->pages_done != chapter->page_count)))) {
171 return false;
172 }
173 }
174 for (uint32_t i = 0U; i < st->page_rec_count; ++i) {
175 const mdl_page_rec_t* page = &st->pages[i];
176 if (!priv_mdl_state_field_valid(page->rel_path, sizeof(page->rel_path)) ||
177 !priv_mdl_state_field_valid(page->etag, sizeof(page->etag)) ||
180 return false;
181 }
182 }
183 return true;
184}
185
187 const char* summary,
188 const char* writer,
189 const char* artist,
190 const char* cover_url,
191 const char* cover_path,
192 const char* language,
194{
195 if ((st == nullptr) || !priv_mdl_state_field_valid(summary, sizeof(st->summary)) ||
196 !priv_mdl_state_field_valid(writer, sizeof(st->writer)) ||
197 !priv_mdl_state_field_valid(artist, sizeof(st->artist)) ||
198 !priv_mdl_state_field_valid(cover_url, sizeof(st->cover_url)) ||
199 !priv_mdl_state_relative_path_valid(cover_path, sizeof(st->cover_path)) ||
200 !priv_mdl_state_field_valid(language, sizeof(st->language)) ||
201 ((direction != k_mdl_state_read_ltr) && (direction != k_mdl_state_read_rtl))) {
202 return false;
203 }
204 char next_summary[k_mdl_summary_max] = {};
205 char next_writer[k_mdl_person_max] = {};
206 char next_artist[k_mdl_person_max] = {};
207 char next_cover_url[k_mdl_url_max] = {};
208 char next_cover_path[k_mdl_relpath_max] = {};
209 char next_language[k_mdl_language_max] = {};
210 (void)snprintf(next_summary, sizeof(next_summary), "%s", summary);
211 (void)snprintf(next_writer, sizeof(next_writer), "%s", writer);
212 (void)snprintf(next_artist, sizeof(next_artist), "%s", artist);
213 (void)snprintf(next_cover_url, sizeof(next_cover_url), "%s", cover_url);
214 (void)snprintf(next_cover_path, sizeof(next_cover_path), "%s", cover_path);
215 (void)snprintf(next_language, sizeof(next_language), "%s", language);
216 memcpy(st->summary, next_summary, sizeof(st->summary));
217 memcpy(st->writer, next_writer, sizeof(st->writer));
218 memcpy(st->artist, next_artist, sizeof(st->artist));
219 memcpy(st->cover_url, next_cover_url, sizeof(st->cover_url));
220 memcpy(st->cover_path, next_cover_path, sizeof(st->cover_path));
221 memcpy(st->language, next_language, sizeof(st->language));
222 st->reading_direction = direction;
223 return true;
224}
225
227 const char* url,
228 const char* title,
229 const char* site_name,
230 const char* site_host,
231 const char* config_path)
232{
233 if (st == nullptr) {
234 return;
235 }
236 priv_mdl_state_set_opt(st->series_url, sizeof(st->series_url), url);
237 priv_mdl_state_set_opt(st->series_title, sizeof(st->series_title), title);
238 priv_mdl_state_set_opt(st->site_name, sizeof(st->site_name), site_name);
239 priv_mdl_state_set_opt(st->site_host, sizeof(st->site_host), site_host);
240 priv_mdl_state_set_opt(st->config_path, sizeof(st->config_path), config_path);
241}
242
244{
245 if ((st == nullptr) || (id == nullptr)) {
246 return nullptr;
247 }
248 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
249 if (strcmp(st->chapters[i].chapter_id, id) == 0) {
250 return &st->chapters[i];
251 }
252 }
253 return nullptr;
254}
255
257mdl_state_add_chapter(mdl_state_t* st, const char* id, const char* url, long number)
258{
259 return mdl_state_add_chapter_numbered(st, id, url, (double)number, number != 0L);
260}
261
263 const char* id,
264 const char* url,
265 double number,
266 bool number_known)
267{
268 if ((st == nullptr) || (id == nullptr) || (url == nullptr)) {
269 return nullptr;
270 }
273 !internal_mdl_state_chapter_number_valid(number, number_known)) {
274 return nullptr;
275 }
276 mdl_chapter_rec_t* existing = mdl_state_find_chapter(st, id);
277 if (existing != nullptr) {
278 return existing;
279 }
280 if (st->chapter_count >= (uint16_t)k_mdl_max_chapters) {
281 return nullptr;
282 }
284 memset(rec, 0, sizeof(*rec));
285 (void)snprintf(rec->chapter_id, sizeof(rec->chapter_id), "%s", id);
286 (void)snprintf(rec->source_url, sizeof(rec->source_url), "%s", url);
287 rec->number = number;
288 rec->number_known = number_known;
289 st->chapter_count += 1U;
290 return rec;
291}
292
294 const char* title,
295 double number,
296 bool number_known)
297{
298 if ((chapter == nullptr) || !priv_mdl_state_field_valid(title, sizeof(chapter->title)) ||
299 !internal_mdl_state_chapter_number_valid(number, number_known)) {
300 return false;
301 }
302 (void)snprintf(chapter->title, sizeof(chapter->title), "%s", title);
303 chapter->number = number;
304 chapter->number_known = number_known;
305 return true;
306}
307
308bool mdl_state_chapter_complete(const mdl_state_t* st, const char* id)
309{
310 if ((st == nullptr) || (id == nullptr)) {
311 return false;
312 }
313 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
314 if (strcmp(st->chapters[i].chapter_id, id) == 0) {
315 return st->chapters[i].complete;
316 }
317 }
318 return false;
319}
320
321uint16_t mdl_state_chapter_pages(const mdl_state_t* st, const char* id)
322{
323 if ((st == nullptr) || (id == nullptr)) {
324 return 0U;
325 }
326 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
327 if (strcmp(st->chapters[i].chapter_id, id) == 0) {
328 return st->chapters[i].page_count;
329 }
330 }
331 return 0U;
332}
333
334const mdl_page_rec_t* mdl_state_find_page(const mdl_state_t* st, uint64_t url_hash)
335{
336 if (st == nullptr) {
337 return nullptr;
338 }
339 for (uint32_t i = 0U; i < st->page_rec_count; ++i) {
340 if (st->pages[i].url_hash == url_hash) {
341 return &st->pages[i];
342 }
343 }
344 return nullptr;
345}
346
348 uint64_t url_hash,
349 uint64_t content_hash,
350 const char* rel_path,
351 const char* etag,
352 const char* last_modified,
353 int64_t fetched_at,
354 uint16_t response_status)
355{
356 if ((st == nullptr) || (rel_path == nullptr)) {
357 return false;
358 }
360 !priv_mdl_state_field_valid((etag != nullptr) ? etag : "", k_mdl_etag_max) ||
361 !priv_mdl_state_field_valid((last_modified != nullptr) ? last_modified : "",
363 !internal_mdl_state_page_response_valid(fetched_at, response_status)) {
364 return false;
365 }
366 mdl_page_rec_t* rec = nullptr;
367 for (uint32_t i = 0U; i < st->page_rec_count; ++i) {
368 if (st->pages[i].url_hash == url_hash) {
369 rec = &st->pages[i];
370 break;
371 }
372 }
373 if (rec == nullptr) {
374 if (st->page_rec_count >= (uint32_t)k_mdl_max_page_recs) {
375 return false;
376 }
377 rec = &st->pages[st->page_rec_count];
378 st->page_rec_count += 1U;
379 }
380 rec->url_hash = url_hash;
381 rec->content_hash = content_hash;
382 (void)snprintf(rec->rel_path, sizeof(rec->rel_path), "%s", rel_path);
383 (void)snprintf(rec->etag, sizeof(rec->etag), "%s", (etag != nullptr) ? etag : "");
384 (void)snprintf(rec->last_modified,
385 sizeof(rec->last_modified),
386 "%s",
387 (last_modified != nullptr) ? last_modified : "");
388 rec->fetched_at = fetched_at;
389 rec->response_status = response_status;
390 return true;
391}
392
394 uint64_t url_hash,
395 int64_t fetched_at,
396 uint16_t response_status)
397{
398 if ((st == nullptr) || !internal_mdl_state_page_response_valid(fetched_at, response_status) ||
399 (response_status == 0U)) {
400 return false;
401 }
402 for (uint32_t i = 0U; i < st->page_rec_count; ++i) {
403 if (st->pages[i].url_hash == url_hash) {
404 st->pages[i].fetched_at = fetched_at;
405 st->pages[i].response_status = response_status;
406 return true;
407 }
408 }
409 return false;
410}
411
412/* ---- serialisation ------------------------------------------------------- */
413
431 long* out)
432{
433 if (!chapter->number_known || ((long double)chapter->number < (long double)LONG_MIN) ||
434 ((long double)chapter->number > (long double)LONG_MAX)) {
435 return false;
436 }
437 const long number = (long)chapter->number;
438 if ((double)number != chapter->number) {
439 return false;
440 }
441 *out = number;
442 return true;
443}
444
463RA8_INTERNAL static bool
464internal_mdl_state_complete_span(const mdl_state_t* st, long* lo, long* hi, size_t* n)
465{
466 bool any = false;
467 *n = 0U;
468 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
469 const mdl_chapter_rec_t* chapter = &st->chapters[i];
470 if (!chapter->complete) {
471 continue;
472 }
473 *n += 1U;
474 long num = 0L;
475 if (!internal_mdl_state_chapter_number_as_long(chapter, &num)) {
476 continue;
477 }
478 if (!any) {
479 *lo = num;
480 *hi = num;
481 any = true;
482 } else {
483 *lo = (num < *lo) ? num : *lo;
484 *hi = (num > *hi) ? num : *hi;
485 }
486 }
487 return any;
488}
489
507{
508 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
509 long chapter_number = 0L;
510 if (st->chapters[i].complete &&
511 internal_mdl_state_chapter_number_as_long(&st->chapters[i], &chapter_number) &&
512 (chapter_number == num)) {
513 return true;
514 }
515 }
516 return false;
517}
518
535RA8_INTERNAL static void
536internal_mdl_state_append_gaps(const mdl_state_t* st, long lo, long hi, char* buf, size_t cap)
537{
538 size_t len = strlen(buf);
539 size_t listed = 0U;
540 bool wrote = false;
541 for (long num = lo; (num <= hi) && (listed < (size_t)k_state_gap_cap); ++num) {
543 continue;
544 }
545 const int w = snprintf(&buf[len],
546 (len < cap) ? (cap - len) : 0U,
547 "%s%ld",
548 wrote ? ", " : ", missing ",
549 num);
550 if ((w < 0) || ((size_t)w >= ((len < cap) ? (cap - len) : 0U))) {
551 return; /* out of room: stop rather than truncate mid-number */
552 }
553 len += (size_t)w;
554 wrote = true;
555 ++listed;
556 }
557}
558
559void mdl_state_coverage(const mdl_state_t* st, char* buf, size_t cap)
560{
561 if ((st == nullptr) || (buf == nullptr) || (cap == 0U)) {
562 return;
563 }
564 long lo = 0;
565 long hi = 0;
566 size_t n = 0U;
567 if (!internal_mdl_state_complete_span(st, &lo, &hi, &n)) {
568 size_t complete = 0U;
569 for (uint16_t i = 0U; i < st->chapter_count; ++i) {
570 complete += st->chapters[i].complete ? 1U : 0U;
571 }
572 if (complete == 0U) {
573 (void)snprintf(buf, cap, "no chapters complete");
574 } else {
575 (void)snprintf(buf, cap, "%zu chapter(s) complete", complete);
576 }
577 return;
578 }
579 (void)snprintf(buf, cap, "%zu chapter(s) complete, %ld..%ld", n, lo, hi);
580 internal_mdl_state_append_gaps(st, lo, hi, buf, cap);
581}
@ k_mdl_url_max
Max bytes per URL, including the NUL.
Definition mdl_extract.h:25
@ k_mdl_last_mod_max
Raw Last-Modified header value buffer bytes.
Definition mdl_net.h:95
@ k_mdl_etag_max
Raw ETag header value buffer bytes.
Definition mdl_net.h:94
uint16_t mdl_state_chapter_pages(const mdl_state_t *st, const char *id)
Recorded page count for a chapter (0 when unknown).
Definition mdl_state.c:321
void priv_mdl_state_set_opt(char *dst, size_t cap, const char *val)
Copy val into a bounded field when val is non-NULL.
Definition mdl_state.c:62
static void internal_mdl_state_append_gaps(const mdl_state_t *st, long lo, long hi, char *buf, size_t cap)
Append the missing-chapter list within [lo,hi] to buf (bounded).
Definition mdl_state.c:536
void mdl_state_coverage(const mdl_state_t *st, char *buf, size_t cap)
Render a one-line coverage summary (chapter span, count, gaps).
Definition mdl_state.c:559
bool mdl_state_set_series_metadata(mdl_state_t *st, const char *summary, const char *writer, const char *artist, const char *cover_url, const char *cover_path, const char *language, mdl_state_reading_direction_t direction)
Set the optional rich metadata persisted for a series.
Definition mdl_state.c:186
mdl_state_coverage_t
Maximum missing chapter numbers rendered in one coverage summary.
Definition mdl_state.c:21
@ k_state_gap_cap
Max missing chapters listed.
Definition mdl_state.c:22
@ k_state_http_status_min
Smallest valid HTTP status.
Definition mdl_state.c:23
@ k_state_http_status_max
Largest valid HTTP status.
Definition mdl_state.c:24
bool priv_mdl_state_valid(const mdl_state_t *st)
Validate every bound and cross-field invariant before persistence.
Definition mdl_state.c:142
static bool internal_mdl_state_page_response_valid(int64_t fetched_at, uint16_t response_status)
Whether persisted HTTP observation metadata is canonical.
Definition mdl_state.c:43
static bool internal_mdl_state_complete_span(const mdl_state_t *st, long *lo, long *hi, size_t *n)
Number span [lo,hi] of complete integral chapters.
Definition mdl_state.c:464
static bool internal_mdl_state_has_complete_number(const mdl_state_t *st, long num)
True when a complete chapter with parsed number num exists.
Definition mdl_state.c:506
mdl_chapter_rec_t * mdl_state_add_chapter(mdl_state_t *st, const char *id, const char *url, long number)
Find or append a chapter record, returning it.
Definition mdl_state.c:257
bool mdl_state_set_chapter_metadata(mdl_chapter_rec_t *chapter, const char *title, double number, bool number_known)
Set a chapter's display title and explicit parsed number.
Definition mdl_state.c:293
mdl_chapter_rec_t * mdl_state_find_chapter(mdl_state_t *st, const char *id)
Find a chapter record by its stable identifier.
Definition mdl_state.c:243
const mdl_page_rec_t * mdl_state_find_page(const mdl_state_t *st, uint64_t url_hash)
Find a page record by its source-URL hash (the dedup lookup).
Definition mdl_state.c:334
bool mdl_state_note_page_response(mdl_state_t *st, uint64_t url_hash, int64_t fetched_at, uint16_t response_status)
Refresh the observed HTTP result for one existing URL cache entry.
Definition mdl_state.c:393
mdl_chapter_rec_t * mdl_state_add_chapter_numbered(mdl_state_t *st, const char *id, const char *url, double number, bool number_known)
Find or append a chapter with explicit parsed-number presence.
Definition mdl_state.c:262
bool priv_mdl_state_relative_path_valid(const char *path, size_t cap)
Validate a bounded relative path.
Definition mdl_state.c:95
static bool internal_mdl_state_chapter_number_valid(double number, bool known)
Validate an explicit chapter-number tuple.
Definition mdl_state.c:136
bool mdl_state_chapter_complete(const mdl_state_t *st, const char *id)
Whether a chapter is recorded fully fetched and verified.
Definition mdl_state.c:308
bool priv_mdl_state_field_valid(const char *text, size_t cap)
True when a record field fits and cannot inject a line or column.
Definition mdl_state.c:70
bool mdl_state_add_page(mdl_state_t *st, uint64_t url_hash, uint64_t content_hash, const char *rel_path, const char *etag, const char *last_modified, int64_t fetched_at, uint16_t response_status)
Add or replace a URL-keyed page cache record.
Definition mdl_state.c:347
void mdl_state_init(mdl_state_t *st)
Reset a state object to an empty, current-version library.
Definition mdl_state.c:52
void mdl_state_set_series(mdl_state_t *st, const char *url, const char *title, const char *site_name, const char *site_host, const char *config_path)
Record the series identity and the descriptor used.
Definition mdl_state.c:226
static bool internal_mdl_state_chapter_number_as_long(const mdl_chapter_rec_t *chapter, long *out)
Convert an exactly integral chapter number to long.
Definition mdl_state.c:430
Persistent per-series library state for the media downloader.
mdl_state_reading_direction_t
Persisted fixed-layout reading direction.
Definition mdl_state.h:108
@ k_mdl_state_read_ltr
Left-to-right page progression.
Definition mdl_state.h:109
@ k_mdl_state_read_rtl
Right-to-left page progression.
Definition mdl_state.h:110
@ k_mdl_language_max
BCP-47 language bytes.
Definition mdl_state.h:101
@ k_mdl_state_version
Timestamped cache schema written now.
Definition mdl_state.h:96
@ k_mdl_person_max
Writer/artist bytes.
Definition mdl_state.h:100
@ k_mdl_summary_max
Series summary bytes.
Definition mdl_state.h:99
@ k_mdl_chapter_id_max
Chapter identifier bytes (sanitised).
Definition mdl_state.h:97
@ k_mdl_max_chapters
Chapters tracked per series.
Definition mdl_state.h:104
@ k_mdl_relpath_max
Page path relative to the series dir.
Definition mdl_state.h:102
@ k_mdl_max_page_recs
Per-page content records per series.
Definition mdl_state.h:115
Module-private validation shared by the state model and codec.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
int strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
size_t strnlen(const char *s, size_t maxlen)
Calculate bounded string length.
One chapter's coverage in library state.
Definition mdl_state.h:128
char chapter_id[k_mdl_chapter_id_max]
Stable identifier (URL leaf).
Definition mdl_state.h:129
double number
Parsed number; 0 may be valid.
Definition mdl_state.h:132
char source_url[k_mdl_url_max]
Chapter page URL.
Definition mdl_state.h:130
uint16_t pages_done
Pages fetched and verified.
Definition mdl_state.h:135
bool number_known
Whether number is known.
Definition mdl_state.h:133
char title[k_mdl_title_max]
Display title, or empty.
Definition mdl_state.h:131
uint16_t page_count
Total pages known (0 = ?).
Definition mdl_state.h:134
bool complete
All pages present + verified.
Definition mdl_state.h:136
One page's dedup/verify record in the series-wide pool.
Definition mdl_state.h:151
char etag[k_mdl_etag_max]
Cached ETag for conditional GET.
Definition mdl_state.h:155
char last_modified[k_mdl_last_mod_max]
Cached Last-Modified response value.
Definition mdl_state.h:157
uint64_t content_hash
FNV-1a 64 of the fetched bytes.
Definition mdl_state.h:153
char rel_path[k_mdl_relpath_max]
Path under the series directory.
Definition mdl_state.h:154
uint64_t url_hash
FNV-1a 64 of the source URL.
Definition mdl_state.h:152
uint16_t response_status
Most recent HTTP status; zero if legacy.
Definition mdl_state.h:159
int64_t fetched_at
Most recent HTTP result time (epoch s).
Definition mdl_state.h:158
One series' complete persistent state (declare at file scope).
Definition mdl_state.h:175
char summary[k_mdl_summary_max]
Series synopsis.
Definition mdl_state.h:182
uint16_t chapter_count
Chapters recorded.
Definition mdl_state.h:191
char cover_path[k_mdl_relpath_max]
Local cover path.
Definition mdl_state.h:186
char series_title[k_mdl_title_max]
Series title.
Definition mdl_state.h:178
mdl_chapter_rec_t chapters[k_mdl_max_chapters]
Per-chapter coverage.
Definition mdl_state.h:195
char series_url[k_mdl_url_max]
Series page URL.
Definition mdl_state.h:177
char site_name[k_mdl_name_max]
Descriptor name.
Definition mdl_state.h:179
mdl_state_reading_direction_t reading_direction
Page progression.
Definition mdl_state.h:189
char language[k_mdl_language_max]
BCP-47 language tag.
Definition mdl_state.h:187
uint16_t version
Schema version.
Definition mdl_state.h:176
char artist[k_mdl_person_max]
Artist/illustrator.
Definition mdl_state.h:184
uint32_t page_rec_count
Page records recorded.
Definition mdl_state.h:193
mdl_page_rec_t pages[k_mdl_max_page_recs]
Per-page identities.
Definition mdl_state.h:197
char site_host[k_mdl_host_max]
Site host.
Definition mdl_state.h:180
char cover_url[k_mdl_url_max]
Remote cover URL.
Definition mdl_state.h:185
char config_path[k_mdl_cfgpath_max]
Descriptor used.
Definition mdl_state.h:181
char writer[k_mdl_person_max]
Writer/author.
Definition mdl_state.h:183