/*********************************************************************** * pc_mem.c * * Memory and message management routines. * Allow this library to be used both inside and outside a * PgSQL backend. * * PgSQL Pointcloud is free and open source software provided * by the Government of Canada * Copyright (c) 2013 Natural Resources Canada * ***********************************************************************/ #include #include "pc_api_internal.h" struct pc_context_t { pc_allocator alloc; pc_reallocator realloc; pc_deallocator free; pc_message_handler err; pc_message_handler warn; pc_message_handler info; }; static struct pc_context_t pc_context; /* * Default allocators * * We include some default allocators that use malloc/free/realloc * along with stdout/stderr since this is the most common use case * */ static void * default_allocator(size_t size) { return malloc(size); } static void default_freeor(void *mem) { free(mem); } static void * default_reallocator(void *mem, size_t size) { return realloc(mem, size); } static void default_msg_handler(const char *label, const char *fmt, va_list ap) { char newfmt[1024] = {0}; snprintf(newfmt, 1024, "%s%s\n", label, fmt); newfmt[1023] = '\0'; vprintf(newfmt, ap); } static void default_info_handler(const char *fmt, va_list ap) { default_msg_handler("INFO: ", fmt, ap); } static void default_warn_handler(const char *fmt, va_list ap) { default_msg_handler("WARNING: ", fmt, ap); } static void default_error_handler(const char *fmt, va_list ap) { default_msg_handler("ERROR: ", fmt, ap); va_end(ap); exit(1); } void pc_install_default_handlers(void) { pc_context.alloc = default_allocator; pc_context.realloc = default_reallocator; pc_context.free = default_freeor; pc_context.err = default_error_handler; pc_context.info = default_info_handler; pc_context.warn = default_warn_handler; #ifdef HAVE_LIBGHT ght_set_handlers( (void *)default_allocator, (void *)default_reallocator, (void *)default_freeor, (void *)default_error_handler, (void *)default_info_handler, (void *)default_warn_handler ); #endif } void pc_set_handlers( pc_allocator allocator, pc_reallocator reallocator, pc_deallocator deallocator, pc_message_handler error_handler, pc_message_handler info_handler, pc_message_handler warn_handler) { if ( ! allocator ) allocator = pc_context.alloc; if ( ! reallocator ) reallocator = pc_context.realloc; if ( ! deallocator ) deallocator = pc_context.free; if ( ! error_handler ) error_handler = pc_context.err; if ( ! warn_handler ) warn_handler = pc_context.warn; if ( ! info_handler ) info_handler = pc_context.info; pc_context.alloc = allocator; pc_context.realloc = reallocator; pc_context.free = deallocator; pc_context.err = error_handler; pc_context.warn = warn_handler; pc_context.info = info_handler; #ifdef HAVE_LIBGHT ght_set_handlers( (void *)allocator, (void *)reallocator, (void *)deallocator, (void *)error_handler, (void *)info_handler, (void *)warn_handler ); #endif return; } void * pcalloc(size_t size) { void *mem; if ( ! size ) return NULL; mem = pc_context.alloc(size); memset(mem, 0, size); /* Always clean memory */ return mem; } char * pcstrdup(const char *str) { size_t len = strlen(str); char *newstr = pcalloc(len + 1); memcpy(newstr, str, len + 1); return newstr; } void * pcrealloc(void * mem, size_t size) { return pc_context.realloc(mem, size); } void pcfree(void * mem) { pc_context.free(mem); } void pcerror(const char *fmt, ...) { va_list ap; va_start(ap, fmt); (*pc_context.err)(fmt, ap); va_end(ap); } void pcinfo(const char *fmt, ...) { va_list ap; va_start(ap, fmt); (*pc_context.info)(fmt, ap); va_end(ap); } void pcwarn(const char *fmt, ...) { va_list ap; va_start(ap, fmt); (*pc_context.warn)(fmt, ap); va_end(ap); }