• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

saitoha / libsixel / 23380678255

21 Mar 2026 01:24PM UTC coverage: 81.547% (-0.08%) from 81.627%
23380678255

push

github

saitoha
loader: share -L schema and build plan from parsed AST

28940 of 68810 branches covered (42.06%)

53 of 60 new or added lines in 4 files covered. (88.33%)

1438 existing lines in 8 files now uncovered.

55183 of 67670 relevant lines covered (81.55%)

4093439.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.36
/src/loader-manager.c
1
/*
2
 * SPDX-License-Identifier: MIT
3
 *
4
 * Copyright (c) 2021-2025 libsixel developers. See `AUTHORS`.
5
 * Copyright (c) 2014-2019 Hayaki Saito
6
 */
7

8
#if defined(HAVE_CONFIG_H)
9
# include "config.h"
10
#endif
11

12
#include "loader-manager.h"
13

14
#include "loader-common.h"
15
#include "loader-order-schema.h"
16
#include "options.h"
17
#include "sixel_atomic.h"
18

19
#include <ctype.h>
20
#include <limits.h>
21
#if HAVE_STRING_H
22
# include <string.h>
23
#endif
24

25
struct sixel_loader_manager {
26
    sixel_atomic_u32_t ref;
27
    sixel_loader_factory_t *factory;
28
};
29

30
static struct sixel_loader_manager g_loader_manager_singleton = {
31
    0u,
32
    NULL
33
};
34

35
static void
36
loader_manager_unref_singleton_ref(sixel_atomic_u32_t *ref)
19,866✔
37
{
38
    unsigned int previous;
12,430✔
39

40
    previous = 0u;
19,866✔
41
    if (ref == NULL) {
19,866!
42
        return;
43
    }
44

45
    /*
46
     * Manager is a singleton coordinator. Saturate at zero so accidental
47
     * extra unref() calls never wrap the reference counter.
48
     */
49
    previous = sixel_atomic_fetch_sub_u32(ref, 1u);
19,866!
50
    if (previous == 0u) {
19,866!
51
        (void)sixel_atomic_fetch_add_u32(ref, 1u);
×
52
    }
53
}
12,399!
54

55

56
#if HAVE_WIC
57
static int
58
loader_manager_parse_positive_int(char const *text,
16✔
59
                                  size_t length,
60
                                  int *value_out)
61
{
62
    size_t index;
8✔
63
    int value;
8✔
64
    unsigned char digit;
8✔
65

66
    index = 0u;
16✔
67
    value = 0;
16✔
68
    digit = 0u;
16✔
69
    if (text == NULL || value_out == NULL || length == 0u) {
16✔
70
        return 0;
71
    }
72

73
    for (index = 0u; index < length; ++index) {
48✔
74
        digit = (unsigned char)text[index];
32✔
75
        if (digit < (unsigned char)'0' || digit > (unsigned char)'9') {
32✔
76
            return 0;
77
        }
78
        if (value > (INT_MAX - 9) / 10) {
32✔
79
            return 0;
80
        }
81
        value = value * 10 + (digit - (unsigned char)'0');
32✔
82
    }
4✔
83

84
    if (value <= 0) {
16✔
85
        return 0;
86
    }
87

88
    *value_out = value;
16✔
89
    return 1;
16✔
90
}
2✔
91
#endif
92

93
static int
94
loader_manager_parse_bool_flag(char const *text,
298✔
95
                               size_t length,
96
                               int *value_out)
97
{
98
    if (text == NULL || value_out == NULL || length != 1u) {
298!
99
        return 0;
100
    }
101
    if (text[0] == '0') {
298!
102
        *value_out = 0;
276✔
103
        return 1;
276✔
104
    }
105
    if (text[0] == '1') {
22!
106
        *value_out = 1;
22✔
107
        return 1;
22✔
108
    }
109
    return 0;
110
}
280✔
111

112
static int
113
loader_manager_plan_contains(sixel_loader_entry_t const **plan,
54,836✔
114
                             size_t plan_length,
115
                             sixel_loader_entry_t const *entry)
