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

saitoha / libsixel / 25532151378

08 May 2026 01:45AM UTC coverage: 85.542% (+0.008%) from 85.534%
25532151378

push

github

saitoha
ci: fix experimental vcpkg checkout eol

126839 of 269435 branches covered (47.08%)

152560 of 178346 relevant lines covered (85.54%)

8894051.04 hits per line

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

86.21
/src/allocator.c
1
/*
2
 * SPDX-License-Identifier: MIT
3
 *
4
 * Copyright (c) 2021-2025 libsixel developers. See `AUTHORS`.
5
 * Copyright (c) 2014-2018 Hayaki Saito
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8
 * this software and associated documentation files (the "Software"), to deal in
9
 * the Software without restriction, including without limitation the rights to
10
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
 * the Software, and to permit persons to whom the Software is furnished to do so,
12
 * subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in all
15
 * copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24

25
#if defined(HAVE_CONFIG_H)
26
#include "config.h"
27
#endif
28

29
/* STDC_HEADERS */
30
#include <stdlib.h>
31

32
#if HAVE_ASSERT_H
33
# include <assert.h>
34
#endif  /* HAVE_ASSERT_H */
35
#if HAVE_SYS_TYPES_H
36
# include <sys/types.h>
37
#endif  /* HAVE_SYS_TYPES_H */
38
#if HAVE_ERRNO_H
39
# include <errno.h>
40
#endif  /* HAVE_ERRNO_H */
41
#if HAVE_MEMORY_H
42
# include <memory.h>
43
#endif  /* HAVE_MEMORY_H */
44

45
#include "allocator.h"
46
#include "malloc_stub.h"
47
#include "sixel_atomic.h"
48

49
/* create allocator object */
50
SIXELAPI SIXELSTATUS
51
sixel_allocator_new(
108,932✔
52
    sixel_allocator_t   /* out */ **ppallocator,  /* allocator object to be created */
53
    sixel_malloc_t      /* in */  fn_malloc,      /* custom malloc() function */
54
    sixel_calloc_t      /* in */  fn_calloc,      /* custom calloc() function */
55
    sixel_realloc_t     /* in */  fn_realloc,     /* custom realloc() function */
56
    sixel_free_t        /* in */  fn_free)        /* custom free() function */
57
{
58
    SIXELSTATUS status = SIXEL_FALSE;
108,932✔
59

60
    if (ppallocator == NULL) {
108,932!
61
        sixel_helper_set_additional_message(
×
62
            "sixel_allocator_new: given argument ppallocator is null.");
63
        status = SIXEL_BAD_ARGUMENT;
×
64
        goto end;
×
65
    }
66

67
    if (fn_malloc == NULL) {
108,932✔
68
        fn_malloc = malloc;
85,221✔
69
    }
36,136✔
70

71
    if (fn_calloc == NULL) {
107,674✔
72
        fn_calloc = calloc;
85,222✔
73
    }
36,136✔
74

75
    if (fn_realloc == NULL) {
107,674✔
76
        fn_realloc = realloc;
85,222✔
77
    }
36,136✔
78

79
    if (fn_free == NULL) {
107,674✔
80
        fn_free = free;
85,222✔
81
    }
36,136✔
82

83
    *ppallocator = fn_malloc(sizeof(sixel_allocator_t));
108,932✔
84
    if (*ppallocator == NULL) {
108,932!
85
        sixel_helper_set_additional_message(
×
86
            "sixel_allocator_new: fn_malloc() failed.");
87
        status = SIXEL_BAD_ALLOCATION;
×
88
        goto end;
×
89
    }
90

91
    (*ppallocator)->ref         = 1;
108,932✔
92
    (*ppallocator)->fn_malloc   = fn_malloc;
108,932✔
93
    (*ppallocator)->fn_calloc   = fn_calloc;
108,932✔
94
    (*ppallocator)->fn_realloc  = fn_realloc;
108,932✔
95
    (*ppallocator)->fn_free     = fn_free;
108,932✔
96

97
    status = SIXEL_OK;
108,932✔
98

99
end:
62,882✔
100
    return status;
135,351✔
101
}
26,419✔
102

103

104
/* destruct allocator object */
105
static void
106
sixel_allocator_destroy(
108,908✔
107
    sixel_allocator_t /* in */ *allocator)  /* allocator object to
108
                                               be destroyed */
109
{
110
    /* precondition */
111
    assert(allocator);
108,908!
112
    assert(allocator->fn_free);
108,908!
113

114
    allocator->fn_free(allocator);
108,908✔
115
}
108,908✔
116

117

118
/* increase reference count of allocator object (thread-safe) */
119
SIXELAPI void
120
sixel_allocator_ref(
1,380,627✔
121
    sixel_allocator_t /* in */ *allocator)  /* allocator object to be
122
                                               increment reference counter */
123
{
124
    unsigned int previous;
721,301✔
125

126
    /* precondition */
127
    assert(allocator);
1,380,627!
128

129
    /*
130
     * Increment the reference counter atomically so concurrent users can
131
     * retain the allocator without racing against a release in another
132
     * thread.
133
     */
134
    previous = sixel_atomic_fetch_add_u32(&allocator->ref, 1U);
1,380,628✔
135
    (void)previous;
986,774✔
136
}
1,380,627✔
137

