/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 | 249 | #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 | 461 | static bool is_little_endian(void) { |
36 | 461 | static const int i = 1; |
37 | 461 | char* p = (char*)&i; |
38 | | |
39 | 461 | if (p[0] == 1) { |
40 | 461 | return true; |
41 | 461 | } |
42 | 0 | else { |
43 | 0 | return false; |
44 | 0 | } |
45 | 461 | } blosc2.c:is_little_endian Line | Count | Source | 35 | 212 | static bool is_little_endian(void) { | 36 | 212 | static const int i = 1; | 37 | 212 | char* p = (char*)&i; | 38 | | | 39 | 212 | if (p[0] == 1) { | 40 | 212 | return true; | 41 | 212 | } | 42 | 0 | else { | 43 | | return false; | 44 | 0 | } | 45 | 212 | } |
Unexecuted instantiation: schunk.c:is_little_endian Line | Count | Source | 35 | 249 | static bool is_little_endian(void) { | 36 | 249 | static const int i = 1; | 37 | 249 | char* p = (char*)&i; | 38 | | | 39 | 249 | if (p[0] == 1) { | 40 | 249 | return true; | 41 | 249 | } | 42 | 0 | else { | 43 | | return false; | 44 | 0 | } | 45 | 249 | } |
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 | 249 | { |
50 | 249 | bool little_endian = is_little_endian(); |
51 | 249 | if (little_endian == little) { |
52 | 0 | memcpy(dest, pa, size); |
53 | 0 | } |
54 | 249 | else { |
55 | 249 | uint8_t* pa_ = (uint8_t*)pa; |
56 | 249 | uint8_t pa2_[8]; |
57 | 249 | switch (size) { |
58 | 103 | case 8: |
59 | 103 | pa2_[0] = pa_[7]; |
60 | 103 | pa2_[1] = pa_[6]; |
61 | 103 | pa2_[2] = pa_[5]; |
62 | 103 | pa2_[3] = pa_[4]; |
63 | 103 | pa2_[4] = pa_[3]; |
64 | 103 | pa2_[5] = pa_[2]; |
65 | 103 | pa2_[6] = pa_[1]; |
66 | 103 | pa2_[7] = pa_[0]; |
67 | 103 | break; |
68 | 131 | case 4: |
69 | 131 | pa2_[0] = pa_[3]; |
70 | 131 | pa2_[1] = pa_[2]; |
71 | 131 | pa2_[2] = pa_[1]; |
72 | 131 | pa2_[3] = pa_[0]; |
73 | 131 | break; |
74 | 12 | case 2: |
75 | 12 | pa2_[0] = pa_[1]; |
76 | 12 | pa2_[1] = pa_[0]; |
77 | 12 | break; |
78 | 3 | case 1: |
79 | 3 | pa2_[0] = pa_[0]; |
80 | 3 | break; |
81 | 0 | default: |
82 | 0 | BLOSC_TRACE_ERROR("Unhandled size: %d.", size); |
83 | 249 | } |
84 | 249 | memcpy(dest, pa2_, size); |
85 | 249 | } |
86 | 249 | } Unexecuted instantiation: blosc2.c:endian_handler Unexecuted instantiation: schunk.c:endian_handler Line | Count | Source | 49 | 249 | { | 50 | 249 | bool little_endian = is_little_endian(); | 51 | 249 | if (little_endian == little) { | 52 | 0 | memcpy(dest, pa, size); | 53 | 0 | } | 54 | 249 | else { | 55 | 249 | uint8_t* pa_ = (uint8_t*)pa; | 56 | 249 | uint8_t pa2_[8]; | 57 | 249 | switch (size) { | 58 | 103 | case 8: | 59 | 103 | pa2_[0] = pa_[7]; | 60 | 103 | pa2_[1] = pa_[6]; | 61 | 103 | pa2_[2] = pa_[5]; | 62 | 103 | pa2_[3] = pa_[4]; | 63 | 103 | pa2_[4] = pa_[3]; | 64 | 103 | pa2_[5] = pa_[2]; | 65 | 103 | pa2_[6] = pa_[1]; | 66 | 103 | pa2_[7] = pa_[0]; | 67 | 103 | break; | 68 | 131 | case 4: | 69 | 131 | pa2_[0] = pa_[3]; | 70 | 131 | pa2_[1] = pa_[2]; | 71 | 131 | pa2_[2] = pa_[1]; | 72 | 131 | pa2_[3] = pa_[0]; | 73 | 131 | break; | 74 | 12 | case 2: | 75 | 12 | pa2_[0] = pa_[1]; | 76 | 12 | pa2_[1] = pa_[0]; | 77 | 12 | break; | 78 | 3 | case 1: | 79 | 3 | pa2_[0] = pa_[0]; | 80 | 3 | break; | 81 | 0 | default: | 82 | 0 | BLOSC_TRACE_ERROR("Unhandled size: %d.", size); | 83 | 249 | } | 84 | 249 | memcpy(dest, pa2_, size); | 85 | 249 | } | 86 | 249 | } |
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 | 70 | static inline int32_t sw32_(const void* pa) { |
90 | 70 | int32_t idest; |
91 | | |
92 | 70 | bool little_endian = is_little_endian(); |
93 | 70 | if (little_endian) { |
94 | 70 | memcpy(&idest, pa, sizeof(idest)); |
95 | 70 | } |
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 | 70 | return idest; |
111 | 70 | } Line | Count | Source | 89 | 70 | static inline int32_t sw32_(const void* pa) { | 90 | 70 | int32_t idest; | 91 | | | 92 | 70 | bool little_endian = is_little_endian(); | 93 | 70 | if (little_endian) { | 94 | 70 | memcpy(&idest, pa, sizeof(idest)); | 95 | 70 | } | 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 | 70 | return idest; | 111 | 70 | } |
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 | 0 | static inline void _sw32(void* dest, int32_t a) { |
115 | 0 | uint8_t* dest_ = (uint8_t*)dest; |
116 | 0 | uint8_t* pa = (uint8_t*)&a; |
117 | |
|
118 | 0 | bool little_endian = is_little_endian(); |
119 | 0 | if (little_endian) { |
120 | 0 | memcpy(dest_, &a, sizeof(a));; |
121 | 0 | } |
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 | 0 | } Unexecuted instantiation: blosc2.c:_sw32 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 */ |