116
{
117
    size_t index;
30,697✔
118

119
    index = 0u;
54,836✔
120
    for (index = 0u; index < plan_length; ++index) {
177,398!
121
        if (plan[index] == entry) {
114,652!
122
            return 1;
123
        }
124
    }
109,427✔
125

126
    return 0;
54,836✔
127
}
50,054✔
128

129
static size_t
130
loader_manager_token_name_length(char const *token,
131
                                 size_t token_length)
132
{
133
    size_t index;
134
    size_t length;
135

UNCOV
136
    index = 0u;
×
UNCOV
137
    length = token_length;
×
138

139
    /*
140
     * Loader tokens can carry suboptions after ':' (for example
141
     * "wic:ico_minsize=30"). Build-plan lookup must match only the loader
142
     * name so that suboptions do not prevent backend resolution.
143
     */
UNCOV
144
    while (index < length) {
×
UNCOV
145
        if (token[index] == ':') {
×
146
            length = index;
147
            break;
148
        }
UNCOV
149
        ++index;
×
150
    }
151

UNCOV
152
    if (token != NULL && token_length > 0 && token[token_length - 1] == '@') {
×
153
        length = token_length - 1u;
×
154
    }
155

UNCOV
156
    return length;
×
157
}
158

159
static int
160
loader_manager_token_matches(char const *token,
9,988✔
161
                             size_t token_length,
162
                             char const *name)
163
{
164
    size_t index;
6,247✔
165
    unsigned char left;
6,247✔
166
    unsigned char right;
6,247✔
167

168
    index = 0u;
9,988✔
169
    left = 0u;
9,988✔
170
    right = 0u;
9,988✔
171
    for (index = 0u; index < token_length && name[index] != '\0'; ++index) {
40,296!
172
        left = (unsigned char)token[index];
36,632✔
173
        right = (unsigned char)name[index];
36,632✔
174
        if (tolower(left) != tolower(right)) {
36,632✔
175
            return 0;
6,124✔
176
        }
177
    }
24,896✔
178

179
    if (index != token_length || name[index] != '\0') {
3,664!
UNCOV
180
        return 0;
×
181
    }
182

183
    return 1;
3,094✔
184
}
8,792✔
185

186
static sixel_loader_entry_t const *
187
loader_manager_lookup_token(char const *token,
3,664✔
188
                            size_t token_length,
189
                            sixel_loader_entry_t const *entries,
190
                            size_t entry_count)
191
{
192
    size_t index;
2,280✔
193

194
    index = 0u;
3,664✔
195
    for (index = 0u; index < entry_count; ++index) {
9,988!
196
        if (loader_manager_token_matches(token,
18,780!
197
                                         token_length,
8,792✔
198
                                         entries[index].name)) {
9,988✔
199
            return &entries[index];
3,094✔
200
        }
201
    }
6,004✔
202

203
    return NULL;
204
}
2,788✔
205

206
SIXELSTATUS
207
loader_manager_parse_loader_order(
3,667✔
208
    char const *order,
209
    sixel_option_argument_list_resolution_t *resolution)
210
{
211
    char diagnostic[128];
2,282✔
212

213
    diagnostic[0] = '\0';
3,667✔
214
    if (resolution == NULL) {
3,667!
UNCOV
215
        sixel_helper_set_additional_message(
×
216
            "loader_manager_parse_loader_order: resolution is null.");
UNCOV
217
        return SIXEL_BAD_ARGUMENT;
×
218
    }
219

220
    return sixel_option_parse_argument_list_with_suboptions(
3,667✔
221
        order,
2,789✔
222
        sixel_loader_order_schema_get(),
2,789✔
223
        resolution,
2,789✔
224
        diagnostic,
2,789✔
225
        sizeof(diagnostic));
226
}
2,789✔
227

228
void
229
loader_manager_apply_loader_suboptions_resolution(
19,866✔
230
    sixel_option_argument_list_resolution_t const *resolution)
