| 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 | 20454 |  |  |  |  |  | PmmNodeTypeName( xmlNodePtr elem ){ | 
| 54 | 20454 |  |  |  |  |  | const char *name = "XML::LibXML::Node"; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 20454 | 50 |  |  |  |  | if ( elem != NULL ) { | 
| 57 | 20454 |  |  |  |  |  | switch ( elem->type ) { | 
| 58 |  |  |  |  |  |  | case XML_ELEMENT_NODE: | 
| 59 | 19164 |  |  |  |  |  | name = "XML::LibXML::Element"; | 
| 60 | 19164 |  |  |  |  |  | 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 | 600 |  |  |  |  |  | name = "XML::LibXML::Document"; | 
| 76 | 600 |  |  |  |  |  | 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 | 20454 |  |  |  |  |  | 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 | 57059 |  |  |  |  |  | PmmNewNode(xmlNodePtr node) | 
| 322 |  |  |  |  |  |  | { | 
| 323 | 57059 |  |  |  |  |  | ProxyNodePtr proxy = NULL; | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 57059 | 50 |  |  |  |  | if ( node == NULL ) { | 
| 326 |  |  |  |  |  |  | xs_warn( "PmmNewNode: no node found\n" ); | 
| 327 | 0 |  |  |  |  |  | return NULL; | 
| 328 |  |  |  |  |  |  | } | 
| 329 |  |  |  |  |  |  |  | 
| 330 | 57059 | 100 |  |  |  |  | if ( node->_private == NULL ) { | 
| 331 | 11104 | 100 |  |  |  |  | switch ( node->type ) { | 
| 332 |  |  |  |  |  |  | case XML_DOCUMENT_NODE: | 
| 333 |  |  |  |  |  |  | case XML_HTML_DOCUMENT_NODE: | 
| 334 |  |  |  |  |  |  | case XML_DOCB_DOCUMENT_NODE: | 
| 335 | 503 |  |  |  |  |  | proxy = (ProxyNodePtr)xmlMalloc(sizeof(struct _DocProxyNode)); | 
| 336 | 503 | 50 |  |  |  |  | if (proxy != NULL) { | 
| 337 | 503 |  |  |  |  |  | ((DocProxyNodePtr)proxy)->psvi_status = Pmm_NO_PSVI; | 
| 338 | 503 |  |  |  |  |  | SetPmmENCODING(proxy, XML_CHAR_ENCODING_NONE); | 
| 339 |  |  |  |  |  |  | } | 
| 340 | 503 |  |  |  |  |  | break; | 
| 341 |  |  |  |  |  |  | default: | 
| 342 | 10601 |  |  |  |  |  | proxy = (ProxyNodePtr)xmlMalloc(sizeof(struct _ProxyNode)); | 
| 343 | 10601 |  |  |  |  |  | break; | 
| 344 |  |  |  |  |  |  | } | 
| 345 | 11104 | 50 |  |  |  |  | if (proxy != NULL) { | 
| 346 | 11104 |  |  |  |  |  | proxy->node  = node; | 
| 347 | 11104 |  |  |  |  |  | proxy->owner   = NULL; | 
| 348 | 11104 |  |  |  |  |  | proxy->count   = 0; | 
| 349 | 11104 |  |  |  |  |  | node->_private = (void*) proxy; | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  | } | 
| 352 |  |  |  |  |  |  | else { | 
| 353 | 45955 |  |  |  |  |  | proxy = (ProxyNodePtr)node->_private; | 
| 354 |  |  |  |  |  |  | } | 
| 355 |  |  |  |  |  |  |  | 
| 356 | 57059 |  |  |  |  |  | return proxy; | 
| 357 |  |  |  |  |  |  | } | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | ProxyNodePtr | 
| 360 | 281 |  |  |  |  |  | PmmNewFragment(xmlDocPtr doc) | 
| 361 |  |  |  |  |  |  | { | 
| 362 | 281 |  |  |  |  |  | ProxyNodePtr retval = NULL; | 
| 363 | 281 |  |  |  |  |  | xmlNodePtr frag = NULL; | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | xs_warn("PmmNewFragment: new frag\n"); | 
| 366 | 281 |  |  |  |  |  | frag   = xmlNewDocFragment( doc ); | 
| 367 | 281 |  |  |  |  |  | retval = PmmNewNode(frag); | 
| 368 |  |  |  |  |  |  | /* fprintf(stderr, "REFCNT NOT incremented on frag: 0x%08.8X\n", retval); */ | 
| 369 |  |  |  |  |  |  |  | 
| 370 | 281 | 100 |  |  |  |  | if ( doc != NULL ) { | 
| 371 |  |  |  |  |  |  | xs_warn("PmmNewFragment: inc document\n"); | 
| 372 |  |  |  |  |  |  | /* under rare circumstances _private is not set correctly? */ | 
| 373 | 235 | 50 |  |  |  |  | if ( doc->_private != NULL ) { | 
| 374 |  |  |  |  |  |  | xs_warn("PmmNewFragment:   doc->_private being incremented!\n"); | 
| 375 | 235 |  |  |  |  |  | PmmREFCNT_inc(((ProxyNodePtr)doc->_private)); | 
| 376 |  |  |  |  |  |  | /* fprintf(stderr, "REFCNT incremented on doc: 0x%08.8X\n", doc->_private); */ | 
| 377 |  |  |  |  |  |  | } | 
| 378 | 235 |  |  |  |  |  | retval->owner = (xmlNodePtr)doc; | 
| 379 |  |  |  |  |  |  | } | 
| 380 |  |  |  |  |  |  |  | 
| 381 | 281 |  |  |  |  |  | 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 | 888 |  |  |  |  |  | PmmFreeNode( xmlNodePtr node ) | 
| 389 |  |  |  |  |  |  | { | 
| 390 | 888 |  |  |  |  |  | switch( node->type ) { | 
| 391 |  |  |  |  |  |  | case XML_DOCUMENT_NODE: | 
| 392 |  |  |  |  |  |  | case XML_HTML_DOCUMENT_NODE: | 
| 393 |  |  |  |  |  |  | xs_warn("PmmFreeNode: XML_DOCUMENT_NODE\n"); | 
| 394 | 503 |  |  |  |  |  | xmlFreeDoc( (xmlDocPtr) node ); | 
| 395 | 503 |  |  |  |  |  | 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 | 353 |  |  |  |  |  | xmlFreeNode( node); | 
| 422 | 353 |  |  |  |  |  | break; | 
| 423 |  |  |  |  |  |  | } | 
| 424 | 888 |  |  |  |  |  | } | 
| 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 | 31203 |  |  |  |  |  | PmmREFCNT_dec( ProxyNodePtr node ) | 
| 433 |  |  |  |  |  |  | { | 
| 434 | 31203 |  |  |  |  |  | xmlNodePtr libnode = NULL; | 
| 435 | 31203 |  |  |  |  |  | ProxyNodePtr owner = NULL; | 
| 436 | 31203 |  |  |  |  |  | int retval = 0; | 
| 437 |  |  |  |  |  |  |  | 
| 438 | 31203 | 50 |  |  |  |  | if ( node != NULL ) { | 
| 439 | 31203 |  |  |  |  |  | retval = PmmREFCNT(node)--; | 
| 440 |  |  |  |  |  |  | /* fprintf(stderr, "REFCNT on 0x%08.8X decremented to %d\n", node, PmmREFCNT(node)); */ | 
| 441 | 31203 | 50 |  |  |  |  | if ( PmmREFCNT(node) < 0 ) | 
| 442 | 0 |  |  |  |  |  | warn( "PmmREFCNT_dec: REFCNT decremented below 0 for %p!", node ); | 
| 443 | 31203 | 100 |  |  |  |  | if ( PmmREFCNT(node) <= 0 ) { | 
| 444 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec: NODE DELETION\n" ); | 
| 445 |  |  |  |  |  |  |  | 
| 446 | 11104 |  |  |  |  |  | libnode = PmmNODE( node ); | 
| 447 | 11104 | 100 |  |  |  |  | if ( libnode != NULL ) { | 
| 448 | 11103 | 50 |  |  |  |  | if ( libnode->_private != node ) { | 
| 449 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec:   lost node\n" ); | 
| 450 | 0 |  |  |  |  |  | libnode = NULL; | 
| 451 |  |  |  |  |  |  | } | 
| 452 |  |  |  |  |  |  | else { | 
| 453 | 11103 |  |  |  |  |  | libnode->_private = NULL; | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  | } | 
| 456 |  |  |  |  |  |  |  | 
| 457 | 11104 |  |  |  |  |  | PmmNODE( node ) = NULL; | 
| 458 | 11104 | 100 |  |  |  |  | if ( PmmOWNER(node) && PmmOWNERPO(node) ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec:   DOC NODE!\n" ); | 
| 460 | 10482 | 50 |  |  |  |  | owner = PmmOWNERPO(node); | 
|  |  | 50 |  |  |  |  |  | 
| 461 | 10482 |  |  |  |  |  | PmmOWNER( node ) = NULL; | 
| 462 | 10482 | 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 | 266 |  |  |  |  |  | PmmFreeNode( libnode ); | 
| 468 |  |  |  |  |  |  | } | 
| 469 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec:   decrease owner\n" ); | 
| 470 | 10482 |  |  |  |  |  | PmmREFCNT_dec( owner ); | 
| 471 |  |  |  |  |  |  | } | 
| 472 | 622 | 50 |  |  |  |  | else if ( libnode != NULL ) { | 
| 473 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec:   STANDALONE REAL DELETE\n" ); | 
| 474 |  |  |  |  |  |  |  | 
| 475 | 622 |  |  |  |  |  | PmmFreeNode( libnode ); | 
| 476 |  |  |  |  |  |  | } | 
| 477 |  |  |  |  |  |  | else { | 
| 478 |  |  |  |  |  |  | xs_warn( "PmmREFCNT_dec:   NO OWNER\n" ); | 
| 479 |  |  |  |  |  |  | } | 
| 480 | 31203 |  |  |  |  |  | xmlFree( node ); | 
| 481 |  |  |  |  |  |  | } | 
| 482 |  |  |  |  |  |  | } | 
| 483 |  |  |  |  |  |  | else { | 
| 484 |  |  |  |  |  |  | xs_warn("PmmREFCNT_dec: lost node\n" ); | 
| 485 |  |  |  |  |  |  | } | 
| 486 | 31203 |  |  |  |  |  | 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 | 20464 |  |  |  |  |  | PmmNodeToSv( xmlNodePtr node, ProxyNodePtr owner ) | 
| 504 |  |  |  |  |  |  | { | 
| 505 | 20464 |  |  |  |  |  | ProxyNodePtr dfProxy= NULL; | 
| 506 |  |  |  |  |  |  | dTHX; | 
| 507 | 20464 |  |  |  |  |  | SV * retval = &PL_sv_undef; | 
| 508 | 20464 |  |  |  |  |  | const char * CLASS = "XML::LibXML::Node"; | 
| 509 |  |  |  |  |  |  |  | 
| 510 | 20464 | 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 | 20452 |  |  |  |  |  | CLASS = PmmNodeTypeName( node ); | 
| 517 |  |  |  |  |  |  | xs_warn("PmmNodeToSv: return new perl node of class:\n"); | 
| 518 |  |  |  |  |  |  | xs_warn( CLASS ); | 
| 519 |  |  |  |  |  |  |  | 
| 520 | 20452 | 100 |  |  |  |  | if ( node->_private != NULL ) { | 
| 521 | 9630 |  |  |  |  |  | dfProxy = PmmNewNode(node); | 
| 522 |  |  |  |  |  |  | /* fprintf(stderr, " at 0x%08.8X\n", dfProxy); */ | 
| 523 |  |  |  |  |  |  | } | 
| 524 |  |  |  |  |  |  | else { | 
| 525 | 10822 |  |  |  |  |  | dfProxy = PmmNewNode(node); | 
| 526 |  |  |  |  |  |  | /* fprintf(stderr, " at 0x%08.8X\n", dfProxy); */ | 
| 527 | 10822 | 50 |  |  |  |  | if ( dfProxy != NULL ) { | 
| 528 | 10822 | 100 |  |  |  |  | if ( owner != NULL ) { | 
| 529 | 10251 |  |  |  |  |  | dfProxy->owner = PmmNODE( owner ); | 
| 530 | 10251 |  |  |  |  |  | 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 | 20452 |  |  |  |  |  | retval = NEWSV(0,0); | 
| 543 | 20452 |  |  |  |  |  | sv_setref_pv( retval, CLASS, (void*)dfProxy ); | 
| 544 |  |  |  |  |  |  | #ifdef XML_LIBXML_THREADS | 
| 545 |  |  |  |  |  |  | if( PmmUSEREGISTRY ) | 
| 546 |  |  |  |  |  |  | PmmRegistryREFCNT_inc(dfProxy); | 
| 547 |  |  |  |  |  |  | #endif | 
| 548 | 20452 |  |  |  |  |  | PmmREFCNT_inc(dfProxy); | 
| 549 |  |  |  |  |  |  | /* fprintf(stderr, "REFCNT incremented on node: 0x%08.8X\n", dfProxy); */ | 
| 550 |  |  |  |  |  |  |  | 
| 551 | 20452 | 100 |  |  |  |  | switch ( node->type ) { | 
| 552 |  |  |  |  |  |  | case XML_DOCUMENT_NODE: | 
| 553 |  |  |  |  |  |  | case XML_HTML_DOCUMENT_NODE: | 
| 554 |  |  |  |  |  |  | case XML_DOCB_DOCUMENT_NODE: | 
| 555 | 600 | 100 |  |  |  |  | if ( ((xmlDocPtr)node)->encoding != NULL ) { | 
| 556 | 73 |  |  |  |  |  | SetPmmENCODING(dfProxy, (int)xmlParseCharEncoding( (const char*)((xmlDocPtr)node)->encoding )); | 
| 557 |  |  |  |  |  |  | } | 
| 558 | 600 |  |  |  |  |  | break; | 
| 559 |  |  |  |  |  |  | default: | 
| 560 | 20452 |  |  |  |  |  | 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 | 20464 |  |  |  |  |  | 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 | 19709 |  |  |  |  |  | PmmSvNodeExt( SV* perlnode, int copy ) | 
| 619 |  |  |  |  |  |  | { | 
| 620 | 19709 |  |  |  |  |  | xmlNodePtr retval = NULL; | 
| 621 | 19709 |  |  |  |  |  | ProxyNodePtr proxy = NULL; | 
| 622 |  |  |  |  |  |  | dTHX; | 
| 623 |  |  |  |  |  |  |  | 
| 624 | 19709 | 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 | 19697 | 100 |  |  |  |  | if ( sv_derived_from(perlnode, "XML::LibXML::Node")  ) { | 
| 631 | 19695 | 50 |  |  |  |  | proxy = SvPROXYNODE(perlnode); | 
| 632 | 19695 | 50 |  |  |  |  | if ( proxy != NULL ) { | 
| 633 |  |  |  |  |  |  | xs_warn( "PmmSvNodeExt:   is a xmlNodePtr structure\n" ); | 
| 634 | 19695 |  |  |  |  |  | retval = PmmNODE( proxy ) ; | 
| 635 |  |  |  |  |  |  | } | 
| 636 |  |  |  |  |  |  |  | 
| 637 | 19695 | 100 |  |  |  |  | if ( retval != NULL | 
| 638 | 19694 | 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 | 19709 |  |  |  |  |  | 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 | 272 |  |  |  |  |  | PmmFixOwner( ProxyNodePtr nodetofix, ProxyNodePtr parent ) | 
| 714 |  |  |  |  |  |  | { | 
| 715 | 272 |  |  |  |  |  | ProxyNodePtr oldParent = NULL; | 
| 716 |  |  |  |  |  |  |  | 
| 717 | 272 | 50 |  |  |  |  | if ( nodetofix != NULL ) { | 
| 718 | 272 | 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 | 272 |  |  |  |  |  | break; | 
| 728 |  |  |  |  |  |  | } | 
| 729 |  |  |  |  |  |  |  | 
| 730 | 272 | 100 |  |  |  |  | if ( PmmOWNER(nodetofix) != NULL ) { | 
| 731 | 270 | 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 | 272 | 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 | 263 | 100 |  |  |  |  | if ( parent && parent != nodetofix ){ | 
|  |  | 50 |  |  |  |  |  | 
| 743 | 257 |  |  |  |  |  | PmmOWNER(nodetofix) = PmmNODE(parent); | 
| 744 | 257 |  |  |  |  |  | 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 | 263 | 100 |  |  |  |  | if ( oldParent != NULL && oldParent != nodetofix ) | 
|  |  | 50 |  |  |  |  |  | 
| 752 | 261 |  |  |  |  |  | PmmREFCNT_dec(oldParent); | 
| 753 |  |  |  |  |  |  |  | 
| 754 | 263 | 100 |  |  |  |  | if ( PmmNODE(nodetofix)->type != XML_ATTRIBUTE_NODE | 
| 755 | 249 | 100 |  |  |  |  | && PmmNODE(nodetofix)->type != XML_DTD_NODE | 
| 756 | 237 | 100 |  |  |  |  | && PmmNODE(nodetofix)->properties != NULL ) { | 
| 757 | 8 |  |  |  |  |  | PmmFixOwnerList( (xmlNodePtr)PmmNODE(nodetofix)->properties, | 
| 758 |  |  |  |  |  |  | parent ); | 
| 759 |  |  |  |  |  |  | } | 
| 760 |  |  |  |  |  |  |  | 
| 761 | 263 | 100 |  |  |  |  | if ( parent == NULL || PmmNODE(nodetofix)->parent == NULL ) { | 
|  |  | 100 |  |  |  |  |  | 
| 762 |  |  |  |  |  |  | /* fix to self */ | 
| 763 | 11 |  |  |  |  |  | parent = nodetofix; | 
| 764 |  |  |  |  |  |  | } | 
| 765 |  |  |  |  |  |  |  | 
| 766 | 263 |  |  |  |  |  | PmmFixOwnerList(PmmNODE(nodetofix)->children, parent); | 
| 767 |  |  |  |  |  |  | } | 
| 768 |  |  |  |  |  |  | else { | 
| 769 |  |  |  |  |  |  | xs_warn( "PmmFixOwner: node doesn't need to get fixed\n" ); | 
| 770 |  |  |  |  |  |  | } | 
| 771 | 272 |  |  |  |  |  | return(1); | 
| 772 |  |  |  |  |  |  | } | 
| 773 | 0 |  |  |  |  |  | return(0); | 
| 774 |  |  |  |  |  |  | } | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | void | 
| 777 | 374 |  |  |  |  |  | PmmFixOwnerList( xmlNodePtr list, ProxyNodePtr parent ) | 
| 778 |  |  |  |  |  |  | { | 
| 779 | 374 | 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 | 374 |  |  |  |  |  | } | 
| 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 | 377 |  |  |  |  |  | PmmSvContext( SV * scalar ) | 
| 897 |  |  |  |  |  |  | { | 
| 898 | 377 |  |  |  |  |  | xmlParserCtxtPtr retval = NULL; | 
| 899 |  |  |  |  |  |  | dTHX; | 
| 900 |  |  |  |  |  |  |  | 
| 901 | 377 | 50 |  |  |  |  | if ( scalar != NULL | 
| 902 | 377 | 50 |  |  |  |  | && scalar != &PL_sv_undef | 
| 903 | 377 | 50 |  |  |  |  | && sv_isa( scalar, "XML::LibXML::ParserContext" ) | 
| 904 | 377 | 50 |  |  |  |  | && SvPROXYNODE(scalar) != NULL  ) { | 
|  |  | 50 |  |  |  |  |  | 
| 905 | 377 | 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 | 377 |  |  |  |  |  | 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 | 1624 |  |  |  |  |  | C2Sv( const xmlChar *string, const xmlChar *encoding ) | 
| 1084 |  |  |  |  |  |  | { | 
| 1085 | 1624 |  |  |  |  |  | SV *retval = &PL_sv_undef; | 
| 1086 |  |  |  |  |  |  | xmlCharEncoding enc; | 
| 1087 |  |  |  |  |  |  |  | 
| 1088 | 1624 | 100 |  |  |  |  | if ( string != NULL ) { | 
| 1089 | 1586 | 50 |  |  |  |  | if ( encoding != NULL ) { | 
| 1090 | 0 |  |  |  |  |  | enc = xmlParseCharEncoding( (const char*)encoding ); | 
| 1091 |  |  |  |  |  |  | } | 
| 1092 |  |  |  |  |  |  | else { | 
| 1093 | 1586 |  |  |  |  |  | enc = 0; | 
| 1094 |  |  |  |  |  |  | } | 
| 1095 | 1586 | 50 |  |  |  |  | if ( enc == 0 ) { | 
| 1096 |  |  |  |  |  |  | /* this happens if the encoding is "" or NULL */ | 
| 1097 | 1586 |  |  |  |  |  | enc = XML_CHAR_ENCODING_UTF8; | 
| 1098 |  |  |  |  |  |  | } | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 | 1586 |  |  |  |  |  | retval = newSVpvn( (const char *)string, (STRLEN) xmlStrlen(string) ); | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 | 1586 | 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 | 1586 |  |  |  |  |  | SvUTF8_on(retval); | 
| 1107 |  |  |  |  |  |  | #endif | 
| 1108 |  |  |  |  |  |  | } | 
| 1109 |  |  |  |  |  |  | } | 
| 1110 |  |  |  |  |  |  |  | 
| 1111 | 1624 |  |  |  |  |  | return retval; | 
| 1112 |  |  |  |  |  |  | } | 
| 1113 |  |  |  |  |  |  |  | 
| 1114 |  |  |  |  |  |  | xmlChar * | 
| 1115 | 1533 |  |  |  |  |  | Sv2C( SV* scalar, const xmlChar *encoding ) | 
| 1116 |  |  |  |  |  |  | { | 
| 1117 | 1533 |  |  |  |  |  | xmlChar *retval = NULL; | 
| 1118 |  |  |  |  |  |  | dTHX; | 
| 1119 |  |  |  |  |  |  |  | 
| 1120 |  |  |  |  |  |  | xs_warn("SV2C: start!\n"); | 
| 1121 | 1533 | 100 |  |  |  |  | SvGETMAGIC(scalar); | 
|  |  | 50 |  |  |  |  |  | 
| 1122 | 1533 | 50 |  |  |  |  | if ( scalar != NULL && SvOK(scalar) ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 1123 | 1499 |  |  |  |  |  | STRLEN len = 0; | 
| 1124 | 1499 | 100 |  |  |  |  | char * t_pv =SvPV(scalar, len); | 
| 1125 | 1499 |  |  |  |  |  | xmlChar* ts = NULL; | 
| 1126 | 1499 |  |  |  |  |  | xmlChar* string = xmlStrdup((xmlChar*)t_pv); | 
| 1127 | 1499 | 100 |  |  |  |  | if ( xmlStrlen(string) > 0 ) { | 
| 1128 |  |  |  |  |  |  | xs_warn( "SV2C:   no undefs\n" ); | 
| 1129 |  |  |  |  |  |  | #ifdef HAVE_UTF8 | 
| 1130 |  |  |  |  |  |  | xs_warn( "SV2C:   use UTF8\n" ); | 
| 1131 | 1421 | 100 |  |  |  |  | if( !DO_UTF8(scalar) && encoding != NULL ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | #else | 
| 1133 |  |  |  |  |  |  | if ( encoding != NULL ) { | 
| 1134 |  |  |  |  |  |  | #endif | 
| 1135 |  |  |  |  |  |  | xs_warn( "SV2C:   domEncodeString!\n" ); | 
| 1136 | 72 |  |  |  |  |  | ts= PmmEncodeString( (const char *)encoding, string, len ); | 
| 1137 |  |  |  |  |  |  | xs_warn( "SV2C:   done encoding!\n" ); | 
| 1138 | 72 | 50 |  |  |  |  | if ( string != NULL ) { | 
| 1139 | 72 |  |  |  |  |  | xmlFree(string); | 
| 1140 |  |  |  |  |  |  | } | 
| 1141 | 72 |  |  |  |  |  | string=ts; | 
| 1142 |  |  |  |  |  |  | } | 
| 1143 |  |  |  |  |  |  | } | 
| 1144 |  |  |  |  |  |  |  | 
| 1145 | 1499 |  |  |  |  |  | retval = xmlStrdup(string); | 
| 1146 | 1499 | 50 |  |  |  |  | if (string != NULL ) { | 
| 1147 | 1499 |  |  |  |  |  | xmlFree(string); | 
| 1148 |  |  |  |  |  |  | } | 
| 1149 |  |  |  |  |  |  | } | 
| 1150 |  |  |  |  |  |  | xs_warn("SV2C: end!\n"); | 
| 1151 | 1533 |  |  |  |  |  | return retval; | 
| 1152 |  |  |  |  |  |  | } | 
| 1153 |  |  |  |  |  |  |  | 
| 1154 |  |  |  |  |  |  | SV* | 
| 1155 | 12 |  |  |  |  |  | nodeC2Sv( const xmlChar * string,  xmlNodePtr refnode ) | 
| 1156 |  |  |  |  |  |  | { | 
| 1157 |  |  |  |  |  |  | /* this is a little helper function to avoid to much redundand | 
| 1158 |  |  |  |  |  |  | code in LibXML.xs */ | 
| 1159 |  |  |  |  |  |  | dTHX; | 
| 1160 | 12 |  |  |  |  |  | SV* retval = &PL_sv_undef; | 
| 1161 | 12 |  |  |  |  |  | STRLEN len = 0; | 
| 1162 | 12 |  |  |  |  |  | xmlChar * decoded = NULL; | 
| 1163 |  |  |  |  |  |  |  | 
| 1164 | 12 | 50 |  |  |  |  | if ( refnode != NULL ) { | 
| 1165 | 12 |  |  |  |  |  | xmlDocPtr real_doc = refnode->doc; | 
| 1166 | 12 | 50 |  |  |  |  | if ( real_doc != NULL && real_doc->encoding != NULL ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1167 |  |  |  |  |  |  | xs_warn( " encode node !!" ); | 
| 1168 |  |  |  |  |  |  | /* The following statement is to handle bad | 
| 1169 |  |  |  |  |  |  | values set by XML::LibXSLT */ | 
| 1170 |  |  |  |  |  |  |  | 
| 1171 | 12 | 50 |  |  |  |  | if ( PmmNodeEncoding(real_doc) == XML_CHAR_ENCODING_NONE ) { | 
| 1172 | 0 |  |  |  |  |  | SetPmmNodeEncoding(real_doc, XML_CHAR_ENCODING_UTF8); | 
| 1173 |  |  |  |  |  |  | } | 
| 1174 |  |  |  |  |  |  |  | 
| 1175 | 12 |  |  |  |  |  | decoded = PmmFastDecodeString( PmmNodeEncoding(real_doc), | 
| 1176 |  |  |  |  |  |  | (const xmlChar *)string, | 
| 1177 |  |  |  |  |  |  | (const xmlChar *)real_doc->encoding, | 
| 1178 |  |  |  |  |  |  | &len ); | 
| 1179 |  |  |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | xs_warn( "push decoded string into SV" ); | 
| 1181 | 12 |  |  |  |  |  | retval = newSVpvn( (const char *)decoded, len ); | 
| 1182 | 12 |  |  |  |  |  | xmlFree( decoded ); | 
| 1183 |  |  |  |  |  |  |  | 
| 1184 | 12 | 50 |  |  |  |  | if ( PmmNodeEncoding( real_doc ) == XML_CHAR_ENCODING_UTF8 ) { | 
| 1185 |  |  |  |  |  |  | #ifdef HAVE_UTF8 | 
| 1186 |  |  |  |  |  |  | xs_warn("nodeC2Sv: set UTF8-SV-flag\n"); | 
| 1187 | 0 |  |  |  |  |  | SvUTF8_on(retval); | 
| 1188 |  |  |  |  |  |  | #endif | 
| 1189 |  |  |  |  |  |  | } | 
| 1190 |  |  |  |  |  |  |  | 
| 1191 | 12 |  |  |  |  |  | return retval; | 
| 1192 |  |  |  |  |  |  | } | 
| 1193 |  |  |  |  |  |  | } | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 | 12 |  |  |  |  |  | return C2Sv(string, NULL ); | 
| 1196 |  |  |  |  |  |  | } | 
| 1197 |  |  |  |  |  |  |  | 
| 1198 |  |  |  |  |  |  | xmlChar * | 
| 1199 | 1443 |  |  |  |  |  | nodeSv2C( SV * scalar, xmlNodePtr refnode ) | 
| 1200 |  |  |  |  |  |  | { | 
| 1201 |  |  |  |  |  |  | /* this function requires conditionized compiling, because we | 
| 1202 |  |  |  |  |  |  | request a function, that does not exists in earlier versions of | 
| 1203 |  |  |  |  |  |  | perl. in this cases the library assumes, all strings are in | 
| 1204 |  |  |  |  |  |  | UTF8. if a programmer likes to have the intelligent code, he | 
| 1205 |  |  |  |  |  |  | needs to upgrade perl */ | 
| 1206 |  |  |  |  |  |  |  | 
| 1207 | 1443 | 50 |  |  |  |  | if ( refnode != NULL ) { | 
| 1208 | 1443 |  |  |  |  |  | xmlDocPtr real_dom = refnode->doc; | 
| 1209 |  |  |  |  |  |  | xs_warn("nodeSv2C: have node!\n"); | 
| 1210 | 1443 | 100 |  |  |  |  | if (real_dom != NULL && real_dom->encoding != NULL ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1211 |  |  |  |  |  |  | dTHX; | 
| 1212 |  |  |  |  |  |  | xs_warn("nodeSv2C:   encode string!\n"); | 
| 1213 |  |  |  |  |  |  | /*  speed things a bit up.... */ | 
| 1214 | 138 | 50 |  |  |  |  | if ( scalar != NULL && scalar != &PL_sv_undef ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1215 | 138 |  |  |  |  |  | STRLEN len = 0; | 
| 1216 | 138 | 50 |  |  |  |  | char * t_pv =SvPV(scalar, len); | 
| 1217 | 138 |  |  |  |  |  | xmlChar* string = NULL; | 
| 1218 | 138 | 50 |  |  |  |  | if ( t_pv && len > 0 ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1219 |  |  |  |  |  |  | xs_warn( "nodeSv2C:   no undefs\n" ); | 
| 1220 |  |  |  |  |  |  | #ifdef HAVE_UTF8 | 
| 1221 |  |  |  |  |  |  | xs_warn( "nodeSv2C:   use UTF8\n" ); | 
| 1222 | 122 | 100 |  |  |  |  | if( !DO_UTF8(scalar) ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1223 |  |  |  |  |  |  | #endif | 
| 1224 |  |  |  |  |  |  | xs_warn( "nodeSv2C:     domEncodeString!\n" ); | 
| 1225 |  |  |  |  |  |  | /* The following statement is to handle bad | 
| 1226 |  |  |  |  |  |  | values set by XML::LibXSLT */ | 
| 1227 | 80 | 50 |  |  |  |  | if ( PmmNodeEncoding(real_dom) == XML_CHAR_ENCODING_NONE ) { | 
| 1228 | 0 |  |  |  |  |  | SetPmmNodeEncoding(real_dom, XML_CHAR_ENCODING_UTF8); | 
| 1229 |  |  |  |  |  |  | } | 
| 1230 |  |  |  |  |  |  | /* the following allocates a new string (by xmlStrdup if no conversion is done) */ | 
| 1231 | 80 |  |  |  |  |  | string= PmmFastEncodeString( PmmNodeEncoding(real_dom), | 
| 1232 |  |  |  |  |  |  | (xmlChar*) t_pv, | 
| 1233 |  |  |  |  |  |  | (const xmlChar*)real_dom->encoding, | 
| 1234 |  |  |  |  |  |  | len); | 
| 1235 |  |  |  |  |  |  | xs_warn( "nodeSv2C:     done!\n" ); | 
| 1236 |  |  |  |  |  |  | #ifdef HAVE_UTF8 | 
| 1237 |  |  |  |  |  |  | } else { | 
| 1238 |  |  |  |  |  |  | xs_warn( "nodeSv2C:   no encoding set, use UTF8!\n" ); | 
| 1239 |  |  |  |  |  |  | } | 
| 1240 |  |  |  |  |  |  | #endif | 
| 1241 |  |  |  |  |  |  | } | 
| 1242 | 138 | 100 |  |  |  |  | if (string==NULL) { | 
| 1243 | 58 |  |  |  |  |  | return xmlStrndup((xmlChar*)t_pv,len); | 
| 1244 |  |  |  |  |  |  | } else { | 
| 1245 | 138 |  |  |  |  |  | return string; | 
| 1246 |  |  |  |  |  |  | } | 
| 1247 |  |  |  |  |  |  | /* if ( string == NULL ) warn( "nodeSv2C:     string is NULL\n" ); */ | 
| 1248 |  |  |  |  |  |  | } | 
| 1249 |  |  |  |  |  |  | else { | 
| 1250 |  |  |  |  |  |  | xs_warn( "nodeSv2C:   return NULL\n" ); | 
| 1251 | 0 |  |  |  |  |  | return NULL; | 
| 1252 |  |  |  |  |  |  | } | 
| 1253 |  |  |  |  |  |  | } | 
| 1254 |  |  |  |  |  |  | else { | 
| 1255 |  |  |  |  |  |  | xs_warn( "nodeSv2C:   document has no encoding defined! use simple SV extraction\n" ); | 
| 1256 |  |  |  |  |  |  | } | 
| 1257 |  |  |  |  |  |  | } | 
| 1258 |  |  |  |  |  |  | xs_warn("nodeSv2C: no encoding !!\n"); | 
| 1259 |  |  |  |  |  |  |  | 
| 1260 | 1305 |  |  |  |  |  | return  Sv2C( scalar, NULL ); | 
| 1261 |  |  |  |  |  |  | } | 
| 1262 |  |  |  |  |  |  |  | 
| 1263 |  |  |  |  |  |  | SV * | 
| 1264 | 0 |  |  |  |  |  | PmmNodeToGdomeSv( xmlNodePtr node ) | 
| 1265 |  |  |  |  |  |  | { | 
| 1266 |  |  |  |  |  |  | dTHX; | 
| 1267 | 0 |  |  |  |  |  | SV * retval = &PL_sv_undef; | 
| 1268 |  |  |  |  |  |  |  | 
| 1269 |  |  |  |  |  |  | #ifdef XML_LIBXML_GDOME_SUPPORT | 
| 1270 |  |  |  |  |  |  | GdomeNode * gnode = NULL; | 
| 1271 |  |  |  |  |  |  | GdomeException exc; | 
| 1272 |  |  |  |  |  |  | const char * CLASS = ""; | 
| 1273 |  |  |  |  |  |  |  | 
| 1274 |  |  |  |  |  |  | if ( node != NULL ) { | 
| 1275 |  |  |  |  |  |  | gnode = gdome_xml_n_mkref( node ); | 
| 1276 |  |  |  |  |  |  | if ( gnode != NULL ) { | 
| 1277 |  |  |  |  |  |  | switch (gdome_n_nodeType(gnode, &exc)) { | 
| 1278 |  |  |  |  |  |  | case GDOME_ELEMENT_NODE: | 
| 1279 |  |  |  |  |  |  | CLASS = "XML::GDOME::Element"; | 
| 1280 |  |  |  |  |  |  | break; | 
| 1281 |  |  |  |  |  |  | case GDOME_ATTRIBUTE_NODE: | 
| 1282 |  |  |  |  |  |  | CLASS = "XML::GDOME::Attr"; | 
| 1283 |  |  |  |  |  |  | break; | 
| 1284 |  |  |  |  |  |  | case GDOME_TEXT_NODE: | 
| 1285 |  |  |  |  |  |  | CLASS = "XML::GDOME::Text"; | 
| 1286 |  |  |  |  |  |  | break; | 
| 1287 |  |  |  |  |  |  | case GDOME_CDATA_SECTION_NODE: | 
| 1288 |  |  |  |  |  |  | CLASS = "XML::GDOME::CDATASection"; | 
| 1289 |  |  |  |  |  |  | break; | 
| 1290 |  |  |  |  |  |  | case GDOME_ENTITY_REFERENCE_NODE: | 
| 1291 |  |  |  |  |  |  | CLASS = "XML::GDOME::EntityReference"; | 
| 1292 |  |  |  |  |  |  | break; | 
| 1293 |  |  |  |  |  |  | case GDOME_ENTITY_NODE: | 
| 1294 |  |  |  |  |  |  | CLASS = "XML::GDOME::Entity"; | 
| 1295 |  |  |  |  |  |  | break; | 
| 1296 |  |  |  |  |  |  | case GDOME_PROCESSING_INSTRUCTION_NODE: | 
| 1297 |  |  |  |  |  |  | CLASS = "XML::GDOME::ProcessingInstruction"; | 
| 1298 |  |  |  |  |  |  | break; | 
| 1299 |  |  |  |  |  |  | case GDOME_COMMENT_NODE: | 
| 1300 |  |  |  |  |  |  | CLASS = "XML::GDOME::Comment"; | 
| 1301 |  |  |  |  |  |  | break; | 
| 1302 |  |  |  |  |  |  | case GDOME_DOCUMENT_TYPE_NODE: | 
| 1303 |  |  |  |  |  |  | CLASS = "XML::GDOME::DocumentType"; | 
| 1304 |  |  |  |  |  |  | break; | 
| 1305 |  |  |  |  |  |  | case GDOME_DOCUMENT_FRAGMENT_NODE: | 
| 1306 |  |  |  |  |  |  | CLASS = "XML::GDOME::DocumentFragment"; | 
| 1307 |  |  |  |  |  |  | break; | 
| 1308 |  |  |  |  |  |  | case GDOME_NOTATION_NODE: | 
| 1309 |  |  |  |  |  |  | CLASS = "XML::GDOME::Notation"; | 
| 1310 |  |  |  |  |  |  | break; | 
| 1311 |  |  |  |  |  |  | case GDOME_DOCUMENT_NODE: | 
| 1312 |  |  |  |  |  |  | CLASS = "XML::GDOME::Document"; | 
| 1313 |  |  |  |  |  |  | break; | 
| 1314 |  |  |  |  |  |  | default: | 
| 1315 |  |  |  |  |  |  | break; | 
| 1316 |  |  |  |  |  |  | } | 
| 1317 |  |  |  |  |  |  |  | 
| 1318 |  |  |  |  |  |  | retval = NEWSV(0,0); | 
| 1319 |  |  |  |  |  |  | sv_setref_pv( retval, CLASS, gnode); | 
| 1320 |  |  |  |  |  |  | } | 
| 1321 |  |  |  |  |  |  | } | 
| 1322 |  |  |  |  |  |  | #endif | 
| 1323 |  |  |  |  |  |  |  | 
| 1324 | 0 |  |  |  |  |  | return retval; | 
| 1325 |  |  |  |  |  |  | } |