1 /*
2 * (C) Copyright 2005- ECMWF.
3 *
4 * This software is licensed under the terms of the Apache Licence Version 2.0
5 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 *
7 * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8 * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9 */
10
11 #include "grib_api_internal.h"
12 #include <errno.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #ifndef ECCODES_ON_WINDOWS
16 #include <unistd.h>
17 #else
18 #include <fcntl.h> /* Windows: for _O_BINARY */
19 #endif
20
21 #ifdef ENABLE_FLOATING_POINT_EXCEPTIONS
22 #define _GNU_SOURCE
23 #include <fenv.h>
24 int feenableexcept(int excepts);
25 #endif
26
27 grib_string_list grib_file_not_found;
28
29 /* Windows always has a colon in pathnames e.g. C:\temp\file. So instead we use semi-colons as delimiter */
30 /* in order to have multiple definitions/samples directories */
31 #ifdef ECCODES_ON_WINDOWS
32 #define ECC_PATH_DELIMITER_CHAR ';'
33 #define ECC_PATH_DELIMITER_STR ";"
34 #else
35 #define ECC_PATH_DELIMITER_CHAR ':'
36 #define ECC_PATH_DELIMITER_STR ":"
37 #endif
38
39 #if GRIB_PTHREADS
40 static pthread_once_t once = PTHREAD_ONCE_INIT;
41
42 static pthread_mutex_t mutex_mem = PTHREAD_MUTEX_INITIALIZER;
43 static pthread_mutex_t mutex_c = PTHREAD_MUTEX_INITIALIZER;
44
init()45 static void init()
46 {
47 pthread_mutexattr_t attr;
48 pthread_mutexattr_init(&attr);
49 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
50 pthread_mutex_init(&mutex_c, &attr);
51 pthread_mutex_init(&mutex_mem, &attr);
52 pthread_mutexattr_destroy(&attr);
53 }
54 #elif GRIB_OMP_THREADS
55 static int once = 0;
56 static omp_nest_lock_t mutex_mem;
57 static omp_nest_lock_t mutex_c;
58
init()59 static void init()
60 {
61 GRIB_OMP_CRITICAL(lock_grib_context_c)
62 {
63 if (once == 0) {
64 omp_init_nest_lock(&mutex_mem);
65 omp_init_nest_lock(&mutex_c);
66 once = 1;
67 }
68 }
69 }
70 #endif
71
72
73 #if MANAGE_MEM
74
75 #else
76
default_long_lasting_free(const grib_context * c,void * p)77 static void default_long_lasting_free(const grib_context* c, void* p)
78 {
79 free(p);
80 }
81
default_long_lasting_malloc(const grib_context * c,size_t size)82 static void* default_long_lasting_malloc(const grib_context* c, size_t size)
83 {
84 void* ret;
85 ret = malloc(size);
86 if (!ret) {
87 grib_context_log(c, GRIB_LOG_FATAL, "default_long_lasting_malloc: error allocating %lu bytes", (unsigned long)size);
88 Assert(0);
89 }
90 return ret;
91 }
92
default_buffer_free(const grib_context * c,void * p)93 static void default_buffer_free(const grib_context* c, void* p)
94 {
95 free(p);
96 }
97
default_buffer_malloc(const grib_context * c,size_t size)98 static void* default_buffer_malloc(const grib_context* c, size_t size)
99 {
100 void* ret;
101 ret = malloc(size);
102 if (!ret) {
103 grib_context_log(c, GRIB_LOG_FATAL, "default_buffer_malloc: error allocating %lu bytes", (unsigned long)size);
104 Assert(0);
105 }
106 return ret;
107 }
108
default_buffer_realloc(const grib_context * c,void * p,size_t size)109 static void* default_buffer_realloc(const grib_context* c, void* p, size_t size)
110 {
111 void* ret;
112 ret = realloc(p, size);
113 if (!ret) {
114 grib_context_log(c, GRIB_LOG_FATAL, "default_buffer_realloc: error allocating %lu bytes", (unsigned long)size);
115 Assert(0);
116 }
117 return ret;
118 }
119
default_free(const grib_context * c,void * p)120 static void default_free(const grib_context* c, void* p)
121 {
122 free(p);
123 }
124
default_malloc(const grib_context * c,size_t size)125 static void* default_malloc(const grib_context* c, size_t size)
126 {
127 void* ret;
128 ret = malloc(size);
129 if (!ret) {
130 grib_context_log(c, GRIB_LOG_FATAL, "default_malloc: error allocating %lu bytes", (unsigned long)size);
131 Assert(0);
132 }
133 return ret;
134 }
135
default_realloc(const grib_context * c,void * p,size_t size)136 static void* default_realloc(const grib_context* c, void* p, size_t size)
137 {
138 void* ret;
139 ret = realloc(p, size);
140 if (!ret) {
141 grib_context_log(c, GRIB_LOG_FATAL, "default_realloc: error allocating %lu bytes", (unsigned long)size);
142 Assert(0);
143 }
144 return ret;
145 }
146 #endif
147
default_read(const grib_context * c,void * ptr,size_t size,void * stream)148 static size_t default_read(const grib_context* c, void* ptr, size_t size, void* stream)
149 {
150 return fread(ptr, 1, size, (FILE*)stream);
151 }
152
default_tell(const grib_context * c,void * stream)153 static off_t default_tell(const grib_context* c, void* stream)
154 {
155 return ftello((FILE*)stream);
156 }
157
default_seek(const grib_context * c,off_t offset,int whence,void * stream)158 static off_t default_seek(const grib_context* c, off_t offset, int whence, void* stream)
159 {
160 return fseeko((FILE*)stream, offset, whence);
161 }
162
default_feof(const grib_context * c,void * stream)163 static int default_feof(const grib_context* c, void* stream)
164 {
165 return feof((FILE*)stream);
166 }
167
default_write(const grib_context * c,const void * ptr,size_t size,void * stream)168 static size_t default_write(const grib_context* c, const void* ptr, size_t size, void* stream)
169 {
170 return fwrite(ptr, 1, size, (FILE*)stream);
171 }
172
grib_context_read(const grib_context * c,void * ptr,size_t size,void * stream)173 size_t grib_context_read(const grib_context* c, void* ptr, size_t size, void* stream)
174 {
175 if (!c)
176 c = grib_context_get_default();
177 return c->read(c, ptr, size, stream);
178 }
179
grib_context_tell(const grib_context * c,void * stream)180 off_t grib_context_tell(const grib_context* c, void* stream)
181 {
182 if (!c)
183 c = grib_context_get_default();
184 return c->tell(c, stream);
185 }
186
grib_context_seek(const grib_context * c,off_t offset,int whence,void * stream)187 int grib_context_seek(const grib_context* c, off_t offset, int whence, void* stream)
188 {
189 if (!c)
190 c = grib_context_get_default();
191 return c->seek(c, offset, whence, stream);
192 }
193
grib_context_eof(const grib_context * c,void * stream)194 int grib_context_eof(const grib_context* c, void* stream)
195 {
196 if (!c)
197 c = grib_context_get_default();
198 return c->eof(c, stream);
199 }
200
grib_context_write(const grib_context * c,const void * ptr,size_t size,void * stream)201 size_t grib_context_write(const grib_context* c, const void* ptr, size_t size, void* stream)
202 {
203 if (!c)
204 c = grib_context_get_default();
205 return c->write(c, ptr, size, stream);
206 }
207
default_log(const grib_context * c,int level,const char * mess)208 static void default_log(const grib_context* c, int level, const char* mess)
209 {
210 if (!c)
211 c = grib_context_get_default();
212 if (level == GRIB_LOG_ERROR) {
213 fprintf(c->log_stream, "ECCODES ERROR : %s\n", mess);
214 /*Assert(1==0);*/
215 }
216 if (level == GRIB_LOG_FATAL)
217 fprintf(c->log_stream, "ECCODES ERROR : %s\n", mess);
218 if (level == GRIB_LOG_DEBUG && c->debug > 0)
219 fprintf(c->log_stream, "ECCODES DEBUG : %s\n", mess);
220 if (level == GRIB_LOG_WARNING)
221 fprintf(c->log_stream, "ECCODES WARNING : %s\n", mess);
222 if (level == GRIB_LOG_INFO)
223 fprintf(c->log_stream, "ECCODES INFO : %s\n", mess);
224
225 if (level == GRIB_LOG_FATAL) {
226 Assert(0);
227 }
228
229 if (getenv("ECCODES_FAIL_IF_LOG_MESSAGE")) {
230 long n = atol(getenv("ECCODES_FAIL_IF_LOG_MESSAGE"));
231 if (n >= 1 && level == GRIB_LOG_ERROR)
232 Assert(0);
233 if (n >= 2 && level == GRIB_LOG_WARNING)
234 Assert(0);
235 }
236 }
237
default_print(const grib_context * c,void * descriptor,const char * mess)238 static void default_print(const grib_context* c, void* descriptor, const char* mess)
239 {
240 fprintf((FILE*)descriptor, "%s", mess);
241 }
242
grib_context_set_print_proc(grib_context * c,grib_print_proc p)243 void grib_context_set_print_proc(grib_context* c, grib_print_proc p)
244 {
245 c = c ? c : grib_context_get_default();
246 c->print = p;
247 }
248
grib_context_set_debug(grib_context * c,int mode)249 void grib_context_set_debug(grib_context* c, int mode)
250 {
251 c = c ? c : grib_context_get_default();
252 c->debug = mode;
253 }
254
grib_context_set_logging_proc(grib_context * c,grib_log_proc p)255 void grib_context_set_logging_proc(grib_context* c, grib_log_proc p)
256 {
257 c = c ? c : grib_context_get_default();
258 c->output_log = p;
259 }
260
grib_get_api_version()261 long grib_get_api_version()
262 {
263 return ECCODES_VERSION;
264 }
265
grib_print_api_version(FILE * out)266 void grib_print_api_version(FILE* out)
267 {
268 fprintf(out, "%d.%d.%d",
269 ECCODES_MAJOR_VERSION,
270 ECCODES_MINOR_VERSION,
271 ECCODES_REVISION_VERSION);
272
273 if (ECCODES_MAJOR_VERSION < 1) {
274 fprintf(out, "%s", " PRE-RELEASE");
275 }
276 }
277
grib_get_package_name()278 const char* grib_get_package_name()
279 {
280 return "ecCodes";
281 }
282
283 #define DEFAULT_FILE_POOL_MAX_OPENED_FILES 0
284
285 static grib_context default_grib_context = {
286 0, /* inited */
287 0, /* debug */
288 0, /* write_on_fail */
289 0, /* no_abort */
290 0, /* io_buffer_size */
291 0, /* no_big_group_split */
292 0, /* no_spd */
293 0, /* keep_matrix */
294 0, /* grib_definition_files_path */
295 0, /* grib_samples_path */
296 0, /* grib_concept_path */
297 0, /* grib_reader */
298 0, /* user data */
299 GRIB_REAL_MODE8, /* real mode for fortran */
300
301 #if MANAGE_MEM
302 &grib_transient_free, /* free_mem */
303 &grib_transient_malloc, /* alloc_mem */
304 &grib_transient_realloc, /* realloc_mem */
305
306 &grib_permanent_free, /* free_persistant_mem */
307 &grib_permanent_malloc, /* alloc_persistant_mem */
308
309 &grib_buffer_free, /* buffer_free_mem */
310 &grib_buffer_malloc, /* buffer_alloc_mem */
311 &grib_buffer_realloc, /* buffer_realloc_mem */
312
313 #else
314
315 &default_free, /* free_mem */
316 &default_malloc, /* alloc_mem */
317 &default_realloc, /* realloc_mem */
318
319 &default_long_lasting_free, /* free_persistant_mem */
320 &default_long_lasting_malloc, /* alloc_persistant_mem */
321
322 &default_buffer_free, /* free_buffer_mem */
323 &default_buffer_malloc, /* alloc_buffer_mem */
324 &default_buffer_realloc, /* realloc_buffer_mem */
325 #endif
326
327 &default_read, /* file read procedure */
328 &default_write, /* file write procedure */
329 &default_tell, /* lfile tell procedure */
330 &default_seek, /* lfile seek procedure */
331 &default_feof, /* file feof procedure */
332
333 &default_log, /* output_log */
334 &default_print, /* print */
335 0, /* codetable */
336 0, /* smart_table */
337 0, /* outfilename */
338 0, /* multi_support_on */
339 0, /* multi_support */
340 0, /* grib_definition_files_dir */
341 0, /* handle_file_count */
342 0, /* handle_total_count */
343 0, /* message_file_offset */
344 0, /* no_fail_on_wrong_length */
345 0, /* gts_header_on */
346 0, /* gribex_mode_on */
347 0, /* large_constant_fields */
348 0, /* keys */
349 0, /* keys_count */
350 0, /* concepts_index */
351 0, /* concepts_count */
352 {0,}, /* concepts */
353 0, /* hash_array_index */
354 0, /* hash_array_count */
355 {0,}, /* hash_array */
356 0, /* def_files */
357 0, /* blocklist */
358 0, /* ieee_packing */
359 0, /* bufrdc_mode */
360 0, /* bufr_set_to_missing_if_out_of_range */
361 0, /* bufr_multi_element_constant_arrays */
362 0, /* grib_data_quality_checks */
363 0, /* log_stream */
364 0, /* classes */
365 0, /* lists */
366 0, /* expanded_descriptors */
367 DEFAULT_FILE_POOL_MAX_OPENED_FILES /* file_pool_max_opened_files */
368 #if GRIB_PTHREADS
369 ,
370 PTHREAD_MUTEX_INITIALIZER /* mutex */
371 #endif
372 };
373
374 /* Hopefully big enough. Note: Definitions and samples path environment variables can contain SEVERAL colon-separated directories */
375 #define ECC_PATH_MAXLEN 8192
376
grib_context_get_default()377 grib_context* grib_context_get_default()
378 {
379 GRIB_MUTEX_INIT_ONCE(&once, &init);
380 GRIB_MUTEX_LOCK(&mutex_c);
381
382 if (!default_grib_context.inited) {
383 const char* write_on_fail = NULL;
384 const char* large_constant_fields = NULL;
385 const char* no_abort = NULL;
386 const char* debug = NULL;
387 const char* gribex = NULL;
388 const char* ieee_packing = NULL;
389 const char* io_buffer_size = NULL;
390 const char* log_stream = NULL;
391 const char* no_big_group_split = NULL;
392 const char* no_spd = NULL;
393 const char* keep_matrix = NULL;
394 const char* bufrdc_mode = NULL;
395 const char* bufr_set_to_missing_if_out_of_range = NULL;
396 const char* bufr_multi_element_constant_arrays = NULL;
397 const char* grib_data_quality_checks = NULL;
398 const char* file_pool_max_opened_files = NULL;
399
400 #ifdef ENABLE_FLOATING_POINT_EXCEPTIONS
401 feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT);
402 #endif
403
404 write_on_fail = codes_getenv("ECCODES_GRIB_WRITE_ON_FAIL");
405 bufrdc_mode = getenv("ECCODES_BUFRDC_MODE_ON");
406 bufr_set_to_missing_if_out_of_range = getenv("ECCODES_BUFR_SET_TO_MISSING_IF_OUT_OF_RANGE");
407 bufr_multi_element_constant_arrays = getenv("ECCODES_BUFR_MULTI_ELEMENT_CONSTANT_ARRAYS");
408 grib_data_quality_checks = getenv("ECCODES_GRIB_DATA_QUALITY_CHECKS");
409 large_constant_fields = codes_getenv("ECCODES_GRIB_LARGE_CONSTANT_FIELDS");
410 no_abort = codes_getenv("ECCODES_NO_ABORT");
411 debug = codes_getenv("ECCODES_DEBUG");
412 gribex = codes_getenv("ECCODES_GRIBEX_MODE_ON");
413 ieee_packing = codes_getenv("ECCODES_GRIB_IEEE_PACKING");
414 io_buffer_size = codes_getenv("ECCODES_IO_BUFFER_SIZE");
415 log_stream = codes_getenv("ECCODES_LOG_STREAM");
416 no_big_group_split = codes_getenv("ECCODES_GRIB_NO_BIG_GROUP_SPLIT");
417 no_spd = codes_getenv("ECCODES_GRIB_NO_SPD");
418 keep_matrix = codes_getenv("ECCODES_GRIB_KEEP_MATRIX");
419 file_pool_max_opened_files = getenv("ECCODES_FILE_POOL_MAX_OPENED_FILES");
420
421 /* On UNIX, when we read from a file we get exactly what is in the file on disk.
422 * But on Windows a file can be opened in binary or text mode. In binary mode the system behaves exactly as in UNIX.
423 */
424 #ifdef ECCODES_ON_WINDOWS
425 _set_fmode(_O_BINARY);
426 #endif
427
428 default_grib_context.inited = 1;
429 default_grib_context.io_buffer_size = io_buffer_size ? atoi(io_buffer_size) : 0;
430 default_grib_context.no_big_group_split = no_big_group_split ? atoi(no_big_group_split) : 0;
431 default_grib_context.no_spd = no_spd ? atoi(no_spd) : 0;
432 default_grib_context.keep_matrix = keep_matrix ? atoi(keep_matrix) : 1;
433 default_grib_context.write_on_fail = write_on_fail ? atoi(write_on_fail) : 0;
434 default_grib_context.no_abort = no_abort ? atoi(no_abort) : 0;
435 default_grib_context.debug = debug ? atoi(debug) : 0;
436 default_grib_context.gribex_mode_on = gribex ? atoi(gribex) : 0;
437 default_grib_context.large_constant_fields = large_constant_fields ? atoi(large_constant_fields) : 0;
438 default_grib_context.ieee_packing = ieee_packing ? atoi(ieee_packing) : 0;
439 default_grib_context.grib_samples_path = codes_getenv("ECCODES_SAMPLES_PATH");
440 default_grib_context.log_stream = stderr;
441 if (!log_stream) {
442 default_grib_context.log_stream = stderr;
443 }
444 else if (!strcmp(log_stream, "stderr")) {
445 default_grib_context.log_stream = stderr;
446 }
447 else if (!strcmp(log_stream, "stdout")) {
448 default_grib_context.log_stream = stdout;
449 }
450
451 #ifdef ECCODES_SAMPLES_PATH
452 if (!default_grib_context.grib_samples_path)
453 default_grib_context.grib_samples_path = ECCODES_SAMPLES_PATH;
454 #endif
455
456 default_grib_context.grib_definition_files_path = codes_getenv("ECCODES_DEFINITION_PATH");
457 #ifdef ECCODES_DEFINITION_PATH
458 if (!default_grib_context.grib_definition_files_path) {
459 default_grib_context.grib_definition_files_path = strdup(ECCODES_DEFINITION_PATH);
460 }
461 else {
462 default_grib_context.grib_definition_files_path = strdup(default_grib_context.grib_definition_files_path);
463 }
464 #endif
465
466 /* GRIB-779: Special case for ECMWF testing. Not for external use! */
467 /* Append the new path to our existing path */
468 {
469 const char* test_defs = codes_getenv("_ECCODES_ECMWF_TEST_DEFINITION_PATH");
470 const char* test_samp = codes_getenv("_ECCODES_ECMWF_TEST_SAMPLES_PATH");
471 if (test_defs) {
472 char buffer[ECC_PATH_MAXLEN]= {0,};
473 if (default_grib_context.grib_definition_files_path) {
474 strcpy(buffer, default_grib_context.grib_definition_files_path);
475 strcat(buffer, ":");
476 }
477 strcat(buffer, test_defs);
478 free(default_grib_context.grib_definition_files_path);
479 default_grib_context.grib_definition_files_path = strdup(buffer);
480 }
481 if (test_samp) {
482 char buffer[ECC_PATH_MAXLEN]= {0,};
483 if (default_grib_context.grib_samples_path) {
484 strcpy(buffer, default_grib_context.grib_samples_path);
485 strcat(buffer, ":");
486 }
487 strcat(buffer, test_samp);
488 default_grib_context.grib_samples_path = strdup(buffer);
489 }
490 }
491
492 /* Definitions path extra: Added at the head of (i.e. before) existing path */
493 {
494 const char* defs_extra = getenv("ECCODES_EXTRA_DEFINITION_PATH");
495 if (defs_extra) {
496 char buffer[ECC_PATH_MAXLEN]= {0,};
497 ecc_snprintf(buffer, ECC_PATH_MAXLEN, "%s%c%s", defs_extra, ECC_PATH_DELIMITER_CHAR, default_grib_context.grib_definition_files_path);
498 free(default_grib_context.grib_definition_files_path);
499 default_grib_context.grib_definition_files_path = strdup(buffer);
500 }
501 }
502 #ifdef ECCODES_DEFINITION_PATH
503 {
504 /* ECC-1088 */
505 if (strstr(default_grib_context.grib_definition_files_path, ECCODES_DEFINITION_PATH) == NULL) {
506 char buffer[ECC_PATH_MAXLEN]= {0,};
507 ecc_snprintf(buffer, ECC_PATH_MAXLEN, "%s%c%s", default_grib_context.grib_definition_files_path,
508 ECC_PATH_DELIMITER_CHAR, ECCODES_DEFINITION_PATH);
509 free(default_grib_context.grib_definition_files_path);
510 default_grib_context.grib_definition_files_path = strdup(buffer);
511 }
512 }
513 #endif
514
515 /* Samples path extra: Added at the head of (i.e. before) existing path */
516 {
517 const char* samples_extra = getenv("ECCODES_EXTRA_SAMPLES_PATH");
518 if (samples_extra) {
519 char buffer[ECC_PATH_MAXLEN];
520 ecc_snprintf(buffer, ECC_PATH_MAXLEN, "%s%c%s", samples_extra, ECC_PATH_DELIMITER_CHAR, default_grib_context.grib_samples_path);
521 default_grib_context.grib_samples_path = strdup(buffer);
522 }
523 }
524 #ifdef ECCODES_SAMPLES_PATH
525 {
526 if (strstr(default_grib_context.grib_samples_path, ECCODES_SAMPLES_PATH) == NULL) {
527 char buffer[ECC_PATH_MAXLEN];
528 ecc_snprintf(buffer, ECC_PATH_MAXLEN, "%s%c%s", default_grib_context.grib_samples_path,
529 ECC_PATH_DELIMITER_CHAR, ECCODES_SAMPLES_PATH);
530 default_grib_context.grib_samples_path = strdup(buffer);
531 }
532 }
533 #endif
534
535 grib_context_log(&default_grib_context, GRIB_LOG_DEBUG, "Definitions path: %s",
536 default_grib_context.grib_definition_files_path);
537 grib_context_log(&default_grib_context, GRIB_LOG_DEBUG, "Samples path: %s",
538 default_grib_context.grib_samples_path);
539
540 default_grib_context.keys_count = 0;
541 default_grib_context.keys = grib_hash_keys_new(&(default_grib_context), &(default_grib_context.keys_count));
542
543 default_grib_context.concepts_index = grib_itrie_new(&(default_grib_context), &(default_grib_context.concepts_count));
544 default_grib_context.hash_array_index = grib_itrie_new(&(default_grib_context), &(default_grib_context.hash_array_count));
545 default_grib_context.def_files = grib_trie_new(&(default_grib_context));
546 default_grib_context.lists = grib_trie_new(&(default_grib_context));
547 default_grib_context.classes = grib_trie_new(&(default_grib_context));
548 default_grib_context.bufrdc_mode = bufrdc_mode ? atoi(bufrdc_mode) : 0;
549 default_grib_context.bufr_set_to_missing_if_out_of_range = bufr_set_to_missing_if_out_of_range ? atoi(bufr_set_to_missing_if_out_of_range) : 0;
550 default_grib_context.bufr_multi_element_constant_arrays = bufr_multi_element_constant_arrays ? atoi(bufr_multi_element_constant_arrays) : 0;
551 default_grib_context.grib_data_quality_checks = grib_data_quality_checks ? atoi(grib_data_quality_checks) : 0;
552 default_grib_context.file_pool_max_opened_files = file_pool_max_opened_files ? atoi(file_pool_max_opened_files) : DEFAULT_FILE_POOL_MAX_OPENED_FILES;
553 }
554
555 GRIB_MUTEX_UNLOCK(&mutex_c);
556 return &default_grib_context;
557 }
558
559 #if 0 /* function removed */
560 grib_context* grib_context_new(grib_context* parent)
561 {
562 grib_context* c;
563 #if GRIB_PTHREADS
564 pthread_mutexattr_t attr;
565 #endif
566
567 if (!parent) parent=grib_context_get_default();
568
569 GRIB_MUTEX_INIT_ONCE(&once,&init);
570 GRIB_MUTEX_LOCK(&(parent->mutex));
571
572 c = (grib_context*)grib_context_malloc_clear_persistent(&default_grib_context,sizeof(grib_context));
573
574 c->inited = default_grib_context.inited;
575 c->debug = default_grib_context.debug;
576
577 c->real_mode = default_grib_context.real_mode;
578
579 c->free_mem = default_grib_context.free_mem;
580 c->alloc_mem = default_grib_context.alloc_mem;
581
582 c->free_persistent_mem = default_grib_context.free_persistent_mem;
583 c->alloc_persistent_mem= default_grib_context.alloc_persistent_mem;
584
585 c->read = default_grib_context.read;
586 c->write = default_grib_context.write;
587 c->tell = default_grib_context.tell;
588
589 c->output_log = default_grib_context.output_log;
590 c->print = default_grib_context.print ;
591 c->user_data = default_grib_context.user_data;
592 c->def_files = default_grib_context.def_files;
593 c->lists = default_grib_context.lists;
594
595 #if GRIB_PTHREADS
596 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
597 pthread_mutex_init(&mutex_c,&attr);
598 pthread_mutexattr_destroy(&attr);
599 #endif
600
601 GRIB_MUTEX_UNLOCK(&(parent->mutex));
602 return c;
603 }
604 #endif /* function removed */
605
606 /* GRIB-235: Resolve path to expand symbolic links etc */
607 /* Note: return value is allocated. Client has to free */
codes_resolve_path(grib_context * c,const char * path)608 char* codes_resolve_path(grib_context* c, const char* path)
609 {
610 char* result = NULL;
611 #if defined(ECCODES_HAVE_REALPATH)
612 char resolved[ECC_PATH_MAXLEN + 1];
613 if (!realpath(path, resolved)) {
614 result = grib_context_strdup(c, path); /* Failed to resolve. Use original path */
615 }
616 else {
617 result = grib_context_strdup(c, resolved);
618 }
619 #else
620 result = grib_context_strdup(c, path);
621 #endif
622
623 return result;
624 }
625
init_definition_files_dir(grib_context * c)626 static int init_definition_files_dir(grib_context* c)
627 {
628 int err = 0;
629 char path[ECC_PATH_MAXLEN];
630 char* p = NULL;
631 grib_string_list* next = NULL;
632
633 if (!c)
634 c = grib_context_get_default();
635
636 if (c->grib_definition_files_dir)
637 return 0;
638 if (!c->grib_definition_files_path)
639 return GRIB_NO_DEFINITIONS;
640
641 /* Note: strtok modifies its first argument so we copy */
642 strncpy(path, c->grib_definition_files_path, ECC_PATH_MAXLEN-1);
643
644 GRIB_MUTEX_INIT_ONCE(&once, &init);
645 GRIB_MUTEX_LOCK(&mutex_c);
646
647 p = path;
648
649 while (*p != ECC_PATH_DELIMITER_CHAR && *p != '\0')
650 p++;
651
652 if (*p != ECC_PATH_DELIMITER_CHAR) {
653 /* No delimiter found so this is a single directory */
654 c->grib_definition_files_dir = (grib_string_list*)grib_context_malloc_clear_persistent(c, sizeof(grib_string_list));
655 c->grib_definition_files_dir->value = codes_resolve_path(c, path);
656 }
657 else {
658 /* Definitions path contains multiple directories */
659 char* dir = NULL;
660 dir = strtok(path, ECC_PATH_DELIMITER_STR);
661
662 while (dir != NULL) {
663 if (next) {
664 next->next = (grib_string_list*)grib_context_malloc_clear_persistent(c, sizeof(grib_string_list));
665 next = next->next;
666 }
667 else {
668 c->grib_definition_files_dir = (grib_string_list*)grib_context_malloc_clear_persistent(c, sizeof(grib_string_list));
669 next = c->grib_definition_files_dir;
670 }
671 next->value = codes_resolve_path(c, dir);
672 dir = strtok(NULL, ECC_PATH_DELIMITER_STR);
673 }
674 }
675
676 GRIB_MUTEX_UNLOCK(&mutex_c);
677
678 return err;
679 }
680
grib_context_full_defs_path(grib_context * c,const char * basename)681 char* grib_context_full_defs_path(grib_context* c, const char* basename)
682 {
683 int err = 0;
684 char full[1024] = {0,};
685 grib_string_list* dir = NULL;
686 grib_string_list* fullpath = 0;
687 if (!c)
688 c = grib_context_get_default();
689
690 GRIB_MUTEX_INIT_ONCE(&once, &init);
691
692 if (*basename == '/' || *basename == '.') {
693 return (char*)basename;
694 }
695 else {
696 GRIB_MUTEX_LOCK(&mutex_c); /* See ECC-604 */
697 fullpath = (grib_string_list*)grib_trie_get(c->def_files, basename);
698 GRIB_MUTEX_UNLOCK(&mutex_c);
699 if (fullpath != NULL) {
700 return fullpath->value;
701 }
702 if (!c->grib_definition_files_dir) {
703 err = init_definition_files_dir(c);
704 }
705
706 if (err != GRIB_SUCCESS) {
707 grib_context_log(c, GRIB_LOG_ERROR,
708 "Unable to find definition files directory");
709 return NULL;
710 }
711
712 dir = c->grib_definition_files_dir;
713
714 while (dir) {
715 sprintf(full, "%s/%s", dir->value, basename);
716 if (!codes_access(full, F_OK)) {
717 fullpath = (grib_string_list*)grib_context_malloc_clear_persistent(c, sizeof(grib_string_list));
718 Assert(fullpath);
719 fullpath->value = grib_context_strdup(c, full);
720 GRIB_MUTEX_LOCK(&mutex_c);
721 grib_trie_insert(c->def_files, basename, fullpath);
722 grib_context_log(c, GRIB_LOG_DEBUG, "Found def file %s", full);
723 GRIB_MUTEX_UNLOCK(&mutex_c);
724 return fullpath->value;
725 }
726 dir = dir->next;
727 }
728 }
729
730 GRIB_MUTEX_LOCK(&mutex_c);
731 /* Store missing files so we don't check for them again and again */
732 grib_trie_insert(c->def_files, basename, &grib_file_not_found);
733 /*grib_context_log(c,GRIB_LOG_ERROR,"Def file \"%s\" not found",basename);*/
734 GRIB_MUTEX_UNLOCK(&mutex_c);
735 full[0] = 0;
736 return NULL;
737 }
738
grib_samples_path(const grib_context * c)739 char* grib_samples_path(const grib_context* c)
740 {
741 if (!c)
742 c = grib_context_get_default();
743 return c->grib_samples_path;
744 }
grib_definition_path(const grib_context * c)745 char* grib_definition_path(const grib_context* c)
746 {
747 if (!c)
748 c = grib_context_get_default();
749 return c->grib_definition_files_path;
750 }
751
grib_context_free(const grib_context * c,void * p)752 void grib_context_free(const grib_context* c, void* p)
753 {
754 if (!c)
755 c = grib_context_get_default();
756 if (p)
757 c->free_mem(c, p);
758 }
759
grib_context_free_persistent(const grib_context * c,void * p)760 void grib_context_free_persistent(const grib_context* c, void* p)
761 {
762 if (!c)
763 c = grib_context_get_default();
764 if (p)
765 c->free_persistent_mem(c, p);
766 }
767
grib_context_reset(grib_context * c)768 void grib_context_reset(grib_context* c)
769 {
770 size_t i = 0;
771 if (!c)
772 c = grib_context_get_default();
773
774 if (c->grib_reader) {
775 grib_action_file* fr = c->grib_reader->first;
776 grib_action_file* fn = fr;
777 grib_action* a;
778
779 while (fn) {
780 fr = fn;
781 fn = fn->next;
782
783 a = fr->root;
784 while (a) {
785 grib_action* na = a->next;
786 grib_action_delete(c, a);
787 a = na;
788 }
789 grib_context_free_persistent(c, fr->filename);
790 grib_context_free_persistent(c, fr);
791 }
792 grib_context_free_persistent(c, c->grib_reader);
793 }
794
795 c->grib_reader = NULL;
796
797 if (c->codetable)
798 grib_codetable_delete(c);
799 c->codetable = NULL;
800
801 if (c->smart_table)
802 grib_smart_table_delete(c);
803 c->smart_table = NULL;
804
805 if (c->grib_definition_files_dir) {
806 grib_string_list* next = c->grib_definition_files_dir;
807 grib_string_list* cur = NULL;
808 while (next) {
809 cur = next;
810 next = next->next;
811 grib_context_free(c, cur->value);
812 grib_context_free(c, cur);
813 }
814 }
815
816 if (c->multi_support_on)
817 grib_multi_support_reset(c);
818
819 for (i=0; i < MAX_NUM_CONCEPTS; ++i) {
820 grib_concept_value* cv = c->concepts[i];
821 if (cv) {
822 grib_trie_delete_container(cv->index);
823 }
824 while (cv) {
825 grib_concept_value* n = cv->next;
826 grib_concept_value_delete(c, cv);
827 cv = n;
828 }
829 }
830 }
831
grib_context_delete(grib_context * c)832 void grib_context_delete(grib_context* c)
833 {
834 if (!c)
835 c = grib_context_get_default();
836
837 grib_hash_keys_delete(c->keys);
838 /*grib_trie_delete(c->def_files); TODO:masn */
839
840 grib_context_reset(c);
841 if (c != &default_grib_context)
842 grib_context_free_persistent(&default_grib_context, c);
843 }
844
codes_bufr_multi_element_constant_arrays_on(grib_context * c)845 void codes_bufr_multi_element_constant_arrays_on(grib_context* c)
846 {
847 if (!c)
848 c = grib_context_get_default();
849 c->bufr_multi_element_constant_arrays = 1;
850 }
codes_bufr_multi_element_constant_arrays_off(grib_context * c)851 void codes_bufr_multi_element_constant_arrays_off(grib_context* c)
852 {
853 if (!c)
854 c = grib_context_get_default();
855 c->bufr_multi_element_constant_arrays = 0;
856 }
857 /*int codes_get_bufr_multi_element_constant_arrays(grib_context* c);*/
858
859
grib_context_set_definitions_path(grib_context * c,const char * path)860 void grib_context_set_definitions_path(grib_context* c, const char* path)
861 {
862 if (!c)
863 c = grib_context_get_default();
864 GRIB_MUTEX_INIT_ONCE(&once, &init);
865 GRIB_MUTEX_LOCK(&mutex_c);
866
867 c->grib_definition_files_path = strdup(path);
868 grib_context_log(c, GRIB_LOG_DEBUG, "Definitions path changed to: %s", c->grib_definition_files_path);
869
870 GRIB_MUTEX_UNLOCK(&mutex_c);
871 }
grib_context_set_samples_path(grib_context * c,const char * path)872 void grib_context_set_samples_path(grib_context* c, const char* path)
873 {
874 if (!c)
875 c = grib_context_get_default();
876 GRIB_MUTEX_INIT_ONCE(&once, &init);
877 GRIB_MUTEX_LOCK(&mutex_c);
878
879 c->grib_samples_path = strdup(path);
880 grib_context_log(c, GRIB_LOG_DEBUG, "Samples path changed to: %s", c->grib_samples_path);
881
882 GRIB_MUTEX_UNLOCK(&mutex_c);
883 }
884
grib_context_malloc_persistent(const grib_context * c,size_t size)885 void* grib_context_malloc_persistent(const grib_context* c, size_t size)
886 {
887 void* p = c->alloc_persistent_mem(c, size);
888 if (!p) {
889 grib_context_log(c, GRIB_LOG_FATAL,
890 "grib_context_malloc_persistent: error allocating %lu bytes", (unsigned long)size);
891 Assert(0);
892 }
893 return p;
894 }
895
grib_context_strdup_persistent(const grib_context * c,const char * s)896 char* grib_context_strdup_persistent(const grib_context* c, const char* s)
897 {
898 char* dup = (char*)grib_context_malloc_persistent(c, (strlen(s) * sizeof(char)) + 1);
899 if (dup)
900 strcpy(dup, s);
901 return dup;
902 }
903
grib_context_malloc_clear_persistent(const grib_context * c,size_t size)904 void* grib_context_malloc_clear_persistent(const grib_context* c, size_t size)
905 {
906 void* p = grib_context_malloc_persistent(c, size);
907 if (p)
908 memset(p, 0, size);
909 return p;
910 }
911
grib_context_malloc(const grib_context * c,size_t size)912 void* grib_context_malloc(const grib_context* c, size_t size)
913 {
914 void* p = NULL;
915 if (!c)
916 c = grib_context_get_default();
917 if (size == 0)
918 return p;
919 else
920 p = c->alloc_mem(c, size);
921 if (!p) {
922 grib_context_log(c, GRIB_LOG_FATAL, "grib_context_malloc: error allocating %lu bytes", (unsigned long)size);
923 Assert(0);
924 }
925 return p;
926 }
927
grib_context_realloc(const grib_context * c,void * p,size_t size)928 void* grib_context_realloc(const grib_context* c, void* p, size_t size)
929 {
930 void* q;
931 if (!c)
932 c = grib_context_get_default();
933 q = c->realloc_mem(c, p, size);
934 if (!q) {
935 grib_context_log(c, GRIB_LOG_FATAL, "grib_context_realloc: error allocating %lu bytes", (unsigned long)size);
936 return NULL;
937 }
938 return q;
939 }
940
grib_context_strdup(const grib_context * c,const char * s)941 char* grib_context_strdup(const grib_context* c, const char* s)
942 {
943 char* dup = 0;
944 if (s) {
945 dup = (char*)grib_context_malloc(c, (strlen(s) * sizeof(char)) + 1);
946 if (dup)
947 strcpy(dup, s);
948 }
949 return dup;
950 }
951
grib_context_malloc_clear(const grib_context * c,size_t size)952 void* grib_context_malloc_clear(const grib_context* c, size_t size)
953 {
954 void* p = grib_context_malloc(c, size);
955 if (p)
956 memset(p, 0, size);
957 return p;
958 }
959
grib_context_buffer_malloc(const grib_context * c,size_t size)960 void* grib_context_buffer_malloc(const grib_context* c, size_t size)
961 {
962 void* p = NULL;
963 if (!c)
964 c = grib_context_get_default();
965 if (size == 0)
966 return p;
967 else
968 p = c->alloc_buffer_mem(c, size);
969 if (!p) {
970 grib_context_log(c, GRIB_LOG_FATAL, "grib_context_buffer_malloc: error allocating %lu bytes", (unsigned long)size);
971 return NULL;
972 }
973 return p;
974 }
975
grib_context_buffer_free(const grib_context * c,void * p)976 void grib_context_buffer_free(const grib_context* c, void* p)
977 {
978 if (!c)
979 c = grib_context_get_default();
980 if (p)
981 c->free_buffer_mem(c, p);
982 }
983
grib_context_buffer_realloc(const grib_context * c,void * p,size_t size)984 void* grib_context_buffer_realloc(const grib_context* c, void* p, size_t size)
985 {
986 void* q = c->realloc_buffer_mem(c, p, size);
987 if (!q) {
988 grib_context_log(c, GRIB_LOG_FATAL, "grib_context_buffer_realloc: error allocating %lu bytes", (unsigned long)size);
989 return NULL;
990 }
991 return q;
992 }
993
grib_context_buffer_malloc_clear(const grib_context * c,size_t size)994 void* grib_context_buffer_malloc_clear(const grib_context* c, size_t size)
995 {
996 void* p = grib_context_buffer_malloc(c, size);
997 if (p)
998 memset(p, 0, size);
999 return p;
1000 }
1001
grib_context_set_memory_proc(grib_context * c,grib_malloc_proc m,grib_free_proc f,grib_realloc_proc r)1002 void grib_context_set_memory_proc(grib_context* c, grib_malloc_proc m, grib_free_proc f, grib_realloc_proc r)
1003 {
1004 c->free_mem = f;
1005 c->alloc_mem = m;
1006 c->realloc_mem = r;
1007 }
1008
grib_context_set_persistent_memory_proc(grib_context * c,grib_malloc_proc m,grib_free_proc f)1009 void grib_context_set_persistent_memory_proc(grib_context* c, grib_malloc_proc m, grib_free_proc f)
1010 {
1011 c->free_persistent_mem = f;
1012 c->alloc_persistent_mem = m;
1013 }
1014
grib_context_set_buffer_memory_proc(grib_context * c,grib_malloc_proc m,grib_free_proc f,grib_realloc_proc r)1015 void grib_context_set_buffer_memory_proc(grib_context* c, grib_malloc_proc m, grib_free_proc f, grib_realloc_proc r)
1016 {
1017 c->free_buffer_mem = f;
1018 c->alloc_buffer_mem = m;
1019 c->realloc_buffer_mem = r;
1020 }
1021
grib_context_set_data_accessing_proc(grib_context * c,grib_data_read_proc read,grib_data_write_proc write,grib_data_tell_proc tell)1022 void grib_context_set_data_accessing_proc(grib_context* c, grib_data_read_proc read, grib_data_write_proc write, grib_data_tell_proc tell)
1023 {
1024 c->read = read;
1025 c->write = write;
1026 c->tell = tell;
1027 }
1028
1029 /* Logging procedure */
grib_context_log(const grib_context * c,int level,const char * fmt,...)1030 void grib_context_log(const grib_context* c, int level, const char* fmt, ...)
1031 {
1032 /* Save some CPU */
1033 if ((level == GRIB_LOG_DEBUG && c->debug < 1) ||
1034 (level == GRIB_LOG_WARNING && c->debug < 2)) {
1035 return;
1036 }
1037 else {
1038 char msg[1024];
1039 va_list list;
1040 const int errsv = errno;
1041
1042 va_start(list, fmt);
1043 vsprintf(msg, fmt, list);
1044 va_end(list);
1045
1046 if (level & GRIB_LOG_PERROR) {
1047 level = level & ~GRIB_LOG_PERROR;
1048
1049 /* #if HAS_STRERROR */
1050 #if 1
1051 strcat(msg, " (");
1052 strcat(msg, strerror(errsv));
1053 strcat(msg, ")");
1054 #else
1055 if (errsv > 0 && errsv < sys_nerr) {
1056 strcat(msg, " (");
1057 strcat(msg, sys_errlist[errsv]);
1058 strcat(msg, " )");
1059 }
1060 #endif
1061 }
1062
1063 if (c->output_log)
1064 c->output_log(c, level, msg);
1065 }
1066 }
1067
1068 /* Logging procedure */
grib_context_print(const grib_context * c,void * descriptor,const char * fmt,...)1069 void grib_context_print(const grib_context* c, void* descriptor, const char* fmt, ...)
1070 {
1071 char msg[1024];
1072 va_list list;
1073 va_start(list, fmt);
1074 vsprintf(msg, fmt, list);
1075 va_end(list);
1076 c->print(c, descriptor, msg);
1077 }
1078
grib_context_get_handle_file_count(grib_context * c)1079 int grib_context_get_handle_file_count(grib_context* c)
1080 {
1081 int r = 0;
1082 if (!c)
1083 c = grib_context_get_default();
1084 GRIB_MUTEX_INIT_ONCE(&once, &init);
1085 GRIB_MUTEX_LOCK(&mutex_c);
1086 r = c->handle_file_count;
1087 GRIB_MUTEX_UNLOCK(&mutex_c);
1088 return r;
1089 }
grib_context_get_handle_total_count(grib_context * c)1090 int grib_context_get_handle_total_count(grib_context* c)
1091 {
1092 int r = 0;
1093 if (!c)
1094 c = grib_context_get_default();
1095 GRIB_MUTEX_INIT_ONCE(&once, &init);
1096 GRIB_MUTEX_LOCK(&mutex_c);
1097 r = c->handle_total_count;
1098 GRIB_MUTEX_UNLOCK(&mutex_c);
1099 return r;
1100 }
1101
grib_context_set_handle_file_count(grib_context * c,int new_count)1102 void grib_context_set_handle_file_count(grib_context* c, int new_count)
1103 {
1104 if (!c)
1105 c = grib_context_get_default();
1106 GRIB_MUTEX_INIT_ONCE(&once, &init);
1107 GRIB_MUTEX_LOCK(&mutex_c);
1108 c->handle_file_count = new_count;
1109 GRIB_MUTEX_UNLOCK(&mutex_c);
1110 }
grib_context_set_handle_total_count(grib_context * c,int new_count)1111 void grib_context_set_handle_total_count(grib_context* c, int new_count)
1112 {
1113 if (!c)
1114 c = grib_context_get_default();
1115 GRIB_MUTEX_INIT_ONCE(&once, &init);
1116 GRIB_MUTEX_LOCK(&mutex_c);
1117 c->handle_total_count = new_count;
1118 GRIB_MUTEX_UNLOCK(&mutex_c);
1119 }
1120
grib_context_increment_handle_file_count(grib_context * c)1121 void grib_context_increment_handle_file_count(grib_context* c)
1122 {
1123 if (!c)
1124 c = grib_context_get_default();
1125 GRIB_MUTEX_INIT_ONCE(&once, &init);
1126 GRIB_MUTEX_LOCK(&mutex_c);
1127 c->handle_file_count++;
1128 GRIB_MUTEX_UNLOCK(&mutex_c);
1129 }
grib_context_increment_handle_total_count(grib_context * c)1130 void grib_context_increment_handle_total_count(grib_context* c)
1131 {
1132 if (!c)
1133 c = grib_context_get_default();
1134 GRIB_MUTEX_INIT_ONCE(&once, &init);
1135 GRIB_MUTEX_LOCK(&mutex_c);
1136 c->handle_total_count++;
1137 GRIB_MUTEX_UNLOCK(&mutex_c);
1138 }
1139
grib_context_expanded_descriptors_list_get(grib_context * c,const char * key,long * u,size_t size)1140 bufr_descriptors_array* grib_context_expanded_descriptors_list_get(grib_context* c, const char* key, long* u, size_t size)
1141 {
1142 bufr_descriptors_map_list* expandedUnexpandedMapList;
1143 size_t i = 0;
1144 int found = 0;
1145 bufr_descriptors_array* result = NULL;
1146 if (!c)
1147 c = grib_context_get_default();
1148
1149 GRIB_MUTEX_INIT_ONCE(&once, &init);
1150 GRIB_MUTEX_LOCK(&mutex_c);
1151
1152 if (!c->expanded_descriptors) {
1153 c->expanded_descriptors = (grib_trie*)grib_trie_new(c);
1154 result = NULL;
1155 goto the_end;
1156 }
1157 expandedUnexpandedMapList = (bufr_descriptors_map_list*)grib_trie_get(c->expanded_descriptors, key);
1158 found = 0;
1159 while (expandedUnexpandedMapList) {
1160 if (expandedUnexpandedMapList->unexpanded->n == size) {
1161 found = 1;
1162 for (i = 0; i < size; i++) {
1163 if (expandedUnexpandedMapList->unexpanded->v[i]->code != u[i]) {
1164 found = 0;
1165 break;
1166 }
1167 }
1168 }
1169 if (found) {
1170 result = expandedUnexpandedMapList->expanded;
1171 goto the_end;
1172 }
1173 expandedUnexpandedMapList = expandedUnexpandedMapList->next;
1174 }
1175 the_end:
1176 GRIB_MUTEX_UNLOCK(&mutex_c);
1177 return result;
1178 }
1179
grib_context_expanded_descriptors_list_push(grib_context * c,const char * key,bufr_descriptors_array * expanded,bufr_descriptors_array * unexpanded)1180 void grib_context_expanded_descriptors_list_push(grib_context* c,
1181 const char* key, bufr_descriptors_array* expanded, bufr_descriptors_array* unexpanded)
1182 {
1183 bufr_descriptors_map_list* descriptorsList = NULL;
1184 bufr_descriptors_map_list* next = NULL;
1185 bufr_descriptors_map_list* newdescriptorsList = NULL;
1186 if (!c)
1187 c = grib_context_get_default();
1188
1189 GRIB_MUTEX_INIT_ONCE(&once, &init);
1190 GRIB_MUTEX_LOCK(&mutex_c);
1191
1192 newdescriptorsList = (bufr_descriptors_map_list*)grib_context_malloc_clear(c, sizeof(bufr_descriptors_map_list));
1193 newdescriptorsList->expanded = expanded;
1194 newdescriptorsList->unexpanded = unexpanded;
1195
1196 descriptorsList = (bufr_descriptors_map_list*)grib_trie_get(c->expanded_descriptors, key);
1197 if (descriptorsList) {
1198 next = descriptorsList;
1199 while (next->next) {
1200 next = next->next;
1201 }
1202 next->next = newdescriptorsList;
1203 }
1204 else {
1205 grib_trie_insert(c->expanded_descriptors, key, newdescriptorsList);
1206 }
1207 GRIB_MUTEX_UNLOCK(&mutex_c);
1208 }
1209
1210 static codes_assertion_failed_proc assertion = NULL;
1211
codes_set_codes_assertion_failed_proc(codes_assertion_failed_proc proc)1212 void codes_set_codes_assertion_failed_proc(codes_assertion_failed_proc proc)
1213 {
1214 assertion = proc;
1215 }
1216
codes_assertion_failed(const char * message,const char * file,int line)1217 void codes_assertion_failed(const char* message, const char* file, int line)
1218 {
1219 /* Default behaviour is to abort
1220 * unless user has supplied his own assertion routine */
1221 if (assertion == NULL) {
1222 grib_context* c = grib_context_get_default();
1223 fprintf(stderr, "ecCodes assertion failed: `%s' in %s:%d\n", message, file, line);
1224 if (!c->no_abort) {
1225 abort();
1226 }
1227 }
1228 else {
1229 char buffer[10240];
1230 sprintf(buffer, "ecCodes assertion failed: `%s' in %s:%d", message, file, line);
1231 assertion(buffer);
1232 }
1233 }
1234
grib_get_gribex_mode(grib_context * c)1235 int grib_get_gribex_mode(grib_context* c)
1236 {
1237 if (!c)
1238 c = grib_context_get_default();
1239 return c->gribex_mode_on;
1240 }
grib_gribex_mode_on(grib_context * c)1241 void grib_gribex_mode_on(grib_context* c)
1242 {
1243 if (!c)
1244 c = grib_context_get_default();
1245 c->gribex_mode_on = 1;
1246 }
grib_gribex_mode_off(grib_context * c)1247 void grib_gribex_mode_off(grib_context* c)
1248 {
1249 if (!c)
1250 c = grib_context_get_default();
1251 c->gribex_mode_on = 0;
1252 }
1253
grib_gts_header_on(grib_context * c)1254 void grib_gts_header_on(grib_context* c)
1255 {
1256 if (!c)
1257 c = grib_context_get_default();
1258 c->gts_header_on = 1;
1259 }
grib_gts_header_off(grib_context * c)1260 void grib_gts_header_off(grib_context* c)
1261 {
1262 if (!c)
1263 c = grib_context_get_default();
1264 c->gts_header_on = 0;
1265 }
1266
grib_multi_support_on(grib_context * c)1267 void grib_multi_support_on(grib_context* c)
1268 {
1269 if (!c)
1270 c = grib_context_get_default();
1271 c->multi_support_on = 1;
1272 }
grib_multi_support_off(grib_context * c)1273 void grib_multi_support_off(grib_context* c)
1274 {
1275 if (!c)
1276 c = grib_context_get_default();
1277 c->multi_support_on = 0;
1278 }
1279