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

saitoha / libsixel / 21335896708

25 Jan 2026 04:33PM UTC coverage: 76.581% (-2.3%) from 78.904%
21335896708

push

github

saitoha
meson: set build type to plain

20012 of 44638 branches covered (44.83%)

36354 of 47471 relevant lines covered (76.58%)

13461842.27 hits per line

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

86.05
/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
SIXELSTATUS
51
sixel_allocator_new(
5,213✔
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;
5,213✔
59

60
    if (ppallocator == NULL) {
5,213!
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) {
5,213✔
68
        fn_malloc = malloc;
4,145✔
69
    }
1,145✔
70

71
    if (fn_calloc == NULL) {
5,213✔
72
        fn_calloc = calloc;
4,145✔
73
    }
1,145✔
74

75
    if (fn_realloc == NULL) {
5,213✔
76
        fn_realloc = realloc;
4,145✔
77
    }
1,145✔
78

79
    if (fn_free == NULL) {
5,213✔
80
        fn_free = free;
4,145✔
81
    }
1,145✔
82

83
    *ppallocator = fn_malloc(sizeof(sixel_allocator_t));
5,213✔
84
    if (*ppallocator == NULL) {
5,213!
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;
5,213✔
92
    (*ppallocator)->fn_malloc   = fn_malloc;
5,213✔
93
    (*ppallocator)->fn_calloc   = fn_calloc;
5,213✔
94
    (*ppallocator)->fn_realloc  = fn_realloc;
5,213✔
95
    (*ppallocator)->fn_free     = fn_free;
5,213✔
96

97
    status = SIXEL_OK;
5,213✔
98

99
end:
3,801✔
100
    return status;
5,711✔
101
}
498✔
102

103

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

114
    allocator->fn_free(allocator);
5,196✔
115
}
5,196✔
116

117

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

126
    /* precondition */
127
    assert(allocator);
27,304!
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);
27,304✔
135
    (void)previous;
20,910✔
136
}
27,304✔
137

138

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

146
    if (allocator) {
32,500!
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);
32,500!
153
        assert(previous > 0U);
32,500!
154
        if (previous == 1U) {
32,500✔
155
            sixel_allocator_destroy(allocator);
5,196✔
156
        }
1,409✔
157
    }
9,057✔
158
}
32,500✔
159

160

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

171
    if (n == 0) {
5,518,743!
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) {
5,518,743!
178
        return NULL;
179
    }
180

181
    return allocator->fn_malloc(n);
5,518,743✔
182
}
1,841,752✔
183

184

185
/* call custom calloc() */
186
SIXELAPI void *
187
sixel_allocator_calloc(
13,140✔
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;
7,713✔
193

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

198
    n = nelm * elsize;
13,140✔
199

200
    if (n == 0) {
13,140!
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) {
13,140!
207
        return NULL;
208
    }
209

210
    return allocator->fn_calloc(nelm, elsize);
13,140✔
211
}
3,589✔
212

213

214
/* call custom realloc() */
215
SIXELAPI void *
216
sixel_allocator_realloc(
14,114✔
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);
14,114!
223
    assert(allocator->fn_realloc);
14,114!
224

225
    if (n == 0) {
14,114!
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) {
14,114!
232
        return NULL;
233
    }
234

235
    return allocator->fn_realloc(p, n);
14,114✔
236
}
2,492✔
237

238

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

248
    allocator->fn_free(p);
5,593,106✔
249
}
5,593,191✔
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