/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the XML::Sablotron::DOM module.
*
* The Initial Developer of the Original Code is Ginfer Alliance Ltd.
* Portions created by Ginger Alliance are
* Copyright (C) 1999-2000 Ginger Alliance Ltd..
* All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/*
*
* ../Sablotron.xs includes this file
*
*/
/************************************************************/
/* globals */
/************************************************************/
/* classes moved to common.h */
char *__classNames[] = CLASSNAMES;
/************************************************************/
/* error handling */
/************************************************************/
/* errorNames moved to common.h */
char* __errorNames[] = ERRORNAMES;
/* check function return value */
#define DE(sit, status) if (status) \
croak("XML::Sablotron::DOM(Code=%d, Name=%s, Msg=%s)", \
status, __errorNames[status], \
SDOM_getExceptionMessage(sit))
/* check the validity of the node */
#define CN(node) if (! node) croak("XML::Sablotron::DOM(Code=-1, Name='INVALID_NODE_ERR')")
/************************************************************/
/* globals for document */
/************************************************************/
#define DOC_HANDLE(doc) (SDOM_Document)SvIV(*hv_fetch((HV*)SvRV(doc), "_handle", 7, 0))
#define SIT_HANDLE(sit) (SablotSituation)SvIV(*hv_fetch((HV*)SvRV(sit), "_handle", 7, 0))
#define SIT_PARAM(cnt) ((items >= cnt) ? ST(cnt - 1) : &PL_sv_undef)
#define SIT_SMART(sit) (SvOK(sit) ? SIT_HANDLE(sit) : __sit)
bool __useUniqueDOMWrappers( void )
{
SV* flag = get_sv( "XML::Sablotron::DOM::useUniqueWrappers", FALSE );
return flag && SvTRUE(flag);
}
static SV* __createNodeOld(SablotSituation situa, SDOM_Node handle)
{
HV* hash;
SV* retval;
SDOM_NodeType type;
/* check and/or create inner SV* - used for validity checks*/
SV* inner = (SV*)SDOM_getNodeInstanceData(handle);
if (!inner) {
/* printf("+++> creating new inner\n"); */
inner = newSViv((IV)handle);
/* store inner SV to node */
SDOM_setNodeInstanceData(handle, inner);
} else {
/* printf("---> reusing the inner %d\n", SvIV(inner)); */
}
/* create new hash and store the handle into it */
hash = newHV();
hv_store(hash, "_handle", 7, SvREFCNT_inc(inner), 0);
/* create blessed reference */
retval = newRV_noinc((SV*)hash);
DE( situa, SDOM_getNodeType(situa, handle, &type) );
sv_bless(retval, gv_stashpv(__classNames[type], 0));
return retval;
}
void __checkNodeInstanceData( SDOM_Node handle, HV * inner )
{
if ( ! inner ) {
croak("XML::Sablotron::DOM(Code=-1, Name='INVALID_NODE_ERR', Msg='InstanceData corrupted: NULL')");
} else if ( SvTYPE( (SV*)inner ) != SVt_PVHV ) {
croak("XML::Sablotron::DOM(Code=-1, Name='INVALID_NODE_ERR', Msg='InstanceData corrupted: not a HV')");
} else {
SV * ref = newRV_inc((SV*) inner);
if ( ! ( sv_isobject( ref ) && sv_derived_from( ref , "XML::Sablotron::DOM::Node" ) ) ) {
SvREFCNT_dec(ref);
croak("XML::Sablotron::DOM(Code=-1, Name='INVALID_NODE_ERR', Msg='InstanceData corrupted: not a XML::Sablotron::DOM::Node");
} else if ( NODE_HANDLE( ref ) != handle ) {
SvREFCNT_dec(ref);
croak("XML::Sablotron::DOM(Code=-1, Name='INVALID_NODE_ERR', Msg='InstanceData corrupted: points to wrong node");
}
SvREFCNT_dec(ref);
}
}
static SV* __createNodeNew(SablotSituation situa, SDOM_Node handle)
{
SV* retval;
HV * hash;
SDOM_NodeType type;
/* we create only one wrapper object and one ref for each handle */
/* is there already an wrapper ? */
hash = (HV*)SDOM_getNodeInstanceData(handle);
if ( hash ) {
/* validity test */
__checkNodeInstanceData( handle, hash );
/* hash handle is ok. Return a new reference to it. */
retval = newRV_inc((SV*)hash);
#if 0
fprintf(stderr,"DOM.h::__createNodeNew(%p): new rv %p reusing hv %p (%d)\n",
handle, retval, hash,(int)SvREFCNT((SV*)hash));
#endif
return retval;
}
/* create new hash and store the handle into it */
hash = newHV();
hv_store(hash, "_handle", 7, newSViv( (IV) handle ), 0);
SDOM_setNodeInstanceData(handle, hash);
/* create blessed reference */
retval = newRV_inc((SV*)hash);
DE( situa, SDOM_getNodeType(situa, handle, &type) );
retval = sv_bless(retval, gv_stashpv(__classNames[type], 0));
#if 0
fprintf(stderr,"DOM.h::__createNodeNew(%p): new rv %p hash %p (%d)\n",
handle, retval, hash,(int)SvREFCNT((SV*)hash) );
#endif
/* sv_dump( retval );
sv_dump( (SV*) hash ); */
return retval;
}
static SV* __createNode(SablotSituation situa, SDOM_Node handle)
{
if ( __useUniqueDOMWrappers() ) {
return __createNodeNew(situa, handle);
}
return __createNodeOld(situa, handle);
}
/************************************************************/
/* dispose calback */
/************************************************************/
static void __nodeDisposeCallbackOld(SDOM_Node node)
{
SV* pnode = (SV*)SDOM_getNodeInstanceData(node);
if ( pnode ) sv_setiv(pnode, 0);
}
static void __nodeDisposeCallbackNew(SDOM_Node node)
{
HV * inner = (HV*)SDOM_getNodeInstanceData( node );
if ( inner ) {
__checkNodeInstanceData( node , inner );
sv_setiv( *hv_fetch( inner, "_handle", 7, 0), 0 );
SvREFCNT_dec( inner );
}
}
void __nodeDisposeCallback(SDOM_Node node)
{
if ( __useUniqueDOMWrappers() )
__nodeDisposeCallbackNew(node);
else
__nodeDisposeCallbackOld(node);
}
/*************************************************************/
/* get implicit situation */
/*************************************************************/
SablotSituation __sit;