231
{
232
    size_t item_index;
12,430✔
233
    size_t assignment_index;
12,430✔
234
    sixel_option_argument_resolution_t const *item;
12,430✔
235
    char const *key_name;
12,430✔
236
    char const *value_text;
12,430✔
237
    size_t value_length;
12,430✔
238
    int parsed_value;
12,430✔
239

240
    item_index = 0u;
19,866✔
241
    assignment_index = 0u;
19,866✔
242
    item = NULL;
19,866✔
243
    key_name = NULL;
19,866✔
244
    value_text = NULL;
19,866✔
245
    value_length = 0u;
19,866✔
246
    parsed_value = 0;
19,866✔
247

248
    /* Reset overrides first so malformed tokens cannot leak previous state. */
249
#if HAVE_WIC
250
    sixel_helper_set_wic_ico_minsize(0);
6,772✔
251
#endif
252
    sixel_helper_set_libpng_enable_cms(-1);
19,866✔
253
    sixel_helper_set_builtin_enable_cms(-1);
19,866✔
254

255
    if (resolution == NULL) {
19,866!
UNCOV
256
        return;
×
257
    }
258

259
    while (item_index < resolution->item_count) {
23,530!
260
        item = &resolution->items[item_index].resolution;
3,664✔
261
        if (item->base_def == NULL) {
3,664!
UNCOV
262
            ++item_index;
×
UNCOV
263
            continue;
×
264
        }
265
        assignment_index = 0u;
3,094✔
266
        while (assignment_index < item->assignment_count) {
3,978!
267
            key_name = item->assignments[assignment_index].resolved_key_name;
314✔
268
            value_text = item->assignments[assignment_index].resolved_value_text;
314✔
269
            value_length = 0u;
314✔
270
            if (value_text != NULL) {
314!
271
                value_length = strlen(value_text);
314✔
272
            }
282✔
273
            if (key_name == NULL || value_text == NULL) {
314!
UNCOV
274
                ++assignment_index;
×
UNCOV
275
                continue;
×
276
            }
277
#if HAVE_WIC
278
            if (strcmp(item->base_def->name, "wic") == 0 &&
32✔
279
                strcmp(key_name, "ico_minsize") == 0 &&
30✔
280
                loader_manager_parse_positive_int(value_text,
18✔
281
                                                  value_length,
2✔
282
                                                  &parsed_value)) {
283
                sixel_helper_set_wic_ico_minsize(parsed_value);
16✔
284
                ++assignment_index;
16✔
285
                continue;
16✔
286
            }
287
#endif
288
            if (strcmp(key_name, "enable_cms") == 0 &&
316!
289
                loader_manager_parse_bool_flag(value_text,
578!
290
                                               value_length,
280✔
291
                                               &parsed_value)) {
292
                if (strcmp(item->base_def->name, "libpng") == 0) {
298!
293
                    sixel_helper_set_libpng_enable_cms(parsed_value);
268✔
294
                } else if (strcmp(item->base_def->name, "builtin") == 0) {
298!
295
                    sixel_helper_set_builtin_enable_cms(parsed_value);
30✔
296
                }
12✔
297
            }
280✔
298
            ++assignment_index;
298✔
299
        }
300
        ++item_index;
3,664✔
301
    }
302
}
12,399!
303

304
void
305
loader_manager_apply_loader_suboptions(char const *order)
306
{
307
    SIXELSTATUS status;
308
    sixel_option_argument_list_resolution_t resolution;
309

UNCOV
310
    status = SIXEL_OK;
×
UNCOV
311
    resolution.canonical_argument = NULL;
×
UNCOV
312
    resolution.has_trailing_bang = 0;
×
UNCOV
313
    resolution.items = NULL;
×
UNCOV
314
    resolution.item_count = 0u;
×
315

UNCOV
316
    if (order == NULL || order[0] == '\0') {
×
UNCOV
317
        loader_manager_apply_loader_suboptions_resolution(NULL);
×
UNCOV
318
        return;
×
319
    }
320

UNCOV
321
    status = loader_manager_parse_loader_order(order, &resolution);
×
UNCOV
322
    if (SIXEL_FAILED(status)) {
×
UNCOV
323
        loader_manager_apply_loader_suboptions_resolution(NULL);
×
UNCOV
324
        return;
×
325
    }
326

UNCOV
327
    loader_manager_apply_loader_suboptions_resolution(&resolution);
×
UNCOV
328
    sixel_option_free_argument_list_resolution(&resolution);
×
329
}
×
330