138

139
/* decrease reference count of output context object (thread-safe) */
140
SIXELAPI void
141
sixel_allocator_unref(
1,489,588✔
142
    sixel_allocator_t /* in */ *allocator)  /* allocator object to be unreference */
143
{
144
    unsigned int previous;
777,133✔
145

146
    if (allocator) {
1,489,588!
147
        /*
148
         * Acquire the previous value atomically. The old count informs us
149
         * whether this thread dropped the last reference, which drives the
150
         * destruction path below.
151
         */
152
        previous = sixel_atomic_fetch_sub_u32(&allocator->ref, 1U);
1,489,589!
153
        assert(previous > 0U);
1,489,589!
154
        if (previous == 1U) {
1,489,589✔
155
            sixel_allocator_destroy(allocator);
108,908✔
156
        }
46,041✔
157
    }
687,240✔
158
}
1,489,590✔
159

160

161
/* call custom malloc() */
162
SIXELAPI void *
163
sixel_allocator_malloc(
18,800,464✔
164
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
165
    size_t              /* in */ n)           /* allocation size */
166
{
167
    /* precondition */
168
    assert(allocator);
18,800,464!
169
    assert(allocator->fn_malloc);
18,800,655!
170

171
    if (n == 0) {
18,800,615!
172
        sixel_helper_set_additional_message(
×
173
            "sixel_allocator_malloc: called with n == 0");
174
        return NULL;
×
175
    }
176

177
    if (n > SIXEL_ALLOCATE_BYTES_MAX) {
18,800,453✔
178
        return NULL;
34✔
179
    }
180

181
    return allocator->fn_malloc(n);
18,800,396✔
182
}
9,401,792✔
183

184

185
/* call custom calloc() */
186
SIXELAPI void *
187
sixel_allocator_calloc(
334,154✔
188
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
189
    size_t              /* in */ nelm,        /* number of elements */
190
    size_t              /* in */ elsize)      /* size of element */
191
{
192
    size_t n;
171,166✔
193

194
    /* precondition */
195
    assert(allocator);
334,154!
196
    assert(allocator->fn_calloc);
334,154!
197

198
    n = nelm * elsize;
334,151✔
199

200
    if (n == 0) {
334,151!
201
        sixel_helper_set_additional_message(
×
202
            "sixel_allocator_malloc: called with n == 0");
203
        return NULL;
×
204
    }
205

206
    if (n > SIXEL_ALLOCATE_BYTES_MAX) {
334,151!
207
        return NULL;
208
    }
209

210
    return allocator->fn_calloc(nelm, elsize);
334,149✔
211
}
146,706✔
212

213

214
/* call custom realloc() */
215
SIXELAPI void *
216
sixel_allocator_realloc(
56,893✔
217
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
218
    void                /* in */ *p,          /* existing buffer to be re-allocated */
219
    size_t              /* in */ n)           /* re-allocation size */
220
{
221
    /* precondition */
222
    assert(allocator);
56,893!
223
    assert(allocator->fn_realloc);
56,893!
224

225
    if (n == 0) {
56,893!
226
        sixel_helper_set_additional_message(
×
227
            "sixel_allocator_malloc: called with n == 0");
228
        return NULL;
×
229
    }
230

231
    if (n > SIXEL_ALLOCATE_BYTES_MAX) {
56,893!
232
        return NULL;
233
    }
234

235
    return allocator->fn_realloc(p, n);
56,893✔
236
}
21,189✔
237

238

239
/* call custom free() */
240
SIXELAPI void
241
sixel_allocator_free(
20,961,577✔
242
    sixel_allocator_t   /* in */ *allocator,  /* allocator object */
243
    void                /* in */ *p)          /* existing buffer to be freed */
244
{
245
    /* precondition */
246
    assert(allocator);
20,961,577!
247

248
    allocator->fn_free(p);
20,961,580✔
249
}
20,962,195✔
250

251

252

253
#if 0
254
int
255
rpl_posix_memalign(void **memptr, size_t alignment, size_t size)
256
{
257
#if HAVE_POSIX_MEMALIGN
258
    return posix_memalign(memptr, alignment, size);
259
#elif HAVE_ALIGNED_ALLOC
260
    *memptr = aligned_alloc(alignment, size);
261
    return *memptr ? 0: ENOMEM;
262
#elif HAVE_MEMALIGN
263
    *memptr = memalign(alignment, size);
264
    return *memptr ? 0: ENOMEM;
265
#elif HAVE__ALIGNED_MALLOC
266
    return _aligned_malloc(size, alignment);
267
#else
268
# error
269
#endif /* _MSC_VER */
270
}
271
#endif
272

273

274

275
/* emacs Local Variables:      */
276
/* emacs mode: c               */
277
/* emacs tab-width: 4          */
278
/* emacs indent-tabs-mode: nil */
279
/* emacs c-basic-offset: 4     */
280
/* emacs End:                  */
281
/* vim: set expandtab ts=4 sts=4 sw=4 : */
282
/* 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