php-src/ext/satellite/struct.c
2001-02-26 06:11:02 +00:00

331 lines
8.1 KiB
C

/*
+----------------------------------------------------------------------+
| PHP version 4.0 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2001 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: David Eriksson <david@2good.com> |
+----------------------------------------------------------------------+
*/
/*
* $Id$
* vim: syntax=c tabstop=2 shiftwidth=2
*/
/* -----------------------------------------------------------------------
*
* OrbitStruct class
*
* There are three ways to create a structure
*
* (1) OrbitStruct_Constructor, for new OrbitStruct(...) in PHP
* (2) OrbitStruct_Create, used when a CORBA method returns a struct
* (3) OrbitStruct_Wakeup, used on "unserialization"
* -----------------------------------------------------------------------
*/
#include "struct.h"
#include "common.h"
#include "typemanager.h"
#include "hashtable.h"
/*
* enable/disable incomplete serialization support
*/
#define SERIALIZABLE_STRUCT 0
struct _OrbitStruct
{
HashTable mMembers;
zend_bool mIsException; /* otherwise normal struct */
union
{
StructType * mpStructType;
ExceptionType * mpExceptionType;
} u;
};
#if SERIALIZABLE_STRUCT
static void OrbitStruct_Wakeup(INTERNAL_FUNCTION_PARAMETERS);
static void OrbitStruct_Sleep(INTERNAL_FUNCTION_PARAMETERS);
static zend_function_entry OrbitStruct_class_functions[] =
{
{"__sleep", OrbitStruct_Sleep},
{"__wakeup", OrbitStruct_Wakeup},
{NULL, NULL}
};
#define MY_IMPLEMENT_CLASS(name, flags)\
IMPLEMENT_DECLARATIONS(name, flags) \
IMPLEMENT_FUNCTION_CALL(name, flags) \
IMPLEMENT_PUT_PROPERTY(name, flags) \
IMPLEMENT_GET_PROPERTY(name, flags) \
IMPLEMENT_INIT_EX(name, flags, ##name##_class_functions, _##name##_FunctionCall, _##name##_GetProperty, _##name##_PutProperty)\
IMPLEMENT_DATA_HELPERS(name, flags)
MY_IMPLEMENT_CLASS(OrbitStruct, NO_FUNCTIONS);
#else /* !SERIALIZABLE_STRUCT */
IMPLEMENT_CLASS(OrbitStruct, NO_FUNCTIONS);
#endif /* SERIALIZABLE_STRUCT */
#if SERIALIZABLE_STRUCT
/*
* prepare for serialization
*/
static void OrbitStruct_Sleep(INTERNAL_FUNCTION_PARAMETERS)
{
/* get struct data */
OrbitStruct * p_struct = OrbitStruct_RetrieveData(this_ptr);
/* validate data */
if (p_struct == NULL)
{
goto error;
}
#if 0
/* add property to zval */
add_property_string(this_ptr, IOR_PROPERTY_KEY, p_ior, TRUE);
/* create array */
array_init(return_value);
/* add name of property IOR to array */
add_next_index_string(return_value, IOR_PROPERTY_KEY, TRUE);
#endif
return;
error:
RETURN_NULL();
}
static void OrbitStruct_Wakeup(INTERNAL_FUNCTION_PARAMETERS)
{
}
#endif /* SERIALIZABLE_STRUCT */
char * OrbitStruct_GetRepositoryId(OrbitStruct * pStruct)
{
if (pStruct->mIsException)
return ExceptionType_GetRepositoryId(pStruct->u.mpExceptionType);
else
return StructType_GetRepositoryId(pStruct->u.mpStructType);
}
static zend_bool OrbitStruct_InitializeMembers(OrbitStruct * pStruct)
{
MemberType * p_member = NULL;
if (pStruct->mIsException)
p_member = ExceptionType_GetFirstMember(pStruct->u.mpExceptionType);
else
p_member = StructType_GetFirstMember(pStruct->u.mpStructType);
zend_hash_init(
&pStruct->mMembers, /* hash table */
0, /* size */
NULL, /* hash function */
ZVAL_DESTRUCTOR, /* destructor */
0); /* persistent */
if (!MemberType_IsValid(p_member))
return TRUE; /* no members */
do
{
zval * p_value = NULL;
char * p_name = MemberType_GetName(p_member);
ALLOC_ZVAL(p_value);
ZVAL_NULL(p_value);
zend_hash_add(
&pStruct->mMembers,
p_name,
strlen(p_name)+1, /* important: include terminating zero byte */
p_value,
sizeof(zval),
NULL
);
} while (MemberType_GetNext(p_member));
return TRUE;
}
static zend_bool OrbitStruct_Initialize(const char * pId, OrbitStruct * pStruct)
{
/* find type info */
pStruct->u.mpStructType = TypeManager_FindStruct(pId);
if (pStruct->u.mpStructType == NULL)
{
/* not a struct -- maybe an exception? */
pStruct->u.mpExceptionType = TypeManager_FindException(pId);
if (pStruct->u.mpExceptionType == NULL)
{
zend_error(E_WARNING, "(Satellite) unknown struct or exception '%s'", pId);
goto error;
}
pStruct->mIsException = TRUE;
}
/* initialize members */
if (!OrbitStruct_InitializeMembers(pStruct))
goto error;
return TRUE;
error:
return FALSE;
}
/*
* used by orbit_namedvalue_to_zval_struct(...)
*/
zend_bool OrbitStruct_Create(const char * pId, zval * pDestination)
{
/* allocate buffer */
OrbitStruct * p_struct = orbit_new(OrbitStruct);
/* initialize struct */
if (!OrbitStruct_Initialize(pId, p_struct))
goto error;
/* set zval members */
pDestination->type = IS_OBJECT;
pDestination->is_ref = 1;
pDestination->refcount = 1;
pDestination->value.obj.ce = &OrbitStruct_class_entry;
pDestination->value.obj.properties = orbit_new(HashTable);
zend_hash_init(
pDestination->value.obj.properties, /* hash table */
0, /* size */
NULL, /* hash function */
ZVAL_PTR_DTOR, /* destructor */
0); /* persistent */
/* save orbit data */
OrbitStruct_SaveData(pDestination, p_struct);
return TRUE;
error:
orbit_delete(p_struct);
return FALSE;
}
/*
* Constructor
*
* Parameters: Repository ID of struct
*/
zend_bool OrbitStruct_Constructor(OrbitStruct ** ppStruct,
int parameterCount, const zval ** ppParameters)
{
/* allocate buffer */
OrbitStruct * p_struct = orbit_new(OrbitStruct);
/* check parameter count */
if (parameterCount != 1)
{
wrong_param_count();
goto error;
}
/* validate parameter types */
if (ppParameters[0]->type != IS_STRING)
goto error;
/* initialize struct */
if (!OrbitStruct_Initialize(ppParameters[0]->value.str.val, p_struct))
goto error;
*ppStruct = p_struct;
return TRUE;
error:
OrbitStruct_Destructor(p_struct);
*ppStruct = NULL;
return FALSE;
}
zend_bool OrbitStruct_Destructor(OrbitStruct * pStruct)
{
if (pStruct->mIsException)
ExceptionType_release(pStruct->u.mpExceptionType);
else
StructType_release(pStruct->u.mpStructType);
/* will crash on uninitialized members structure :-( */
zend_hash_destroy(&pStruct->mMembers);
orbit_delete(pStruct);
return TRUE;
}
/* not used */
zend_bool OrbitStruct_CallFunction(OrbitStruct * pStruct,
const char * pFunctionName, int parameterCount, const zval ** ppParameters, zval * pResult)
{
return FALSE;
}
zend_bool OrbitStruct_PutProperty(OrbitStruct * pStruct,
const char * pPropertyName, const zval * pValue)
{
zend_bool result;
result = orbit_store_by_key(&pStruct->mMembers, pPropertyName, pValue);
if (!result)
{
zend_error(E_WARNING, "(Satellite) unknown member '%s' in struct '%s'",
pPropertyName, OrbitStruct_GetRepositoryId(pStruct));
}
return result;
}
zend_bool OrbitStruct_GetProperty(OrbitStruct * pStruct,
const char * pPropertyName, zval * pReturnValue)
{
zval * p_value = orbit_find_by_key(&pStruct->mMembers, pPropertyName);
if (p_value == NULL)
{
zend_error(E_WARNING, "(Satellite) unknown member '%s' in struct '%s'",
pPropertyName, OrbitStruct_GetRepositoryId(pStruct));
ZVAL_NULL(pReturnValue);
return FALSE;
}
else
{
memcpy(pReturnValue, p_value, sizeof(zval)); /* raw data copy */
zval_copy_ctor(pReturnValue); /* smart data copy */
INIT_PZVAL(pReturnValue); /* set reference count */
return TRUE;
}
}