331
size_t
332
loader_manager_build_plan_from_resolution(
3,648✔
333
    sixel_option_argument_list_resolution_t const *resolution,
334
    sixel_loader_entry_t const *entries,
335
    size_t entry_count,
336
    sixel_loader_entry_t const **plan,
337
    size_t plan_capacity)
338
{
339
    size_t plan_length;
2,270✔
340
    size_t index;
2,270✔
341
    sixel_loader_entry_t const *entry;
2,270✔
342
    size_t limit;
2,270✔
343
    int allow_fallback;
2,270✔
344
    sixel_option_argument_resolution_t const *item;
2,270✔
345

346
    plan_length = 0u;
3,648✔
347
    index = 0u;
3,648✔
348
    entry = NULL;
3,648✔
349
    limit = plan_capacity;
3,648✔
350
    allow_fallback = 1;
3,648✔
351
    item = NULL;
3,648✔
352

353
    if (resolution != NULL) {
3,648!
354
        allow_fallback = !resolution->has_trailing_bang;
3,648✔
355
    }
2,779✔
356

357
    if (plan != NULL && plan_capacity > 0u && resolution != NULL) {
3,648!
358
        for (index = 0u; index < resolution->item_count; ++index) {
7,312!
359
            item = &resolution->items[index].resolution;
3,664✔
360
            if (item->base_def == NULL || item->base_def->name == NULL) {
3,664!
NEW
361
                continue;
×
362
            }
363
            entry = loader_manager_lookup_token(item->base_def->name,
6,452✔
364
                                                strlen(item->base_def->name),
3,094✔
365
                                                entries,
2,788✔
366
                                                entry_count);
2,788✔
367
            if (entry != NULL &&
6,656!
368
                !loader_manager_plan_contains(plan, plan_length, entry) &&
3,970!
369
                plan_length < limit) {
2,788!
370
                plan[plan_length] = entry;
3,664✔
371
                ++plan_length;
3,664✔
372
            }
2,788✔
373
        }
2,788✔
374
    }
2,779✔
375

376
    if (allow_fallback && plan != NULL && limit > 0u) {
3,648!
377
        for (index = 0u; index < entry_count && plan_length < limit; ++index) {
8!
NEW
378
            entry = &entries[index];
×
NEW
379
            if (!entry->default_enabled) {
×
NEW
380
                continue;
×
381
            }
NEW
382
            if (!loader_manager_plan_contains(plan, plan_length, entry)) {
×
NEW
383
                plan[plan_length] = entry;
×
NEW
384
                ++plan_length;
×
385
            }
386
        }
387
    }
1✔
388

389
    return plan_length;
5,352✔
390
}
1,704✔
391

392
size_t
393
loader_manager_build_plan(
16,218✔
394
    char const *order,
395
    sixel_loader_entry_t const *entries,
396
    size_t entry_count,
397
    sixel_loader_entry_t const **plan,
398
    size_t plan_capacity)
