Coverage Report

Created: 2026-04-09 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/c-blosc2/blosc/blosc-private.h
Line
Count
Source
1
/*********************************************************************
2
  Blosc - Blocked Shuffling and Compression Library
3
4
  Copyright (c) 2021  Blosc Development Team <blosc@blosc.org>
5
  https://blosc.org
6
  License: BSD 3-Clause (see LICENSE.txt)
7
8
  See LICENSE.txt for details about copyright and rights to use.
9
**********************************************************************/
10
11
12
#ifndef BLOSC_BLOSC_PRIVATE_H
13
#define BLOSC_BLOSC_PRIVATE_H
14
15
#include "blosc2/blosc2-common.h"
16
#include "blosc2.h"
17
18
#include <stdbool.h>
19
#include <stdlib.h>
20
#include <stdint.h>
21
22
/*********************************************************************
23
24
  Utility functions meant to be used internally.
25
26
*********************************************************************/
27
28
0
#define to_little(dest, src, itemsize)    endian_handler(true, dest, src, itemsize)
29
#define from_little(dest, src, itemsize)  endian_handler(true, dest, src, itemsize)
30
0
#define to_big(dest, src, itemsize)       endian_handler(false, dest, src, itemsize)
31
0
#define from_big(dest, src, itemsize)     endian_handler(false, dest, src, itemsize)
32
33
34
// Return true if platform is little endian; else false
35
1.03M
static bool is_little_endian(void) {
36
1.03M
  static const int i = 1;
37
1.03M
  char* p = (char*)&i;
38
39
1.03M
  if (p[0] == 1) {
40
1.03M
    return true;
41
1.03M
  }
42
0
  else {
43
0
    return false;
44
0
  }
45
1.03M
}
blosc2.c:is_little_endian
Line
Count
Source
35
1.03M
static bool is_little_endian(void) {
36
1.03M
  static const int i = 1;
37
1.03M
  char* p = (char*)&i;
38
39
1.03M
  if (p[0] == 1) {
40
1.03M
    return true;
41
1.03M
  }
42
0
  else {
43
    return false;
44
0
  }
45
1.03M
}
Unexecuted instantiation: schunk.c:is_little_endian
Unexecuted instantiation: frame.c:is_little_endian
Unexecuted instantiation: codecs-registry.c:is_little_endian
Unexecuted instantiation: tuners-registry.c:is_little_endian
Unexecuted instantiation: filters-registry.c:is_little_endian
46
47
48
static inline void endian_handler(bool little, void *dest, const void *pa, int size)
49
0
{
50
0
  bool little_endian = is_little_endian();
51
0
  if (little_endian == little) {
52
0
    memcpy(dest, pa, size);
53
0
  }
54
0
  else {
55
0
    uint8_t* pa_ = (uint8_t*)pa;
56
0
    uint8_t pa2_[8];
57
0
    switch (size) {
58
0
      case 8:
59
0
        pa2_[0] = pa_[7];
60
0
        pa2_[1] = pa_[6];
61
0
        pa2_[2] = pa_[5];
62
0
        pa2_[3] = pa_[4];
63
0
        pa2_[4] = pa_[3];
64
0
        pa2_[5] = pa_[2];
65
0
        pa2_[6] = pa_[1];
66
0
        pa2_[7] = pa_[0];
67
0
        break;
68
0
      case 4:
69
0
        pa2_[0] = pa_[3];
70
0
        pa2_[1] = pa_[2];
71
0
        pa2_[2] = pa_[1];
72
0
        pa2_[3] = pa_[0];
73
0
        break;
74
0
      case 2:
75
0
        pa2_[0] = pa_[1];
76
0
        pa2_[1] = pa_[0];
77
0
        break;
78
0
      case 1:
79
0
        pa2_[0] = pa_[0];
80
0
        break;
81
0
      default:
82
0
        BLOSC_TRACE_ERROR("Unhandled size: %d.", size);
83
0
    }
84
0
    memcpy(dest, pa2_, size);
85
0
  }
86
0
}
Unexecuted instantiation: blosc2.c:endian_handler
Unexecuted instantiation: schunk.c:endian_handler
Unexecuted instantiation: frame.c:endian_handler
Unexecuted instantiation: codecs-registry.c:endian_handler
Unexecuted instantiation: tuners-registry.c:endian_handler
Unexecuted instantiation: filters-registry.c:endian_handler
87
88
/* Copy 4 bytes from @p *pa to int32_t, changing endianness if necessary. */
89
86.3k
static inline int32_t sw32_(const void* pa) {
90
86.3k
  int32_t idest;
91
92
86.3k
  bool little_endian = is_little_endian();
93
86.3k
  if (little_endian) {
94
86.3k
    memcpy(&idest, pa, sizeof(idest));
95
86.3k
  }
96
0
  else {
97
0
#if defined (__GNUC__)
98
0
    return __builtin_bswap32(*(unsigned int *)pa);
99
#elif defined (_MSC_VER) /* Visual Studio */
100
    return _byteswap_ulong(*(unsigned int *)pa);
101
#else
102
    const uint8_t *pa_ = (const uint8_t *)pa;
103
    uint8_t *dest = (uint8_t *)&idest;
104
    dest[0] = pa_[3];
105
    dest[1] = pa_[2];
106
    dest[2] = pa_[1];
107
    dest[3] = pa_[0];
108
#endif
109
0
  }
110
86.3k
  return idest;
111
86.3k
}
blosc2.c:sw32_
Line
Count
Source
89
86.3k
static inline int32_t sw32_(const void* pa) {
90
86.3k
  int32_t idest;
91
92
86.3k
  bool little_endian = is_little_endian();
93
86.3k
  if (little_endian) {
94
86.3k
    memcpy(&idest, pa, sizeof(idest));
95
86.3k
  }
96
0
  else {
97
0
#if defined (__GNUC__)
98
0
    return __builtin_bswap32(*(unsigned int *)pa);
99
#elif defined (_MSC_VER) /* Visual Studio */
100
    return _byteswap_ulong(*(unsigned int *)pa);
101
#else
102
    const uint8_t *pa_ = (const uint8_t *)pa;
103
    uint8_t *dest = (uint8_t *)&idest;
104
    dest[0] = pa_[3];
105
    dest[1] = pa_[2];
106
    dest[2] = pa_[1];
107
    dest[3] = pa_[0];
108
#endif
109
0
  }
110
86.3k
  return idest;
111
86.3k
}
Unexecuted instantiation: schunk.c:sw32_
Unexecuted instantiation: frame.c:sw32_
Unexecuted instantiation: codecs-registry.c:sw32_
Unexecuted instantiation: tuners-registry.c:sw32_
Unexecuted instantiation: filters-registry.c:sw32_
112
113
/* Copy 4 bytes from int32_t to @p *dest, changing endianness if necessary. */
114
862k
static inline void _sw32(void* dest, int32_t a) {
115
862k
  uint8_t* dest_ = (uint8_t*)dest;
116
862k
  uint8_t* pa = (uint8_t*)&a;
117
118
862k
  bool little_endian = is_little_endian();
119
862k
  if (little_endian) {
120
862k
    memcpy(dest_, &a, sizeof(a));;
121
862k
  }
122
0
  else {
123
0
#if defined (__GNUC__)
124
0
    *(int32_t *)dest_ = __builtin_bswap32(*(unsigned int *)pa);
125
#elif defined (_MSC_VER) /* Visual Studio */
126
    *(int32_t *)dest_ = _byteswap_ulong(*(unsigned int *)pa);
127
#else
128
    dest_[0] = pa[3];
129
    dest_[1] = pa[2];
130
    dest_[2] = pa[1];
131
    dest_[3] = pa[0];
132
#endif
133
0
  }
134
862k
}
blosc2.c:_sw32
Line
Count
Source
114
862k
static inline void _sw32(void* dest, int32_t a) {
115
862k
  uint8_t* dest_ = (uint8_t*)dest;
116
862k
  uint8_t* pa = (uint8_t*)&a;
117
118
862k
  bool little_endian = is_little_endian();
119
862k
  if (little_endian) {
120
862k
    memcpy(dest_, &a, sizeof(a));;
121
862k
  }
122
0
  else {
123
0
#if defined (__GNUC__)
124
0
    *(int32_t *)dest_ = __builtin_bswap32(*(unsigned int *)pa);
125
#elif defined (_MSC_VER) /* Visual Studio */
126
    *(int32_t *)dest_ = _byteswap_ulong(*(unsigned int *)pa);
127
#else
128
    dest_[0] = pa[3];
129
    dest_[1] = pa[2];
130
    dest_[2] = pa[1];
131
    dest_[3] = pa[0];
132
#endif
133
0
  }
134
862k
}
Unexecuted instantiation: schunk.c:_sw32
Unexecuted instantiation: frame.c:_sw32
Unexecuted instantiation: codecs-registry.c:_sw32
Unexecuted instantiation: tuners-registry.c:_sw32
Unexecuted instantiation: filters-registry.c:_sw32
135
136
/* Reverse swap bits in a 32-bit integer */
137
0
static inline int32_t bswap32_(int32_t a) {
138
0
#if defined (__GNUC__)
139
0
  return __builtin_bswap32(a);
140
141
#elif defined (_MSC_VER) /* Visual Studio */
142
  return _byteswap_ulong(a);
143
#else
144
  a = ((a & 0x000000FF) << 24) |
145
      ((a & 0x0000FF00) <<  8) |
146
      ((a & 0x00FF0000) >>  8) |
147
      ((a & 0xFF000000) >> 24);
148
  return a;
149
#endif
150
0
}
Unexecuted instantiation: blosc2.c:bswap32_
Unexecuted instantiation: schunk.c:bswap32_
Unexecuted instantiation: frame.c:bswap32_
Unexecuted instantiation: codecs-registry.c:bswap32_
Unexecuted instantiation: tuners-registry.c:bswap32_
Unexecuted instantiation: filters-registry.c:bswap32_
151
152
/**
153
 * @brief Register a filter in Blosc.
154
 *
155
 * @param filter The filter to register.
156
 *
157
 * @return 0 if succeeds. Else a negative code is returned.
158
 */
