File Coverage

perl-libxml-mm.c
Criterion Covered Total %
statement 345 406 84.9
branch 199 316 62.9
condition n/a
subroutine n/a
pod n/a
total 544 722 75.3


line stmt bran cond sub pod time code
1             /**
2             * perl-libxml-mm.c
3             * $Id$
4             *
5             * This is free software, you may use it and distribute it under the same terms as
6             * Perl itself.
7             *
8             * Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas
9             */
10              
11             /*
12             *
13             * Basic concept:
14             * perl varies in the implementation of UTF8 handling. this header (together
15             * with the c source) implements a few functions, that can be used from within
16             * the core module inorder to avoid cascades of c pragmas
17             */
18              
19             #ifdef __cplusplus
20             extern "C" {
21             #endif
22              
23             #include
24             #include
25              
26             #include "perl-libxml-mm.h"
27              
28             #include "XSUB.h"
29             #include "ppport.h"
30             #include
31              
32             #ifdef XML_LIBXML_GDOME_SUPPORT
33              
34             #include
35             #include
36              
37             #endif
38              
39             #include "perl-libxml-sax.h"
40              
41             #ifdef __cplusplus
42             }
43             #endif
44              
45             /**
46             * this is a wrapper function that does the type evaluation for the
47             * node. this makes the code a little more readable in the .XS
48             *
49             * the code is not really portable, but i think we'll avoid some
50             * memory leak problems that way.
51             **/
52             const char*
53 20442           PmmNodeTypeName( xmlNodePtr elem ){
54 20442           const char *name = "XML::LibXML::Node";
55              
56 20442 50         if ( elem != NULL ) {
57 20442           switch ( elem->type ) {
58             case XML_ELEMENT_NODE:
59 19155           name = "XML::LibXML::Element";
60 19155           break;
61             case XML_TEXT_NODE:
62 275           name = "XML::LibXML::Text";
63 275           break;
64             case XML_COMMENT_NODE:
65 51           name = "XML::LibXML::Comment";
66 51           break;
67             case XML_CDATA_SECTION_NODE:
68 56           name = "XML::LibXML::CDATASection";
69 56           break;
70             case XML_ATTRIBUTE_NODE:
71 112           name = "XML::LibXML::Attr";
72 112           break;
73             case XML_DOCUMENT_NODE:
74             case XML_HTML_DOCUMENT_NODE:
75 597           name = "XML::LibXML::Document";
76 597           break;
77             case XML_DOCUMENT_FRAG_NODE:
78 103           name = "XML::LibXML::DocumentFragment";
79 103           break;
80             case XML_NAMESPACE_DECL:
81 2           name = "XML::LibXML::Namespace";
82 2           break;
83             case XML_DTD_NODE:
84 63           name = "XML::LibXML::Dtd";
85 63           break;
86             case XML_PI_NODE:
87 18           name = "XML::LibXML::PI";
88 18           break;
89             default:
90 10           name = "XML::LibXML::Node";
91 10           break;
92             };
93 20442           return name;
94             }
95 0           return "";
96             }
97              
98             /*
99             * free a hash table
100             */
101             void
102 0           PmmFreeHashTable(xmlHashTablePtr table)
103             {
104 0 0         if( xmlHashSize(table) > 0 ) {
105 0           warn("PmmFreeHashTable: not empty\n");
106             /* PmmDumpRegistry(table); */
107             }
108             /* warn("Freeing table %p with %d elements in\n", table, xmlHashSize(table)); */
109 0           xmlHashFree(table, NULL);
110 0           }
111              
112             #ifdef XML_LIBXML_THREADS
113              
114             /*
115             * registry of all current proxy nodes
116             *
117             * other classes like XML::LibXSLT must get a pointer
118             * to this registry via XML::LibXML::__proxy_registry
119             *
120             */
121             extern SV* PROXY_NODE_REGISTRY_MUTEX;
122              
123             /* Utility method used by PmmDumpRegistry */
124             void PmmRegistryDumpHashScanner(void * payload, void * data, xmlChar * name)
125             {
126             LocalProxyNodePtr lp = (LocalProxyNodePtr) payload;
127             ProxyNodePtr node = (ProxyNodePtr) lp->proxy;
128             const char * CLASS = PmmNodeTypeName( PmmNODE(node) );
129             warn("%s=%p with %d references (%d perl)\n",CLASS,node,PmmREFCNT(node),lp->count);
130             }
131              
132             /*
133             * dump the current thread's node registry to STDERR
134             */
135             void
136             PmmDumpRegistry(xmlHashTablePtr r)
137             {
138             if( r )
139             {
140             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
141             warn("%d total nodes\n", xmlHashSize(r));
142             xmlHashScan(r, PmmRegistryDumpHashScanner, NULL);
143             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
144             }
145             }
146              
147             /*
148             * returns the address of the proxy registry
149             */
150             xmlHashTablePtr*
151             PmmProxyNodeRegistryPtr(ProxyNodePtr proxy)
152             {
153             croak("PmmProxyNodeRegistryPtr: TODO!\n");
154             return NULL;
155             /* return &PmmREGISTRY; */
156             }
157              
158             /*
159             * efficiently generate a string representation of the given pointer
160             */
161             #define _PMM_HASH_NAME_SIZE(n) n+(n>>3)+(n%8>0 ? 1 : 0)
162             xmlChar *
163             PmmRegistryName(void * ptr)
164             {
165             unsigned long int v = (unsigned long int) ptr;
166             int HASH_NAME_SIZE = _PMM_HASH_NAME_SIZE(sizeof(void*));
167             xmlChar * name;
168             int i;
169              
170             name = (xmlChar *) safemalloc(HASH_NAME_SIZE+1);
171              
172             for(i = 0; i < HASH_NAME_SIZE; ++i)
173             {
174             name[i] = (xmlChar) (128 | v);
175             v >>= 7;
176             }
177             name[HASH_NAME_SIZE] = '\0';
178              
179             return name;
180             }
181              
182             /*
183             * allocate and return a new LocalProxyNode structure
184             */
185             LocalProxyNodePtr
186             PmmNewLocalProxyNode(ProxyNodePtr proxy)
187             {
188             LocalProxyNodePtr lp;
189             Newc(0, lp, 1, LocalProxyNode, LocalProxyNode);
190             lp->proxy = proxy;
191             lp->count = 0;
192             return lp;
193             }
194              
195             /*
196             * @proxy: proxy node to register
197             *
198             * adds a proxy node to the proxy node registry
199             */
200             LocalProxyNodePtr
201             PmmRegisterProxyNode(ProxyNodePtr proxy)
202             {
203             xmlChar * name = PmmRegistryName( proxy );
204             LocalProxyNodePtr lp = PmmNewLocalProxyNode( proxy );
205             /* warn("LibXML registers proxy node with %p\n",PmmREGISTRY); */
206             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
207             if( xmlHashAddEntry(PmmREGISTRY, name, lp) )
208             croak("PmmRegisterProxyNode: error adding node to hash, hash size is %d\n",xmlHashSize(PmmREGISTRY));
209             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
210             Safefree(name);
211             return lp;
212             }
213              
214             /* utility method for PmmUnregisterProxyNode */
215             /* PP: originally this was static inline void, but on AIX the compiler
216             did not chew it, so I'm removing the inline */
217             static void
218             PmmRegistryHashDeallocator(void *payload, xmlChar *name)
219             {
220             Safefree((LocalProxyNodePtr) payload);
221             }
222              
223             /*
224             * @proxy: proxy node to remove
225             *
226             * removes a proxy node from the proxy node registry
227             */
228             void
229             PmmUnregisterProxyNode(ProxyNodePtr proxy)
230             {
231             xmlChar * name = PmmRegistryName( proxy );
232             /* warn("LibXML unregistering proxy node with %p\n",PmmREGISTRY); */
233             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
234             if( xmlHashRemoveEntry(PmmREGISTRY, name, PmmRegistryHashDeallocator) )
235             croak("PmmUnregisterProxyNode: error removing node from hash\n");
236             Safefree(name);
237             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
238             }
239              
240             /*
241             * lookup a LocalProxyNode in the registry
242             */
243             LocalProxyNodePtr
244             PmmRegistryLookup(ProxyNodePtr proxy)
245             {
246             xmlChar * name = PmmRegistryName( proxy );
247             LocalProxyNodePtr lp = xmlHashLookup(PmmREGISTRY, name);
248             Safefree(name);
249             return lp;
250             }
251              
252             /*
253             * increment the local refcount for proxy
254             */
255             void
256             PmmRegistryREFCNT_inc(ProxyNodePtr proxy)
257             {
258             /* warn("Registry inc\n"); */
259             LocalProxyNodePtr lp = PmmRegistryLookup( proxy );
260             if( lp )
261             lp->count++;
262             else
263             PmmRegisterProxyNode( proxy )->count++;
264             }
265              
266             /*
267             * decrement the local refcount for proxy and remove the local pointer if zero
268             */
269             void
270             PmmRegistryREFCNT_dec(ProxyNodePtr proxy)
271             {
272             /* warn("Registry dec\n"); */
273             LocalProxyNodePtr lp = PmmRegistryLookup(proxy);
274             if( lp && --(lp->count) == 0 )
275             PmmUnregisterProxyNode(proxy);
276             }
277              
278             /*
279             * internal, used by PmmCloneProxyNodes
280             */
281             void *
282             PmmRegistryHashCopier(void *payload, xmlChar *name)
283             {
284             ProxyNodePtr proxy = ((LocalProxyNodePtr) payload)->proxy;
285             LocalProxyNodePtr lp;
286             Newc(0, lp, 1, LocalProxyNode, LocalProxyNode);
287             memcpy(lp, payload, sizeof(LocalProxyNode));
288             PmmREFCNT_inc(proxy);
289             return lp;
290             }
291              
292             /*
293             * increments all proxy node counters by one (called on thread spawn)
294             */
295             void
296             PmmCloneProxyNodes()
297             {
298             SV *sv_reg = get_sv("XML::LibXML::__PROXY_NODE_REGISTRY",0);
299             xmlHashTablePtr reg_copy;
300             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
301             reg_copy = xmlHashCopy(PmmREGISTRY, PmmRegistryHashCopier);
302             SvIV_set(SvRV(sv_reg), PTR2IV(reg_copy));
303             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
304             }
305              
306             /*
307             * returns the current number of proxy nodes in the registry
308             */
309             int
310             PmmProxyNodeRegistrySize()
311             {
312             return xmlHashSize(PmmREGISTRY);
313             }
314              
315             #endif /* end of XML_LIBXML_THREADS */
316              
317             /* creates a new proxy node from a given node. this function is aware
318             * about the fact that a node may already has a proxy structure.
319             */
320             ProxyNodePtr
321 57041           PmmNewNode(xmlNodePtr node)
322             {
323 57041           ProxyNodePtr proxy = NULL;
324              
325 57041 50         if ( node == NULL ) {
326             xs_warn( "PmmNewNode: no node found\n" );
327 0           return NULL;
328             }
329              
330 57041 100         if ( node->_private == NULL ) {
331 11089 100         switch ( node->type ) {
332             case XML_DOCUMENT_NODE:
333             case XML_HTML_DOCUMENT_NODE:
334             case XML_DOCB_DOCUMENT_NODE:
335 500           proxy = (ProxyNodePtr)xmlMalloc(sizeof(struct _DocProxyNode));
336 500 50         if (proxy != NULL) {
337 500           ((DocProxyNodePtr)proxy)->psvi_status = Pmm_NO_PSVI;
338 500           SetPmmENCODING(proxy, XML_CHAR_ENCODING_NONE);
339             }
340 500           break;
341             default:
342 10589           proxy = (ProxyNodePtr)xmlMalloc(sizeof(struct _ProxyNode));
343 10589           break;
344             }
345 11089 50         if (proxy != NULL) {
346 11089           proxy->node = node;
347 11089           proxy->owner = NULL;
348 11089           proxy->count = 0;
349 11089           node->_private = (void*) proxy;
350             }
351             }
352             else {
353 45952           proxy = (ProxyNodePtr)node->_private;
354             }
355              
356 57041           return proxy;
357             }
358              
359             ProxyNodePtr
360 275           PmmNewFragment(xmlDocPtr doc)
361             {
362 275           ProxyNodePtr retval = NULL;
363 275           xmlNodePtr frag = NULL;
364              
365             xs_warn("PmmNewFragment: new frag\n");
366 275           frag = xmlNewDocFragment( doc );
367 275           retval = PmmNewNode(frag);
368             /* fprintf(stderr, "REFCNT NOT incremented on frag: 0x%08.8X\n", retval); */
369              
370 275 100         if ( doc != NULL ) {
371             xs_warn("PmmNewFragment: inc document\n");
372             /* under rare circumstances _private is not set correctly? */
373 229 50         if ( doc->_private != NULL ) {
374             xs_warn("PmmNewFragment: doc->_private being incremented!\n");
375 229           PmmREFCNT_inc(((ProxyNodePtr)doc->_private));
376             /* fprintf(stderr, "REFCNT incremented on doc: 0x%08.8X\n", doc->_private); */
377             }
378 229           retval->owner = (xmlNodePtr)doc;
379             }
380              
381 275           return retval;
382             }
383              
384             /* frees the node if necessary. this method is aware that libxml2
385             * has several different nodetypes.
386             */
387             void
388 879           PmmFreeNode( xmlNodePtr node )
389             {
390 879           switch( node->type ) {
391             case XML_DOCUMENT_NODE:
392             case XML_HTML_DOCUMENT_NODE:
393             xs_warn("PmmFreeNode: XML_DOCUMENT_NODE\n");
394 500           xmlFreeDoc( (xmlDocPtr) node );
395 500           break;
396             case XML_ATTRIBUTE_NODE:
397             xs_warn("PmmFreeNode: XML_ATTRIBUTE_NODE\n");
398 14 50         if ( node->parent == NULL ) {
399             xs_warn( "PmmFreeNode: free node!\n");
400 14           node->ns = NULL;
401 14           xmlFreeProp( (xmlAttrPtr) node );
402             }
403 14           break;
404             case XML_DTD_NODE:
405 18 100         if ( node->doc != NULL ) {
406 12 100         if ( node->doc->extSubset != (xmlDtdPtr)node
407 11 50         && node->doc->intSubset != (xmlDtdPtr)node ) {
408             xs_warn( "PmmFreeNode: XML_DTD_NODE\n");
409 11           node->doc = NULL;
410 12           xmlFreeDtd( (xmlDtdPtr)node );
411             }
412             } else {
413             xs_warn( "PmmFreeNode: XML_DTD_NODE (no doc)\n");
414 6           xmlFreeDtd( (xmlDtdPtr)node );
415             }
416 18           break;
417             case XML_DOCUMENT_FRAG_NODE:
418             xs_warn("PmmFreeNode: XML_DOCUMENT_FRAG_NODE\n");
419             default:
420             xs_warn( "PmmFreeNode: normal node\n" );
421 347           xmlFreeNode( node);
422 347           break;
423             }
424 879           }
425              
426             /* decrements the proxy counter. if the counter becomes zero or less,
427             this method will free the proxy node. If the node is part of a
428             subtree, PmmREFCNT_dec will fix the reference counts and delete
429             the subtree if it is not required any more.
430             */
431             int
432 31176           PmmREFCNT_dec( ProxyNodePtr node )
433             {
434 31176           xmlNodePtr libnode = NULL;
435 31176           ProxyNodePtr owner = NULL;
436 31176           int retval = 0;
437              
438 31176 50         if ( node != NULL ) {
439 31176           retval = PmmREFCNT(node)--;
440             /* fprintf(stderr, "REFCNT on 0x%08.8X decremented to %d\n", node, PmmREFCNT(node)); */
441 31176 50         if ( PmmREFCNT(node) < 0 )
442 0           warn( "PmmREFCNT_dec: REFCNT decremented below 0 for %p!", node );
443 31176 100         if ( PmmREFCNT(node) <= 0 ) {
444             xs_warn( "PmmREFCNT_dec: NODE DELETION\n" );
445              
446 11089           libnode = PmmNODE( node );
447 11089 100         if ( libnode != NULL ) {
448 11088 50         if ( libnode->_private != node ) {
449             xs_warn( "PmmREFCNT_dec: lost node\n" );
450 0           libnode = NULL;
451             }
452             else {
453 11088           libnode->_private = NULL;
454             }
455             }
456              
457 11089           PmmNODE( node ) = NULL;
458 11089 100         if ( PmmOWNER(node) && PmmOWNERPO(node) ) {
    50          
    50          
    50          
    0          
459             xs_warn( "PmmREFCNT_dec: DOC NODE!\n" );
460 10470 50         owner = PmmOWNERPO(node);
    50          
461 10470           PmmOWNER( node ) = NULL;
462 10470 100         if( libnode != NULL && libnode->parent == NULL ) {
    100          
463             /* this is required if the node does not directly
464             * belong to the document tree
465             */
466             xs_warn( "PmmREFCNT_dec: REAL DELETE\n" );
467 260           PmmFreeNode( libnode );
468             }
469             xs_warn( "PmmREFCNT_dec: decrease owner\n" );
470 10470           PmmREFCNT_dec( owner );
471             }
472 619 50         else if ( libnode != NULL ) {
473             xs_warn( "PmmREFCNT_dec: STANDALONE REAL DELETE\n" );
474              
475 619           PmmFreeNode( libnode );
476             }
477             else {
478             xs_warn( "PmmREFCNT_dec: NO OWNER\n" );
479             }
480 31176           xmlFree( node );
481             }
482             }
483             else {
484             xs_warn("PmmREFCNT_dec: lost node\n" );
485             }
486 31176           return retval;
487             }
488              
489             /* @node: the node that should be wrapped into a SV
490             * @owner: perl instance of the owner node (may be NULL)
491             *
492             * This function will create a real perl instance of a given node.
493             * the function is called directly by the XS layer, to generate a perl
494             * instance of the node. All node reference counts are updated within
495             * this function. Therefore this function returns a node that can
496             * directly be used as output.
497             *
498             * if @ower is NULL or undefined, the node is ment to be the root node
499             * of the tree. this node will later be used as an owner of other
500             * nodes.
501             */
502             SV*
503 20452           PmmNodeToSv( xmlNodePtr node, ProxyNodePtr owner )
504             {
505 20452           ProxyNodePtr dfProxy= NULL;
506             dTHX;
507 20452           SV * retval = &PL_sv_undef;
508 20452           const char * CLASS = "XML::LibXML::Node";
509              
510 20452 100         if ( node != NULL ) {
511             #ifdef XML_LIBXML_THREADS
512             if( PmmUSEREGISTRY )
513             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
514             #endif
515             /* find out about the class */
516 20440           CLASS = PmmNodeTypeName( node );
517             xs_warn("PmmNodeToSv: return new perl node of class:\n");
518             xs_warn( CLASS );
519              
520 20440 100         if ( node->_private != NULL ) {
521 9627           dfProxy = PmmNewNode(node);
522             /* fprintf(stderr, " at 0x%08.8X\n", dfProxy); */
523             }
524             else {
525 10813           dfProxy = PmmNewNode(node);
526             /* fprintf(stderr, " at 0x%08.8X\n", dfProxy); */
527 10813 50         if ( dfProxy != NULL ) {
528 10813 100         if ( owner != NULL ) {
529 10245           dfProxy->owner = PmmNODE( owner );
530 10245           PmmREFCNT_inc( owner );
531             /* fprintf(stderr, "REFCNT incremented on owner: 0x%08.8X\n", owner); */
532             }
533             else {
534             xs_warn("PmmNodeToSv: node contains itself (owner==NULL)\n");
535             }
536             }
537             else {
538 0           croak("XML::LibXML: failed to create a proxy node (out of memory?)\n");
539             }
540             }
541              
542 20440           retval = NEWSV(0,0);
543 20440           sv_setref_pv( retval, CLASS, (void*)dfProxy );
544             #ifdef XML_LIBXML_THREADS
545             if( PmmUSEREGISTRY )
546             PmmRegistryREFCNT_inc(dfProxy);
547             #endif
548 20440           PmmREFCNT_inc(dfProxy);
549             /* fprintf(stderr, "REFCNT incremented on node: 0x%08.8X\n", dfProxy); */
550              
551 20440 100         switch ( node->type ) {
552             case XML_DOCUMENT_NODE:
553             case XML_HTML_DOCUMENT_NODE:
554             case XML_DOCB_DOCUMENT_NODE:
555 597 100         if ( ((xmlDocPtr)node)->encoding != NULL ) {
556 73           SetPmmENCODING(dfProxy, (int)xmlParseCharEncoding( (const char*)((xmlDocPtr)node)->encoding ));
557             }
558 597           break;
559             default:
560 20440           break;
561             }
562             #ifdef XML_LIBXML_THREADS
563             if( PmmUSEREGISTRY )
564             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
565             #endif
566             }
567             else {
568             xs_warn( "PmmNodeToSv: no node found!\n" );
569             }
570              
571 20452           return retval;
572             }
573              
574              
575             xmlNodePtr
576 8           PmmCloneNode( xmlNodePtr node, int recursive )
577             {
578 8           xmlNodePtr retval = NULL;
579              
580 8 50         if ( node != NULL ) {
581 8           switch ( node->type ) {
582             case XML_ELEMENT_NODE:
583             case XML_TEXT_NODE:
584             case XML_CDATA_SECTION_NODE:
585             case XML_ENTITY_REF_NODE:
586             case XML_PI_NODE:
587             case XML_COMMENT_NODE:
588             case XML_DOCUMENT_FRAG_NODE:
589             case XML_ENTITY_DECL:
590 7 100         retval = xmlCopyNode( node, recursive ? 1 : 2 );
591 7           break;
592             case XML_ATTRIBUTE_NODE:
593 0           retval = (xmlNodePtr) xmlCopyProp( NULL, (xmlAttrPtr) node );
594 0           break;
595             case XML_DOCUMENT_NODE:
596             case XML_HTML_DOCUMENT_NODE:
597 0           retval = (xmlNodePtr) xmlCopyDoc( (xmlDocPtr)node, recursive );
598 0           break;
599             case XML_DOCUMENT_TYPE_NODE:
600             case XML_DTD_NODE:
601 1           retval = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr)node );
602 1           break;
603             case XML_NAMESPACE_DECL:
604 0           retval = ( xmlNodePtr ) xmlCopyNamespace( (xmlNsPtr) node );
605 0           break;
606             default:
607 0           break;
608             }
609             }
610              
611 8           return retval;
612             }
613              
614             /* extracts the libxml2 node from a perl reference
615             */
616              
617             xmlNodePtr
618 19694           PmmSvNodeExt( SV* perlnode, int copy )
619             {
620 19694           xmlNodePtr retval = NULL;
621 19694           ProxyNodePtr proxy = NULL;
622             dTHX;
623              
624 19694 100         if ( perlnode != NULL && perlnode != &PL_sv_undef ) {
    100          
625             /* if ( sv_derived_from(perlnode, "XML::LibXML::Node") */
626             /* && SvPROXYNODE(perlnode) != NULL ) { */
627             /* retval = PmmNODE( SvPROXYNODE(perlnode) ) ; */
628             /* } */
629             xs_warn("PmmSvNodeExt: perlnode found\n" );
630 19682 100         if ( sv_derived_from(perlnode, "XML::LibXML::Node") ) {
631 19680 50         proxy = SvPROXYNODE(perlnode);
632 19680 50         if ( proxy != NULL ) {
633             xs_warn( "PmmSvNodeExt: is a xmlNodePtr structure\n" );
634 19680           retval = PmmNODE( proxy ) ;
635             }
636              
637 19680 100         if ( retval != NULL
638 19679 50         && ((ProxyNodePtr)retval->_private) != proxy ) {
639             xs_warn( "PmmSvNodeExt: no node in proxy node\n" );
640 0           PmmNODE( proxy ) = NULL;
641 0           retval = NULL;
642             }
643             }
644             #ifdef XML_LIBXML_GDOME_SUPPORT
645             else if ( sv_derived_from( perlnode, "XML::GDOME::Node" ) ) {
646             GdomeNode* gnode = (GdomeNode*)SvIV((SV*)SvRV( perlnode ));
647             if ( gnode == NULL ) {
648             warn( "no XML::GDOME data found (datastructure empty)" );
649             }
650             else {
651             retval = gdome_xml_n_get_xmlNode( gnode );
652             if ( retval == NULL ) {
653             xs_warn( "PmmSvNodeExt: no XML::LibXML node found in GDOME object\n" );
654             }
655             else if ( copy == 1 ) {
656             retval = PmmCloneNode( retval, 1 );
657             }
658             }
659             }
660             #endif
661             }
662              
663 19694           return retval;
664             }
665              
666             /* extracts the libxml2 owner node from a perl reference
667             */
668             xmlNodePtr
669 0           PmmSvOwner( SV* perlnode )
670             {
671             dTHX;
672 0           xmlNodePtr retval = NULL;
673 0 0         if ( perlnode != NULL
674 0 0         && perlnode != &PL_sv_undef
675 0 0         && SvPROXYNODE(perlnode) != NULL ) {
    0          
676 0 0         retval = PmmOWNER( SvPROXYNODE(perlnode) );
677             }
678 0           return retval;
679             }
680              
681             /* reverse to PmmSvOwner(). sets the owner of the current node. this
682             * will increase the proxy count of the owner.
683             */
684             SV*
685 0           PmmSetSvOwner( SV* perlnode, SV* extra )
686             {
687             dTHX;
688 0 0         if ( perlnode != NULL && perlnode != &PL_sv_undef ) {
    0          
689 0 0         PmmOWNER( SvPROXYNODE(perlnode)) = PmmNODE( SvPROXYNODE(extra) );
    0          
690 0 0         PmmREFCNT_inc( SvPROXYNODE(extra) );
691             /* fprintf(stderr, "REFCNT incremented on new owner: 0x%08.8X\n", SvPROXYNODE(extra)); */
692             }
693 0           return perlnode;
694             }
695              
696             void PmmFixOwnerList( xmlNodePtr list, ProxyNodePtr parent );
697              
698             /**
699             * this functions fixes the reference counts for an entire subtree.
700             * it is very important to fix an entire subtree after node operations
701             * where the documents or the owner node may get changed. this method is
702             * aware about nodes that already belong to a certain owner node.
703             *
704             * the method uses the internal methods PmmFixNode and PmmChildNodes to
705             * do the real updates.
706             *
707             * in the worst case this traverses the subtree twice during a node
708             * operation. this case is only given when the node has to be
709             * adopted by the document. Since the ownerdocument and the effective
710             * owner may differ this double traversing makes sense.
711             */
712             int
713 269           PmmFixOwner( ProxyNodePtr nodetofix, ProxyNodePtr parent )
714             {
715 269           ProxyNodePtr oldParent = NULL;
716              
717 269 50         if ( nodetofix != NULL ) {
718 269 50         switch ( PmmNODE(nodetofix)->type ) {
719             case XML_ENTITY_DECL:
720             case XML_ATTRIBUTE_DECL:
721             case XML_NAMESPACE_DECL:
722             case XML_ELEMENT_DECL:
723             case XML_DOCUMENT_NODE:
724             xs_warn( "PmmFixOwner: don't need to fix this type of node\n" );
725 0           return(0);
726             default:
727 269           break;
728             }
729              
730 269 100         if ( PmmOWNER(nodetofix) != NULL ) {
731 267 50         oldParent = PmmOWNERPO(nodetofix);
    50          
732             }
733              
734             /* The owner data is only fixed if the node is neither a
735             * fragment nor a document. Also no update will happen if
736             * the node is already his owner or the owner has not
737             * changed during previous operations.
738             */
739 269 100         if( oldParent != parent ) {
740             xs_warn( "PmmFixOwner: re-parenting node\n" );
741             /* fprintf(stderr, " 0x%08.8X (%s)\n", nodetofix, PmmNODE(nodetofix)->name); */
742 260 100         if ( parent && parent != nodetofix ){
    50          
743 254           PmmOWNER(nodetofix) = PmmNODE(parent);
744 254           PmmREFCNT_inc( parent );
745             /* fprintf(stderr, "REFCNT incremented on new parent: 0x%08.8X\n", parent); */
746             }
747             else {
748 6           PmmOWNER(nodetofix) = NULL;
749             }
750              
751 260 100         if ( oldParent != NULL && oldParent != nodetofix )
    50          
752 258           PmmREFCNT_dec(oldParent);
753              
754 260 100         if ( PmmNODE(nodetofix)->type != XML_ATTRIBUTE_NODE
755 246 100         && PmmNODE(nodetofix)->type != XML_DTD_NODE
756 234 100         && PmmNODE(nodetofix)->properties != NULL ) {
757 8           PmmFixOwnerList( (xmlNodePtr)PmmNODE(nodetofix)->properties,
758             parent );
759             }
760              
761 260 100         if ( parent == NULL || PmmNODE(nodetofix)->parent == NULL ) {
    100          
762             /* fix to self */
763 11           parent = nodetofix;
764             }
765              
766 260           PmmFixOwnerList(PmmNODE(nodetofix)->children, parent);
767             }
768             else {
769             xs_warn( "PmmFixOwner: node doesn't need to get fixed\n" );
770             }
771 269           return(1);
772             }
773 0           return(0);
774             }
775              
776             void
777 371           PmmFixOwnerList( xmlNodePtr list, ProxyNodePtr parent )
778             {
779 371 100         if ( list != NULL ) {
780 82           xmlNodePtr iterator = list;
781 207 100         while ( iterator != NULL ) {
782 125 100         switch ( iterator->type ) {
783             case XML_ENTITY_DECL:
784             case XML_ATTRIBUTE_DECL:
785             case XML_NAMESPACE_DECL:
786             case XML_ELEMENT_DECL:
787             xs_warn( "PmmFixOwnerList: don't need to fix this type of node\n" );
788 27           iterator = iterator->next;
789 27           continue;
790             break;
791             default:
792 98           break;
793             }
794              
795 98 100         if ( iterator->_private != NULL ) {
796 5           PmmFixOwner( (ProxyNodePtr)iterator->_private, parent );
797             }
798             else {
799 93 100         if ( iterator->type != XML_ATTRIBUTE_NODE
800 79 100         && iterator->properties != NULL ){
801 7           PmmFixOwnerList( (xmlNodePtr)iterator->properties, parent );
802             }
803 93           PmmFixOwnerList(iterator->children, parent);
804             }
805 98           iterator = iterator->next;
806             }
807             }
808 371           }
809              
810             void
811 3           PmmFixOwnerNode( xmlNodePtr node, ProxyNodePtr parent )
812             {
813 3 50         if ( node != NULL && parent != NULL ) {
    50          
814 3 50         if ( node->_private != NULL ) {
815             xs_warn( "PmmFixOwnerNode: calling PmmFixOwner\n" );
816 0           PmmFixOwner( node->_private, parent );
817             }
818             else {
819             xs_warn( "PmmFixOwnerNode: calling PmmFixOwnerList\n" );
820 3           PmmFixOwnerList(node->children, parent );
821             }
822             }
823 3           }
824              
825             ProxyNodePtr
826 78           PmmNewContext(xmlParserCtxtPtr node)
827             {
828 78           ProxyNodePtr proxy = NULL;
829              
830 78           proxy = (ProxyNodePtr)xmlMalloc(sizeof(ProxyNode));
831 78 50         if (proxy != NULL) {
832 78           proxy->node = (xmlNodePtr)node;
833 78           proxy->owner = NULL;
834 78           proxy->count = 0;
835             }
836             else {
837 0           warn( "empty context" );
838             }
839 78           return proxy;
840             }
841              
842             int
843 78           PmmContextREFCNT_dec( ProxyNodePtr node )
844             {
845 78           xmlParserCtxtPtr libnode = NULL;
846 78           int retval = 0;
847 78 50         if ( node != NULL ) {
848 78           retval = PmmREFCNT(node)--;
849             /* fprintf(stderr, "REFCNT on context %p decremented to %d\n", node, PmmREFCNT(node)); */
850 78 50         if ( PmmREFCNT(node) <= 0 ) {
851             xs_warn( "PmmContextREFCNT_dec: NODE DELETION\n" );
852 78           libnode = (xmlParserCtxtPtr)PmmNODE( node );
853 78 100         if ( libnode != NULL ) {
854 1 50         if (libnode->_private != NULL ) {
855 0 0         if ( libnode->_private != (void*)node ) {
856 0           PmmSAXCloseContext( libnode );
857             }
858             else {
859 0           xmlFree( libnode->_private );
860             }
861 0           libnode->_private = NULL;
862             }
863 1           PmmNODE( node ) = NULL;
864 1           xmlFreeParserCtxt(libnode);
865             }
866             }
867 78           xmlFree( node );
868             }
869 78           return retval;
870             }
871              
872             SV*
873 78           PmmContextSv( xmlParserCtxtPtr ctxt )
874             {
875 78           ProxyNodePtr dfProxy= NULL;
876             dTHX;
877 78           SV * retval = &PL_sv_undef;
878 78           const char * CLASS = "XML::LibXML::ParserContext";
879              
880 78 50         if ( ctxt != NULL ) {
881 78           dfProxy = PmmNewContext(ctxt);
882              
883 78           retval = NEWSV(0,0);
884 78           sv_setref_pv( retval, CLASS, (void*)dfProxy );
885 78           PmmREFCNT_inc(dfProxy);
886             /* fprintf(stderr, "REFCNT incremented on new context: 0x%08.8X\n", dfProxy); */
887             }
888             else {
889             xs_warn( "PmmContextSv: no node found!\n" );
890             }
891              
892 78           return retval;
893             }
894              
895             xmlParserCtxtPtr
896 376           PmmSvContext( SV * scalar )
897             {
898 376           xmlParserCtxtPtr retval = NULL;
899             dTHX;
900              
901 376 50         if ( scalar != NULL
902 376 50         && scalar != &PL_sv_undef
903 376 50         && sv_isa( scalar, "XML::LibXML::ParserContext" )
904 376 50         && SvPROXYNODE(scalar) != NULL ) {
    50          
905 376 50         retval = (xmlParserCtxtPtr)PmmNODE( SvPROXYNODE(scalar) );
906             }
907             else {
908 0 0         if ( scalar == NULL
909 0 0         && scalar == &PL_sv_undef ) {
910             xs_warn( "PmmSvContext: no scalar!\n" );
911             }
912 0 0         else if ( ! sv_isa( scalar, "XML::LibXML::ParserContext" ) ) {
913             xs_warn( "PmmSvContext: bad object\n" );
914             }
915 0 0         else if (SvPROXYNODE(scalar) == NULL) {
916             xs_warn( "PmmSvContext: empty object\n" );
917             }
918             else {
919             xs_warn( "PmmSvContext: nothing was wrong!\n");
920             }
921             }
922 376           return retval;
923             }
924              
925             xmlChar*
926 152           PmmFastEncodeString( int charset,
927             const xmlChar *string,
928             const xmlChar *encoding,
929             STRLEN len )
930             {
931 152           xmlCharEncodingHandlerPtr coder = NULL;
932 152           xmlChar *retval = NULL;
933 152           xmlBufferPtr in = NULL, out = NULL;
934              
935             int i;
936             /* first check that the input is not ascii */
937             /* since we do not want to recode ascii as, say, UTF-16 */
938 152 50         if (len == 0)
939 0           len=xmlStrlen(string);
940 1935 100         for (i=0; i
941 1799 100         if(!string[i] || string[i] & 0x80) {
    100          
942             break;
943             }
944             }
945 152 100         if (i>=len) return xmlStrdup( string );
946             xs_warn("PmmFastEncodeString: string is non-ascii\n");
947              
948 16 100         if ( charset == XML_CHAR_ENCODING_ERROR){
949 8 100         if (xmlStrcmp(encoding,(const xmlChar*)"UTF-16LE")==0) {
950 4           charset = XML_CHAR_ENCODING_UTF16LE;
951 4 50         } else if (xmlStrcmp(encoding,(const xmlChar*) "UTF-16BE")==0) {
952 4           charset = XML_CHAR_ENCODING_UTF16BE;
953             }
954             }
955 16 100         if ( charset == XML_CHAR_ENCODING_UTF8 ) {
956             /* warn("use UTF8 for encoding ... %s ", string); */
957 1           return xmlStrdup( string );
958             }
959 15 100         else if ( charset == XML_CHAR_ENCODING_UTF16LE || charset == XML_CHAR_ENCODING_UTF16BE ){
    100          
960             /* detect and strip BOM, if any */
961 24 50         if (len>=2 && (char)string[0]=='\xFE' && (char)string[1]=='\xFF') {
    100          
    50          
962             xs_warn("detected BE BOM\n");
963 8           string += 2;
964 8           len -= 2;
965 8           coder = xmlGetCharEncodingHandler( XML_CHAR_ENCODING_UTF16BE );
966 4 50         } else if (len>=2 && (char)string[0]=='\xFF' && (char)string[1]=='\xFE') {
    50          
    0          
967             xs_warn("detected LE BOM\n");
968 0           string += 2;
969 0           len -= 2;
970 0           coder = xmlGetCharEncodingHandler( XML_CHAR_ENCODING_UTF16LE );
971             } else {
972 4           coder= xmlGetCharEncodingHandler( charset );
973             }
974             }
975 3 50         else if ( charset == XML_CHAR_ENCODING_ERROR ){
976             /* warn("no standard encoding %s\n", encoding); */
977 0           coder =xmlFindCharEncodingHandler( (const char *)encoding );
978             }
979 3 50         else if ( charset == XML_CHAR_ENCODING_NONE ){
980             xs_warn("PmmFastEncodeString: no encoding found\n");
981             }
982             else {
983             /* warn( "use document encoding %s (%d)", encoding, charset ); */
984 3           coder= xmlGetCharEncodingHandler( charset );
985             }
986              
987 15 50         if ( coder != NULL ) {
988             xs_warn("PmmFastEncodeString: coding machine found \n");
989 15           in = xmlBufferCreateStatic((void*)string, len);
990 15           out = xmlBufferCreate();
991 15 50         if ( xmlCharEncInFunc( coder, out, in ) >= 0 ) {
992 15           retval = xmlStrdup( out->content );
993             /* warn( "encoded string is %s" , retval); */
994             }
995             else {
996             /* warn( "b0rked encoiding!\n"); */
997             }
998              
999 15           xmlBufferFree( in );
1000 15           xmlBufferFree( out );
1001 15           xmlCharEncCloseFunc( coder );
1002             }
1003 15           return retval;
1004             }
1005              
1006             xmlChar*
1007 12           PmmFastDecodeString( int charset,
1008             const xmlChar *string,
1009             const xmlChar *encoding,
1010             STRLEN* len )
1011             {
1012 12           xmlCharEncodingHandlerPtr coder = NULL;
1013 12           xmlChar *retval = NULL;
1014 12           xmlBufferPtr in = NULL, out = NULL;
1015 12 50         if (len==NULL) return NULL;
1016 12           *len = 0;
1017 12 100         if ( charset == XML_CHAR_ENCODING_ERROR){
1018 6 100         if (xmlStrcmp(encoding,(const xmlChar*)"UTF-16LE")==0) {
1019 3           charset = XML_CHAR_ENCODING_UTF16LE;
1020 3 50         } else if (xmlStrcmp(encoding,(const xmlChar*) "UTF-16BE")==0) {
1021 3           charset = XML_CHAR_ENCODING_UTF16BE;
1022             }
1023             }
1024              
1025 12 50         if ( charset == XML_CHAR_ENCODING_UTF8 ) {
1026 0           retval = xmlStrdup( string );
1027 0           *len = xmlStrlen(retval);
1028             }
1029 12 50         else if ( charset == XML_CHAR_ENCODING_ERROR ){
1030 0           coder = xmlFindCharEncodingHandler( (const char *) encoding );
1031             }
1032 12 50         else if ( charset == XML_CHAR_ENCODING_NONE ){
1033 0           warn("PmmFastDecodeString: no encoding found\n");
1034             }
1035             else {
1036 12           coder= xmlGetCharEncodingHandler( charset );
1037             }
1038              
1039 12 50         if ( coder != NULL ) {
1040             /* warn( "do encoding %s", string ); */
1041 12           in = xmlBufferCreateStatic((void*)string,xmlStrlen(string));
1042 12           out = xmlBufferCreate();
1043 12 50         if ( xmlCharEncOutFunc( coder, out, in ) >= 0 ) {
1044 12           *len = xmlBufferLength(out);
1045 12           retval = xmlStrndup(xmlBufferContent(out), *len);
1046             }
1047             else {
1048             /* xs_warn("PmmFastEncodeString: decoding error\n"); */
1049             }
1050              
1051 12           xmlBufferFree( in );
1052 12           xmlBufferFree( out );
1053 12           xmlCharEncCloseFunc( coder );
1054             }
1055 12           return retval;
1056             }
1057              
1058             /**
1059             * encodeString returns an UTF-8 encoded String
1060             * while the encodig has the name of the encoding of string
1061             **/
1062             xmlChar*
1063 72           PmmEncodeString( const char *encoding, const xmlChar *string, STRLEN len ){
1064             xmlCharEncoding enc;
1065 72           xmlChar *ret = NULL;
1066              
1067 72 50         if ( string != NULL ) {
1068 72 50         if( encoding != NULL ) {
1069             xs_warn("PmmEncodeString: encoding to UTF-8 from:\n");
1070             xs_warn( encoding );
1071 72           enc = xmlParseCharEncoding( encoding );
1072 72           ret = PmmFastEncodeString( enc, string, (const xmlChar *)encoding,len);
1073             }
1074             else {
1075             /* if utf-8 is requested we do nothing */
1076 0           ret = xmlStrdup( string );
1077             }
1078             }
1079 72           return ret;
1080             }
1081              
1082             SV*
1083 3738           C2Sv( const xmlChar *string, const xmlChar *encoding )
1084             {
1085 3738           SV *retval = &PL_sv_undef;
1086             xmlCharEncoding enc;
1087              
1088 3738 100         if ( string != NULL ) {
1089 3700 50         if ( encoding != NULL ) {
1090 0           enc = xmlParseCharEncoding( (const char*)encoding );
1091             }
1092             else {
1093 3700           enc = 0;
1094             }
1095 3700 50         if ( enc == 0 ) {
1096             /* this happens if the encoding is "" or NULL */
1097 3700           enc = XML_CHAR_ENCODING_UTF8;
1098             }
1099              
1100 3700           retval = newSVpvn( (const char *)string, (STRLEN) xmlStrlen(string) );
1101              
1102 3700 50         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
1103             /* create an UTF8 string. */
1104             #ifdef HAVE_UTF8
1105             xs_warn("C2Sv: set UTF8-SV-flag\n");
1106 3700           SvUTF8_on(retval);
1107             #endif
1108             }
1109             }
1110              
1111 3738           return retval;
1112             }
1113              
1114             xmlChar *
1115 1524           Sv2C( SV* scalar, const xmlChar *encoding )
1116             {
1117 1524           xmlChar *retval = NULL;
1118             dTHX;
1119              
1120             xs_warn("SV2C: start!\n");
1121 1524 50         if ( scalar != NULL && SvOK(scalar) ) {
    100          
    50          
    50          
1122 1490           STRLEN len = 0;
1123 1490 100         char * t_pv =SvPV(scalar, len);
1124 1490           xmlChar* ts = NULL;
1125 1490           xmlChar* string = xmlStrdup((xmlChar*)t_pv);
1126 1490 100         if ( xmlStrlen(string) > 0 ) {
1127             xs_warn( "SV2C: no undefs\n" );
1128             #ifdef HAVE_UTF8
1129             xs_warn( "SV2C: use UTF8\n" );
1130 1412 100         if( !DO_UTF8(scalar) && encoding != NULL ) {
    50          
    100          
1131             #else
1132             if ( encoding != NULL ) {
1133             #endif
1134             xs_warn( "SV2C: domEncodeString!\n" );
1135 72           ts= PmmEncodeString( (const char *)encoding, string, len );
1136             xs_warn( "SV2C: done encoding!\n" );
1137 72 50         if ( string != NULL ) {
1138 72           xmlFree(string);
1139             }
1140 72           string=ts;
1141             }
1142             }
1143              
1144 1490           retval = xmlStrdup(string);
1145 1490 50         if (string != NULL ) {
1146 1490           xmlFree(string);
1147             }
1148             }
1149             xs_warn("SV2C: end!\n");
1150 1524           return retval;
1151             }
1152              
1153             SV*
1154 12           nodeC2Sv( const xmlChar * string, xmlNodePtr refnode )
1155             {
1156             /* this is a little helper function to avoid to much redundand
1157             code in LibXML.xs */
1158             dTHX;
1159 12           SV* retval = &PL_sv_undef;
1160 12           STRLEN len = 0;
1161 12           xmlChar * decoded = NULL;
1162              
1163 12 50         if ( refnode != NULL ) {
1164 12           xmlDocPtr real_doc = refnode->doc;
1165 12 50         if ( real_doc != NULL && real_doc->encoding != NULL ) {
    50          
1166             xs_warn( " encode node !!" );
1167             /* The following statement is to handle bad
1168             values set by XML::LibXSLT */
1169              
1170 12 50         if ( PmmNodeEncoding(real_doc) == XML_CHAR_ENCODING_NONE ) {
1171 0           SetPmmNodeEncoding(real_doc, XML_CHAR_ENCODING_UTF8);
1172             }
1173              
1174 12           decoded = PmmFastDecodeString( PmmNodeEncoding(real_doc),
1175             (const xmlChar *)string,
1176             (const xmlChar *)real_doc->encoding,
1177             &len );
1178              
1179             xs_warn( "push decoded string into SV" );
1180 12           retval = newSVpvn( (const char *)decoded, len );
1181 12           xmlFree( decoded );
1182              
1183 12 50         if ( PmmNodeEncoding( real_doc ) == XML_CHAR_ENCODING_UTF8 ) {
1184             #ifdef HAVE_UTF8
1185             xs_warn("nodeC2Sv: set UTF8-SV-flag\n");
1186 0           SvUTF8_on(retval);
1187             #endif
1188             }
1189              
1190 12           return retval;
1191             }
1192             }
1193              
1194 12           return C2Sv(string, NULL );
1195             }
1196              
1197             xmlChar *
1198 1437           nodeSv2C( SV * scalar, xmlNodePtr refnode )
1199             {
1200             /* this function requires conditionized compiling, because we
1201             request a function, that does not exists in earlier versions of
1202             perl. in this cases the library assumes, all strings are in
1203             UTF8. if a programmer likes to have the intelligent code, he
1204             needs to upgrade perl */
1205              
1206 1437 50         if ( refnode != NULL ) {
1207 1437           xmlDocPtr real_dom = refnode->doc;
1208             xs_warn("nodeSv2C: have node!\n");
1209 1437 100         if (real_dom != NULL && real_dom->encoding != NULL ) {
    100          
1210             dTHX;
1211             xs_warn("nodeSv2C: encode string!\n");
1212             /* speed things a bit up.... */
1213 138 50         if ( scalar != NULL && scalar != &PL_sv_undef ) {
    50          
1214 138           STRLEN len = 0;
1215 138 50         char * t_pv =SvPV(scalar, len);
1216 138           xmlChar* string = NULL;
1217 138 50         if ( t_pv && len > 0 ) {
    100          
1218             xs_warn( "nodeSv2C: no undefs\n" );
1219             #ifdef HAVE_UTF8
1220             xs_warn( "nodeSv2C: use UTF8\n" );
1221 122 100         if( !DO_UTF8(scalar) ) {
    50          
1222             #endif
1223             xs_warn( "nodeSv2C: domEncodeString!\n" );
1224             /* The following statement is to handle bad
1225             values set by XML::LibXSLT */
1226 80 50         if ( PmmNodeEncoding(real_dom) == XML_CHAR_ENCODING_NONE ) {
1227 0           SetPmmNodeEncoding(real_dom, XML_CHAR_ENCODING_UTF8);
1228             }
1229             /* the following allocates a new string (by xmlStrdup if no conversion is done) */
1230 80           string= PmmFastEncodeString( PmmNodeEncoding(real_dom),
1231             (xmlChar*) t_pv,
1232             (const xmlChar*)real_dom->encoding,
1233             len);
1234             xs_warn( "nodeSv2C: done!\n" );
1235             #ifdef HAVE_UTF8
1236             } else {
1237             xs_warn( "nodeSv2C: no encoding set, use UTF8!\n" );
1238             }
1239             #endif
1240             }
1241 138 100         if (string==NULL) {
1242 58           return xmlStrndup((xmlChar*)t_pv,len);
1243             } else {
1244 138           return string;
1245             }
1246             /* if ( string == NULL ) warn( "nodeSv2C: string is NULL\n" ); */
1247             }
1248             else {
1249             xs_warn( "nodeSv2C: return NULL\n" );
1250 0           return NULL;
1251             }
1252             }
1253             else {
1254             xs_warn( "nodeSv2C: document has no encoding defined! use simple SV extraction\n" );
1255             }
1256             }
1257             xs_warn("nodeSv2C: no encoding !!\n");
1258              
1259 1299           return Sv2C( scalar, NULL );
1260             }
1261              
1262             SV *
1263 0           PmmNodeToGdomeSv( xmlNodePtr node )
1264             {
1265             dTHX;
1266 0           SV * retval = &PL_sv_undef;
1267              
1268             #ifdef XML_LIBXML_GDOME_SUPPORT
1269             GdomeNode * gnode = NULL;
1270             GdomeException exc;
1271             const char * CLASS = "";
1272              
1273             if ( node != NULL ) {
1274             gnode = gdome_xml_n_mkref( node );
1275             if ( gnode != NULL ) {
1276             switch (gdome_n_nodeType(gnode, &exc)) {
1277             case GDOME_ELEMENT_NODE:
1278             CLASS = "XML::GDOME::Element";
1279             break;
1280             case GDOME_ATTRIBUTE_NODE:
1281             CLASS = "XML::GDOME::Attr";
1282             break;
1283             case GDOME_TEXT_NODE:
1284             CLASS = "XML::GDOME::Text";
1285             break;
1286             case GDOME_CDATA_SECTION_NODE:
1287             CLASS = "XML::GDOME::CDATASection";
1288             break;
1289             case GDOME_ENTITY_REFERENCE_NODE:
1290             CLASS = "XML::GDOME::EntityReference";
1291             break;
1292             case GDOME_ENTITY_NODE:
1293             CLASS = "XML::GDOME::Entity";
1294             break;
1295             case GDOME_PROCESSING_INSTRUCTION_NODE:
1296             CLASS = "XML::GDOME::ProcessingInstruction";
1297             break;
1298             case GDOME_COMMENT_NODE:
1299             CLASS = "XML::GDOME::Comment";
1300             break;
1301             case GDOME_DOCUMENT_TYPE_NODE:
1302             CLASS = "XML::GDOME::DocumentType";
1303             break;
1304             case GDOME_DOCUMENT_FRAGMENT_NODE:
1305             CLASS = "XML::GDOME::DocumentFragment";
1306             break;
1307             case GDOME_NOTATION_NODE:
1308             CLASS = "XML::GDOME::Notation";
1309             break;
1310             case GDOME_DOCUMENT_NODE:
1311             CLASS = "XML::GDOME::Document";
1312             break;
1313             default:
1314             break;
1315             }
1316              
1317             retval = NEWSV(0,0);
1318             sv_setref_pv( retval, CLASS, gnode);
1319             }
1320             }
1321             #endif
1322              
1323 0           return retval;
1324             }