399
{
400
    size_t plan_length;
10,160✔
401
    size_t index;
10,160✔
402
    char const *cursor;
10,160✔
403
    char const *token_start;
10,160✔
404
    char const *token_end;
10,160✔
405
    char const *order_end;
10,160✔
406
    size_t token_length;
10,160✔
407
    sixel_loader_entry_t const *entry;
10,160✔
408
    size_t limit;
10,160✔
409
    int allow_fallback;
10,160✔
410

411
    plan_length = 0u;
16,218✔
412
    index = 0u;
16,218✔
413
    cursor = order;
16,218✔
414
    token_start = order;
16,218✔
415
    token_end = order;
16,218✔
416
    order_end = NULL;
16,218✔
417
    token_length = 0u;
16,218✔
418
    entry = NULL;
16,218✔
419
    limit = plan_capacity;
16,218✔
420
    allow_fallback = 1;
16,218✔
421

422
    if (order != NULL) {
16,218!
UNCOV
423
        order_end = order + strlen(order);
×
UNCOV
424
        while (order_end > order &&
×
425
               isspace((unsigned char)order_end[-1])) {
×
UNCOV
426
            --order_end;
×
427
        }
UNCOV
428
        if (order_end > order && order_end[-1] == '!') {
×
UNCOV
429
            allow_fallback = 0;
×
UNCOV
430
            --order_end;
×
UNCOV
431
            while (order_end > order &&
×
UNCOV
432
                   isspace((unsigned char)order_end[-1])) {
×
UNCOV
433
                --order_end;
×
434
            }
435
        }
436
    }
437

438
    if (order != NULL && plan != NULL && plan_capacity > 0u) {
16,218!
439
        token_start = order;
440
        cursor = order;
UNCOV
441
        while (cursor < order_end) {
×
UNCOV
442
            if (*cursor == ',') {
×
UNCOV
443
                token_end = cursor;
×
UNCOV
444
                while (token_start < token_end &&
×
UNCOV
445
                       isspace((unsigned char)*token_start)) {
×
UNCOV
446
                    ++token_start;
×
447
                }
UNCOV
448
                while (token_end > token_start &&
×
UNCOV
449
                       isspace((unsigned char)token_end[-1])) {
×
UNCOV
450
                    --token_end;
×
451
                }
452
                token_length = (size_t)(token_end - token_start);
×
UNCOV
453
                if (token_length > 0u) {
×
UNCOV
454
                    entry = loader_manager_lookup_token(
×
455
                        token_start,
456
                        loader_manager_token_name_length(token_start,
457
                                                         token_length),
458
                        entries,
459
                        entry_count);
UNCOV
460
                    if (entry != NULL &&
×
UNCOV
461
                        !loader_manager_plan_contains(plan,
×
462
                                                     plan_length,
UNCOV
463
                                                     entry) &&
×
464
                        plan_length < limit) {
×
UNCOV
465
                        plan[plan_length] = entry;
×
UNCOV
466
                        ++plan_length;
×
467
                    }
468
                }
UNCOV
469
                token_start = cursor + 1;
×
470
            }
UNCOV
471
            ++cursor;
×
472
        }
473

UNCOV
474
        token_end = order_end;
×
UNCOV
475
        while (token_start < token_end &&
×
UNCOV
476
               isspace((unsigned char)*token_start)) {
×
UNCOV
477
            ++token_start;
×
478
        }
UNCOV
479
        while (token_end > token_start &&
×
UNCOV
480
               isspace((unsigned char)token_end[-1])) {
×
UNCOV
481
            --token_end;
×
482
        }
UNCOV
483
        token_length = (size_t)(token_end - token_start);
×
UNCOV
484
        if (token_length > 0u) {
×
UNCOV
485
            entry = loader_manager_lookup_token(
×
486
                token_start,
487
                loader_manager_token_name_length(token_start, token_length),
488
                entries,
489
                entry_count);
UNCOV
490
            if (entry != NULL &&
×
UNCOV
491
                !loader_manager_plan_contains(plan, plan_length, entry) &&
×
492
                plan_length < limit) {
×
UNCOV
493
                plan[plan_length] = entry;
×
UNCOV
494
                ++plan_length;
×
495
            }
496
        }
497
    }
498

499
    if (allow_fallback && plan != NULL && limit > 0u) {
16,218!
500
        for (index = 0u; index < entry_count && plan_length < limit; ++index) {
85,554!
501
            entry = &entries[index];
69,336✔
502
            if (!entry->default_enabled) {
69,336✔
503
                continue;
10,254✔
504
            }
505
            if (!loader_manager_plan_contains(plan, plan_length, entry)) {
59,082!
506
                plan[plan_length] = entry;
59,082✔
507
                ++plan_length;
59,082✔
508
            }
47,266✔
509
        }
47,266✔
510
    }
9,620✔
511

512
    return plan_length;
22,018✔
513
}
5,800✔
514

