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

saitoha / libsixel / 19541344273

20 Nov 2025 03:02PM UTC coverage: 40.773% (-0.4%) from 41.21%
19541344273

push

github

saitoha
feat: initial prototyping for parallel dithering

9711 of 33880 branches covered (28.66%)

55 of 483 new or added lines in 10 files covered. (11.39%)

12 existing lines in 4 files now uncovered.

12720 of 31197 relevant lines covered (40.77%)

656879.66 hits per line

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

0.0
/src/parallel-log.c
1
/*
2
 * SPDX-License-Identifier: MIT
3
 *
4
 * Copyright (c) 2025 libsixel developers. See `AUTHORS`.
5
 */
6

7
#include "config.h"
8

9
#include <stdarg.h>
10
#include <stdint.h>
11
#include <stdio.h>
12
#include <string.h>
13

14
#ifndef _WIN32
15
#include <pthread.h>
16
#endif
17

18
#include "assessment.h"
19
#include "parallel-log.h"
20

21
static unsigned long long
NEW
22
sixel_parallel_logger_thread_id(void)
×
23
{
24
#ifndef _WIN32
NEW
25
    return (unsigned long long)(uintptr_t)pthread_self();
×
26
#else
27
    return 0ULL;
28
#endif
29
}
30

31
static void
NEW
32
sixel_parallel_logger_escape(char const *message, char *buffer, size_t size)
×
33
{
34
    size_t i;
35
    size_t written;
36

NEW
37
    if (buffer == NULL || size == 0) {
×
NEW
38
        return;
×
39
    }
NEW
40
    buffer[0] = '\0';
×
NEW
41
    if (message == NULL) {
×
NEW
42
        return;
×
43
    }
NEW
44
    written = 0;
×
NEW
45
    for (i = 0; message[i] != '\0' && written + 2 < size; ++i) {
×
NEW
46
        if (message[i] == '\"' || message[i] == '\\') {
×
NEW
47
            buffer[written++] = '\\';
×
NEW
48
            if (written + 1 >= size) {
×
NEW
49
                break;
×
50
            }
51
        }
NEW
52
        buffer[written++] = message[i];
×
53
    }
NEW
54
    buffer[written] = '\0';
×
55
}
56

57
void
NEW
58
sixel_parallel_logger_init(sixel_parallel_logger_t *logger)
×
59
{
NEW
60
    if (logger == NULL) {
×
NEW
61
        return;
×
62
    }
NEW
63
    logger->file = NULL;
×
NEW
64
    logger->mutex_ready = 0;
×
NEW
65
    logger->active = 0;
×
NEW
66
    logger->started_at = 0.0;
×
67
}
68

69
void
NEW
70
sixel_parallel_logger_close(sixel_parallel_logger_t *logger)
×
71
{
NEW
72
    if (logger == NULL) {
×
NEW
73
        return;
×
74
    }
NEW
75
    if (logger->mutex_ready) {
×
NEW
76
        sixel_mutex_destroy(&logger->mutex);
×
NEW
77
        logger->mutex_ready = 0;
×
78
    }
NEW
79
    if (logger->file != NULL) {
×
NEW
80
        fclose(logger->file);
×
NEW
81
        logger->file = NULL;
×
82
    }
NEW
83
    logger->active = 0;
×
84
}
85

86
SIXELSTATUS
NEW
87
sixel_parallel_logger_open(sixel_parallel_logger_t *logger, char const *path)
×
88
{
NEW
89
    if (logger == NULL) {
×
NEW
90
        return SIXEL_BAD_ARGUMENT;
×
91
    }
NEW
92
    if (path == NULL || path[0] == '\0') {
×
NEW
93
        return SIXEL_OK;
×
94
    }
NEW
95
    logger->file = fopen(path, "w");
×
NEW
96
    if (logger->file == NULL) {
×
NEW
97
        return SIXEL_RUNTIME_ERROR;
×
98
    }
NEW
99
    if (sixel_mutex_init(&logger->mutex) != 0) {
×
NEW
100
        fclose(logger->file);
×
NEW
101
        logger->file = NULL;
×
NEW
102
        return SIXEL_RUNTIME_ERROR;
×
103
    }
NEW
104
    logger->mutex_ready = 1;
×
NEW
105
    logger->active = 1;
×
NEW
106
    logger->started_at = sixel_assessment_timer_now();
×
NEW
107
    setvbuf(logger->file, NULL, _IOLBF, 0);
×
NEW
108
    return SIXEL_OK;
×
109
}
110

111
void
NEW
112
sixel_parallel_logger_logf(sixel_parallel_logger_t *logger,
×
113
                           char const *worker,
114
                           char const *event,
115
                           int job_id,
116
                           int row_index,
117
                           int y0,
118
                           int y1,
119
                           int in0,
120
                           int in1,
121
                           char const *fmt,
122
                           ...)
123
{
124
    char message[256];
125
    char escaped[512];
126
    va_list args;
127
    double timestamp;
128

NEW
129
    if (logger == NULL || !logger->active || logger->file == NULL
×
NEW
130
            || !logger->mutex_ready) {
×
NEW
131
        return;
×
132
    }
133

NEW
134
    va_start(args, fmt);
×
NEW
135
    if (fmt != NULL) {
×
136
#if defined(__clang__)
137
#pragma clang diagnostic push
138
#pragma clang diagnostic ignored "-Wformat-nonliteral"
139
#elif defined(__GNUC__)
140
#pragma GCC diagnostic push
141
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
142
#endif
143
        /*
144
         * The format strings are defined in our code paths.  Suppress the
145
         * nonliteral warning so we can forward variadic arguments safely.
146
         */
NEW
147
        (void)vsnprintf(message, sizeof(message), fmt, args);
×
148
#if defined(__clang__)
149
#pragma clang diagnostic pop
150
#elif defined(__GNUC__)
151
#pragma GCC diagnostic pop
152
#endif
153
    } else {
NEW
154
        message[0] = '\0';
×
155
    }
NEW
156
    va_end(args);
×
157

NEW
158
    sixel_parallel_logger_escape(message, escaped, sizeof(escaped));
×
159

NEW
160
    sixel_mutex_lock(&logger->mutex);
×
NEW
161
    timestamp = sixel_assessment_timer_now() - logger->started_at;
×
NEW
162
    if (timestamp < 0.0) {
×
NEW
163
        timestamp = 0.0;
×
164
    }
NEW
165
    fprintf(logger->file,
×
166
            "{\"ts\":%.6f,\"thread\":%llu,\"worker\":\"%s\","\
167
            "\"event\":\"%s\",\"job\":%d,\"row\":%d,\"y0\":%d,"\
168
            "\"y1\":%d,\"in0\":%d,\"in1\":%d,\"message\":\"%s\"}\n",
169
            timestamp,
170
            sixel_parallel_logger_thread_id(),
171
            worker != NULL ? worker : "",
×
172
            event != NULL ? event : "",
×
173
            job_id,
174
            row_index,
175
            y0,
176
            y1,
177
            in0,
178
            in1,
179
            escaped);
NEW
180
    fflush(logger->file);
×
NEW
181
    sixel_mutex_unlock(&logger->mutex);
×
182
}
183

184
/* emacs Local Variables:      */
185
/* emacs mode: c               */
186
/* emacs tab-width: 4          */
187
/* emacs indent-tabs-mode: nil */
188
/* emacs c-basic-offset: 4     */
189
/* emacs End:                  */
190
/* vim: set expandtab ts=4 sts=4 sw=4 : */
191

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