159
int register_filter_private(blosc2_filter *filter);
160
161
/**
162
 * @brief Register a codec in Blosc.
163
 *
164
 * @param codec The codec to register.
165
 *
166
 * @return 0 if succeeds. Else a negative code is returned.
167
 */
168
int register_codec_private(blosc2_codec *codec);
169
170
171
/**
172
 * @brief Register a tune in Blosc.
173
 *
174
 * @param tune The tune to register.
175
 *
176
 * @return 0 if succeeds. Else a negative code is returned.
177
 */
178
int register_tuner_private(blosc2_tuner *tuner);
179
180
int fill_tuner(blosc2_tuner *tuner);
181
182
extern blosc2_tuner g_tuners[256];
183
extern int g_ntuners;
184
185
186
#if defined(_WIN32)
187
#include <windows.h>
188
#ifndef PATH_MAX
189
#define PATH_MAX MAX_PATH
190
#endif
191
#define RTLD_LAZY   0x000
192
#define popen _popen
193
#define pclose _pclose
194
195
static struct {
196
    long lasterror;
197
    const char *err_rutin;
198
}
199
var = {
200
    0,
201
    NULL
202
};
203
204
static inline void *dlopen (const char *filename, int flags) {
205
  BLOSC_UNUSED_PARAM(flags);
206
  HINSTANCE hInst;
207
  hInst = LoadLibrary(filename);
208
  if (hInst==NULL) {
209
    var.lasterror = GetLastError();
210
    var.err_rutin = "dlopen";
211
  }
212
213
  return hInst;
214
}
215
216
static inline void *dlsym(void *handle, const char *name) {
217
  FARPROC fp;
218
  fp = GetProcAddress((HINSTANCE)handle, name);
219
  if (!fp) {
220
    var.lasterror = GetLastError ();
221
    var.err_rutin = "dlsym";
222
  }
223
  return (void *)(intptr_t)fp;
224
}
225
226
static inline int dlclose(void *handle) {
227
  bool ok = FreeLibrary((HINSTANCE)handle);
228
  if (!ok) {
229
    var.lasterror = GetLastError();
230
    var.err_rutin = "dlclose";
231
    return BLOSC2_ERROR_FAILURE;
232
  }
233
  return BLOSC2_ERROR_SUCCESS;
234
}
235
236
static inline const char *dlerror (void) {
237
  static char errstr [88];
238
  if (var.lasterror) {
239
      sprintf (errstr, "%s error #%ld", var.err_rutin, var.lasterror);
240
      return errstr;
241
  } else {
242
      return NULL;
243
  }
244
}
245
#else
246
#include <dlfcn.h>
247
#endif
248
249
250
0
static inline int get_libpath(char *plugin_name, char *libpath, char *python_version) {
251
0
  BLOSC_TRACE_INFO("Trying to get plugin path with python%s\n", python_version);
252
0
  char python_cmd[PATH_MAX] = {0};
253
0
  sprintf(python_cmd, "python%s -c \"import blosc2_%s; blosc2_%s.print_libpath()\"", python_version, plugin_name, plugin_name);
254
0
  FILE *fp = popen(python_cmd, "r");
255
0
  if (fp == NULL) {
256
0
    BLOSC_TRACE_ERROR("Could not run python");
257
0
    return BLOSC2_ERROR_FAILURE;
258
0
  }
259
0
  if (fgets(libpath, PATH_MAX, fp) == NULL) {
260
0
    BLOSC_TRACE_ERROR("Could not read python output");
261
0
    pclose(fp);
262
0
    return BLOSC2_ERROR_FAILURE;
263
0
  }
264
0
  pclose(fp);
265
266
0
  return BLOSC2_ERROR_SUCCESS;
267
0
}
Unexecuted instantiation: blosc2.c:get_libpath
Unexecuted instantiation: schunk.c:get_libpath
Unexecuted instantiation: frame.c:get_libpath
Unexecuted instantiation: codecs-registry.c:get_libpath
Unexecuted instantiation: tuners-registry.c:get_libpath
Unexecuted instantiation: filters-registry.c:get_libpath
268
269
0
static inline void* load_lib(char *plugin_name, char *libpath) {
270
    // Attempt to directly load the library by name
271
#if defined(_WIN32)
272
    // Windows dynamic library (DLL) format
273
    snprintf(libpath, PATH_MAX, "blosc2_%s.dll", plugin_name);
274
#else
275
    // Unix/Linux/Mac OS dynamic library (.so) format
276
0
    snprintf(libpath, PATH_MAX, "libblosc2_%s.so", plugin_name);
277
0
#endif
278
0
    void* loaded_lib = dlopen(libpath, RTLD_LAZY);
279
0
    if (loaded_lib != NULL) {
280
0
        BLOSC_TRACE_INFO("Successfully loaded %s directly\n", libpath);
281
0
        return loaded_lib;
282
0
    } else {
283
#if defined(_WIN32)
284
        BLOSC_TRACE_INFO("Failed to load %s directly, error: %lu\n", libpath, GetLastError());
285
#else
286
0
        BLOSC_TRACE_INFO("Failed to load %s directly, error: %s\n", libpath, dlerror());
287
0
#endif
288
0
    }
289
    // If direct loading fails, fallback to using Python to find the library path
290
0
    if (get_libpath(plugin_name, libpath, "") < 0 && get_libpath(plugin_name, libpath, "3") < 0) {
291
0
        BLOSC_TRACE_ERROR("Problems when running python or python3 for getting plugin path");
292
0
        return NULL;
293
0
    }
294
295
0
    if (strlen(libpath) == 0) {
296
0
        BLOSC_TRACE_ERROR("Could not find plugin libpath");
297
0
        return NULL;
298
0
    }
299
300
    // Try to load the library again with the path from Python
301
0
    loaded_lib = dlopen(libpath, RTLD_LAZY);
302
0
    if (loaded_lib == NULL) {
303
0
        BLOSC_TRACE_ERROR("Attempt to load plugin in path '%s' failed with error: %s", libpath, dlerror());
304
0
    } else {
305
0
        BLOSC_TRACE_INFO("Successfully loaded library with Python path: %s\n", libpath);
306
0
    }
307
308
0
    return loaded_lib;
309
0
}
Unexecuted instantiation: blosc2.c:load_lib
Unexecuted instantiation: schunk.c:load_lib
Unexecuted instantiation: frame.c:load_lib
Unexecuted instantiation: codecs-registry.c:load_lib
Unexecuted instantiation: tuners-registry.c:load_lib
Unexecuted instantiation: filters-registry.c:load_lib
310
311
312
#endif /* BLOSC_BLOSC_PRIVATE_H */