515
SIXELSTATUS
516
loader_manager_get_default(sixel_loader_manager_t **ppmanager)
19,866✔
517
{
518
    SIXELSTATUS status;
12,430✔
519

520
    status = SIXEL_OK;
19,866✔
521
    if (ppmanager == NULL) {
19,866!
UNCOV
522
        sixel_helper_set_additional_message(
×
523
            "loader_manager_get_default: ppmanager is null.");
UNCOV
524
        return SIXEL_BAD_ARGUMENT;
×
525
    }
526

527
    if (g_loader_manager_singleton.factory == NULL) {
19,866✔
528
        status = loader_factory_get_default(
14,531✔
529
            &g_loader_manager_singleton.factory);
530
        if (SIXEL_FAILED(status)) {
14,531!
531
            return status;
532
        }
533
    }
9,053✔
534

535
    loader_manager_ref(&g_loader_manager_singleton);
19,866✔
536
    *ppmanager = &g_loader_manager_singleton;
19,866✔
537

538
    return status;
19,866✔
539
}
12,399✔
540

541
void
542
loader_manager_ref(sixel_loader_manager_t *manager)
19,866✔
543
{
544
    if (manager == NULL) {
16,482!
545
        return;
546
    }
547

548
    (void)sixel_atomic_fetch_add_u32(&manager->ref, 1u);
19,866✔
549
}
12,399✔
550

551
void
552
loader_manager_unref(sixel_loader_manager_t *manager)
19,949✔
553
{
554
    if (manager == NULL) {
19,949✔
555
        return;
65✔
556
    }
557

558
    loader_manager_unref_singleton_ref(&manager->ref);
19,866✔
559
}
12,449✔
560

561
SIXELSTATUS
562
loader_manager_build_chain_from_plan(
19,866✔
563
    sixel_loader_manager_t *manager,
564
    sixel_loader_entry_t const **plan,
565
    size_t plan_length,
566
    sixel_chunk_t const *chunk,
567
    sixel_allocator_t *allocator,
568
    sixel_loader_chain_t **ppchain)
569
{
570
    SIXELSTATUS status;
12,430✔
571
    sixel_loader_chain_t *chain;
12,430✔
572
    sixel_loader_component_t *component;
12,430✔
573
    size_t index;
12,430✔
574

575
    status = SIXEL_OK;
19,866✔
576
    chain = NULL;
19,866✔
577
    component = NULL;
19,866✔
578
    index = 0u;
19,866✔
579
    if (ppchain == NULL || manager == NULL || plan == NULL) {
19,866!
UNCOV
580
        sixel_helper_set_additional_message(
×
581
            "loader_manager_build_chain_from_plan: invalid argument.");
UNCOV
582
        return SIXEL_BAD_ARGUMENT;
×
583
    }
584

585
    *ppchain = NULL;
19,866✔
586
    status = loader_chain_new(&chain, allocator);
19,866✔
587
    if (SIXEL_FAILED(status)) {
19,866!
588
        return status;
589
    }
590

591
    /*
592
     * Chain assembly keeps a strict separation of concerns.
593
     *
594
     * 1) plan[] already defines candidate order.
595
     * 2) factory decides whether a candidate can run for this chunk.
596
     * 3) factory materializes a backend component.
597
     * 4) chain owns component references in execution order.
598
     */
599
    for (index = 0u; index < plan_length; ++index) {
82,612!
600
        if (plan[index] == NULL) {
62,746!
UNCOV
601
            continue;
×
602
        }
603
        if (!loader_factory_entry_matches_chunk(manager->factory,
112,800!
604
                                                plan[index],
54,836✔
605
                                                chunk)) {
50,054✔
606
            continue;
19,768✔
607
        }
608

609
        status = loader_factory_create_component(manager->factory,
81,174✔
610
                                                 plan[index]->name,
42,978✔
611
                                                 allocator,
30,286✔
612
                                                 &component);
613
        if (SIXEL_FAILED(status)) {
42,978!
UNCOV
614
            goto end;
×
615
        }
616

617
        status = loader_chain_append(chain, component);
42,978✔
618
        sixel_loader_component_unref(component);
42,978✔
619
        component = NULL;
42,978✔
620
        if (SIXEL_FAILED(status)) {
42,978!
UNCOV
621
            goto end;
×
622
        }
623
    }
30,286✔
624

625
    *ppchain = chain;
19,866✔
626
    chain = NULL;
19,866✔
627

628
end:
7,467✔
629
    if (component != NULL) {
19,866!
UNCOV
630
        sixel_loader_component_unref(component);
×
631
    }
632
    loader_chain_unref(chain);
19,866✔
633
    return status;
19,866✔
634
}
12,399✔
635

