/*
* Copyright (c) Likewise Software. All rights Reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the license, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Module Name:
*
* context.c
*
* Abstract:
*
* Marshalling context API
*
* Authors: Brian Koropoff (bkoropoff@likewisesoftware.com)
*
*/
#include "context-private.h"
#include "status-private.h"
#include "util-private.h"
#include "type-private.h"
#include
#include
static LWMsgStatus
lwmsg_context_default_alloc (
size_t size,
void** out,
void* data)
{
void* object = malloc(size == 0 ? 1 : size);
if (!object)
{
return LWMSG_STATUS_MEMORY;
}
else
{
memset(object, 0, size);
*out = object;
return LWMSG_STATUS_SUCCESS;
}
}
static
void
lwmsg_context_default_free (
void* object,
void* data
)
{
free(object);
}
static LWMsgStatus
lwmsg_context_default_realloc (
void* object,
size_t old_size,
size_t new_size,
void** new_object,
void* data)
{
void* nobj = realloc(object, new_size);
if (!nobj)
{
return LWMSG_STATUS_MEMORY;
}
else
{
if (new_size > old_size)
{
memset(nobj + old_size, 0, new_size - old_size);
}
*new_object = nobj;
return LWMSG_STATUS_SUCCESS;
}
}
void
lwmsg_context_setup(
LWMsgContext* context,
const LWMsgContext* parent
)
{
context->parent = parent;
}
LWMsgStatus
lwmsg_context_new(
const LWMsgContext* parent,
LWMsgContext** context
)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
LWMsgContext* my_context = NULL;
my_context = calloc(1, sizeof(*my_context));
if (my_context == NULL)
{
BAIL_ON_ERROR(status = LWMSG_STATUS_MEMORY);
}
lwmsg_context_setup(my_context, parent);
*context = my_context;
error:
return status;
}
void
lwmsg_context_cleanup(LWMsgContext* context)
{
lwmsg_error_clear(&context->error);
}
void
lwmsg_context_delete(LWMsgContext* context)
{
lwmsg_context_cleanup(context);
free(context);
}
void
lwmsg_context_set_memory_functions(
LWMsgContext* context,
LWMsgAllocFunction alloc,
LWMsgFreeFunction free,
LWMsgReallocFunction realloc,
void* data
)
{
context->alloc = alloc;
context->free = free;
context->realloc = realloc;
context->memdata = data;
}
const char*
lwmsg_context_get_error_message(
LWMsgContext* context,
LWMsgStatus status
)
{
return lwmsg_error_message(status, &context->error);
}
void
lwmsg_context_get_memory_functions(
const LWMsgContext* context,
LWMsgAllocFunction* alloc,
LWMsgFreeFunction* free,
LWMsgReallocFunction* realloc,
void** data
)
{
if (!context)
{
if (alloc)
{
*alloc = lwmsg_context_default_alloc;
}
if (free)
{
*free = lwmsg_context_default_free;
}
if (realloc)
{
*realloc = lwmsg_context_default_realloc;
}
if (data)
{
*data = NULL;
}
}
else if (context->alloc)
{
if (alloc)
{
*alloc = context->alloc;
}
if (free)
{
*free = context->free;
}
if (realloc)
{
*realloc = context->realloc;
}
if (data)
{
*data = context->memdata;
}
}
else
{
lwmsg_context_get_memory_functions(context->parent, alloc, free, realloc, data);
}
}
void
lwmsg_context_set_data_function(
LWMsgContext* context,
LWMsgContextDataFunction fn,
void* data
)
{
context->datafn = fn;
context->datafndata = data;
}
void
lwmsg_context_set_log_function(
LWMsgContext* context,
LWMsgLogFunction logfn,
void* data
)
{
context->logfn = logfn;
context->logfndata = data;
}
static
void
lwmsg_context_get_log_function(
const LWMsgContext* context,
LWMsgLogFunction* logfn,
void** logfndata
)
{
if (!context)
{
*logfn = NULL;
*logfndata = NULL;
}
else if (context->logfn)
{
*logfn = context->logfn;
*logfndata = context->logfndata;
}
else
{
lwmsg_context_get_log_function(context->parent, logfn, logfndata);
}
}
LWMsgStatus
lwmsg_context_get_data(
const LWMsgContext* context,
const char* key,
void** out_data
)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
for (; context; context = context->parent)
{
if (context->datafn)
{
status = context->datafn(key, out_data, context->datafndata);
if (status == LWMSG_STATUS_NOT_FOUND)
{
status = LWMSG_STATUS_SUCCESS;
continue;
}
BAIL_ON_ERROR(status);
break;
}
}
error:
return status;
}
void
lwmsg_context_log(
const LWMsgContext* context,
LWMsgLogLevel level,
const char* message,
const char* filename,
unsigned int line
)
{
LWMsgLogFunction logfn = NULL;
void* logfndata = NULL;
lwmsg_context_get_log_function(context, &logfn, &logfndata);
if (logfn)
{
logfn(level, message, filename, line, logfndata);
}
}
void
lwmsg_context_log_printf(
const LWMsgContext* context,
LWMsgLogLevel level,
const char* filename,
unsigned int line,
const char* format,
...
)
{
LWMsgLogFunction logfn = NULL;
void* logfndata = NULL;
char* message = NULL;
va_list ap;
lwmsg_context_get_log_function(context, &logfn, &logfndata);
if (logfn)
{
va_start(ap, format);
message = lwmsg_formatv(format, ap);
va_end(ap);
if (message)
{
logfn(level, message, filename, line, logfndata);
free(message);
}
}
}
LWMsgStatus
lwmsg_context_alloc(
const LWMsgContext* context,
size_t size,
void** object
)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
LWMsgAllocFunction fn_alloc = NULL;
LWMsgReallocFunction fn_realloc = NULL;
void* data = NULL;
lwmsg_context_get_memory_functions(context, &fn_alloc, NULL, &fn_realloc, &data);
if (fn_alloc)
{
BAIL_ON_ERROR(status = fn_alloc(size, object, data));
}
else if (fn_realloc)
{
BAIL_ON_ERROR(status = fn_realloc(NULL, 0, size, object, data));
}
else
{
BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED);
}
cleanup:
return status;
error:
*object = NULL;
goto cleanup;
}
void
lwmsg_context_free(
const LWMsgContext* context,
void* object
)
{
LWMsgFreeFunction fn_free = NULL;
void* data = NULL;
lwmsg_context_get_memory_functions(context, NULL, &fn_free, NULL, &data);
fn_free(object, data);
}
LWMsgStatus
lwmsg_context_realloc(
const LWMsgContext* context,
void* old_object,
size_t old_size,
size_t new_size,
void** new_object
)
{
LWMsgStatus status = LWMSG_STATUS_SUCCESS;
LWMsgAllocFunction fn_alloc = NULL;
LWMsgFreeFunction fn_free = NULL;
LWMsgReallocFunction fn_realloc = NULL;
void* data = NULL;
lwmsg_context_get_memory_functions(context, &fn_alloc, &fn_free, &fn_realloc, &data);
if (fn_realloc)
{
BAIL_ON_ERROR(status = fn_realloc(old_object, old_size, new_size, new_object, data));
}
else if (fn_alloc && fn_free)
{
BAIL_ON_ERROR(status = fn_alloc(new_size, new_object, data));
memcpy(*new_object, old_object, new_size < old_size ? new_size : old_size);
fn_free(old_object, data);
}
else
{
BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED);
}
cleanup:
return status;
error:
*new_object = NULL;
goto cleanup;
}
LWMsgBool
lwmsg_context_would_log(
const LWMsgContext* context,
LWMsgLogLevel level
)
{
LWMsgLogFunction logfn = NULL;
void* logfndata = NULL;
lwmsg_context_get_log_function(context, &logfn, &logfndata);
if (logfn)
{
return logfn(level, NULL, NULL, 0, logfndata);
}
else
{
return LWMSG_FALSE;
}
}