636
SIXELSTATUS
637
loader_manager_execute_chain(
19,866✔
638
    sixel_loader_manager_t *manager,
639
    sixel_loader_chain_t const *chain,
640
    sixel_chunk_t const *chunk,
641
    sixel_load_image_function fn_load,
642
    void *load_context,
643
    sixel_loader_manager_configure_component_fn fn_configure,
644
    void *configure_context,
645
    sixel_loader_manager_trace_try_fn fn_try,
646
    sixel_loader_manager_trace_result_fn fn_result,
647
    void *trace_context,
648
    char const **selected_name)
649
{
650
    SIXELSTATUS status;
12,430✔
651
    sixel_loader_chain_node_t const *node;
12,430✔
652
    char const *name;
12,430✔
653

654
    status = SIXEL_FALSE;
19,866✔
655
    node = NULL;
19,866✔
656
    name = NULL;
19,866✔
657
    if (selected_name != NULL) {
19,866!
658
        *selected_name = NULL;
19,866✔
659
    }
12,399✔
660
    if (manager == NULL || chain == NULL || chunk == NULL) {
19,866!
UNCOV
661
        sixel_helper_set_additional_message(
×
662
            "loader_manager_execute_chain: invalid argument.");
UNCOV
663
        return SIXEL_BAD_ARGUMENT;
×
664
    }
665

666
    (void)manager;
17,325✔
667
    node = loader_chain_head(chain);
19,866✔
668
    while (node != NULL) {
20,605!
669
        name = sixel_loader_component_get_name(node->component);
20,086✔
670
        if (fn_configure != NULL) {
20,086!
671
            status = fn_configure(node->component, configure_context);
20,086✔
672
            if (SIXEL_FAILED(status)) {
20,086!
673
                return status;
674
            }
675
        }
12,549✔
676

677
        if (fn_try != NULL) {
20,086!
678
            fn_try(name, trace_context);
20,086✔
679
        }
12,549✔
680

681
        status = sixel_loader_component_load(node->component,
32,635✔
682
                                             chunk,
12,549✔
683
                                             fn_load,
12,549✔
684
                                             load_context);
12,549✔
685

686
        if (fn_result != NULL) {
20,086!
687
            fn_result(name, status, trace_context);
20,086✔
688
        }
12,549✔
689

690
        if (SIXEL_SUCCEEDED(status)) {
20,086✔
691
            if (selected_name != NULL) {
19,347!
692
                *selected_name = name;
19,347✔
693
            }
12,040✔
694
            return status;
19,347✔
695
        }
696
        node = node->next;
739✔
697
    }
698

699
    return status;
413✔
700
}
12,399✔
701

702
/* emacs Local Variables:      */
703
/* emacs mode: c               */
704
/* emacs tab-width: 4          */
705
/* emacs indent-tabs-mode: nil */
706
/* emacs c-basic-offset: 4     */
707
/* emacs End:                  */
708
/* vim: set expandtab ts=4 sts=4 sw=4 : */
709
/* EOF */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc