xref: /aosp_15_r20/external/libxml2/python/types.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1 /*
2  * types.c: converter functions between the internal representation
3  *          and the Python objects
4  *
5  * See Copyright for the status of this software.
6  *
7  * [email protected]
8  */
9 #include "libxml_wrap.h"
10 #include <libxml/xpathInternals.h>
11 #include <string.h>
12 
13 #if PY_MAJOR_VERSION >= 3
14 #define PY_IMPORT_STRING_SIZE PyUnicode_FromStringAndSize
15 #define PY_IMPORT_STRING PyUnicode_FromString
16 #define PY_IMPORT_INT PyLong_FromLong
17 #else
18 #define PY_IMPORT_STRING_SIZE PyString_FromStringAndSize
19 #define PY_IMPORT_STRING PyString_FromString
20 #define PY_IMPORT_INT PyInt_FromLong
21 #endif
22 
23 #if PY_MAJOR_VERSION >= 3
24 #include <stdio.h>
25 #include <stdint.h>
26 
27 #ifdef _WIN32
28 
29 #include <windows.h>
30 #include <crtdbg.h>
31 
32 /* Taken from info on MSDN site, as we may not have the Windows WDK/DDK headers */
33 typedef struct _IO_STATUS_BLOCK {
34   union {
35     NTSTATUS Status;
36     PVOID    Pointer;
37   } DUMMYUNIONNAME;
38   ULONG_PTR Information;
39 } IO_STATUS_BLOCK;
40 
41 typedef struct _FILE_ACCESS_INFORMATION {
42   ACCESS_MASK AccessFlags;
43 } FILE_ACCESS_INFORMATION;
44 
45 typedef NTSTATUS (*t_NtQueryInformationFile) (HANDLE           FileHandle,
46                                               IO_STATUS_BLOCK *IoStatusBlock,
47                                               PVOID            FileInformation,
48                                               ULONG            Length,
49                                               int              FileInformationClass); /* this is an Enum */
50 
51 #if (defined (_MSC_VER) && _MSC_VER >= 1400)
52 /*
53  * This is the (empty) invalid parameter handler
54  * that is used for Visual C++ 2005 (and later) builds
55  * so that we can use this instead of the system automatically
56  * aborting the process.
57  *
58  * This is necessary as we use _get_oshandle() to check the validity
59  * of the file descriptors as we close them, so when an invalid file
60  * descriptor is passed into that function as we check on it, we get
61  * -1 as the result, instead of the gspawn helper program aborting.
62  *
63  * Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
64  * for an explanation on this.
65  */
66 void
myInvalidParameterHandler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)67 myInvalidParameterHandler(const wchar_t *expression,
68                           const wchar_t *function,
69                           const wchar_t *file,
70                           unsigned int   line,
71                           uintptr_t      pReserved)
72 {
73 }
74 #endif
75 #else
76 #include <unistd.h>
77 #include <fcntl.h>
78 #endif
79 
80 FILE *
libxml_PyFileGet(PyObject * f)81 libxml_PyFileGet(PyObject *f) {
82     FILE *res;
83     const char *mode;
84     int fd = PyObject_AsFileDescriptor(f);
85 
86 #ifdef _WIN32
87     intptr_t w_fh = -1;
88     HMODULE hntdll = NULL;
89     IO_STATUS_BLOCK status_block;
90     FILE_ACCESS_INFORMATION ai;
91     t_NtQueryInformationFile NtQueryInformationFile;
92     BOOL is_read = FALSE;
93     BOOL is_write = FALSE;
94     BOOL is_append = FALSE;
95 
96 #if (defined (_MSC_VER) && _MSC_VER >= 1400)
97     /* set up our empty invalid parameter handler */
98     _invalid_parameter_handler oldHandler, newHandler;
99     newHandler = myInvalidParameterHandler;
100     oldHandler = _set_invalid_parameter_handler(newHandler);
101 
102     /* Disable the message box for assertions. */
103     _CrtSetReportMode(_CRT_ASSERT, 0);
104 #endif
105 
106     w_fh = _get_osfhandle(fd);
107 
108     if (w_fh == -1)
109         return(NULL);
110 
111     hntdll = GetModuleHandleW(L"ntdll.dll");
112 
113     if (hntdll == NULL)
114         return(NULL);
115 XML_IGNORE_FPTR_CAST_WARNINGS
116     NtQueryInformationFile = (t_NtQueryInformationFile)GetProcAddress(hntdll, "NtQueryInformationFile");
117 XML_POP_WARNINGS
118 
119     if (NtQueryInformationFile != NULL &&
120         (NtQueryInformationFile((HANDLE)w_fh,
121                                &status_block,
122                                &ai,
123                                 sizeof(FILE_ACCESS_INFORMATION),
124                                 8) == 0)) /* 8 means "FileAccessInformation" */
125         {
126             if (ai.AccessFlags & FILE_READ_DATA)
127                 is_read = TRUE;
128             if (ai.AccessFlags & FILE_WRITE_DATA)
129                 is_write = TRUE;
130             if (ai.AccessFlags & FILE_APPEND_DATA)
131                 is_append = TRUE;
132 
133             if (is_write) {
134                 if (is_read) {
135                     if (is_append)
136                         mode = "a+";
137                     else
138                         mode = "rw";
139                 } else {
140                     if (is_append)
141                         mode = "a";
142                     else
143                         mode = "w";
144                 }
145             } else {
146                 if (is_append)
147                     mode = "r+";
148                 else
149                     mode = "r";
150             }
151         }
152 
153     FreeLibrary(hntdll);
154 
155     if (!is_write && !is_read) /* also happens if we did not load or run NtQueryInformationFile() successfully */
156         return(NULL);
157 #else
158     int flags;
159 
160     /*
161      * macOS returns O_RDWR for standard streams, but fails to write to
162      * stdout or stderr when opened with fdopen(dup_fd, "rw").
163      */
164     switch (fd) {
165         case STDIN_FILENO:
166             mode = "r";
167             break;
168         case STDOUT_FILENO:
169         case STDERR_FILENO:
170             mode = "w";
171             break;
172         default:
173             /*
174              * Get the flags on the fd to understand how it was opened
175              */
176             flags = fcntl(fd, F_GETFL, 0);
177             switch (flags & O_ACCMODE) {
178                 case O_RDWR:
179                     if (flags & O_APPEND)
180                         mode = "a+";
181                     else
182                         mode = "rw";
183                     break;
184                 case O_RDONLY:
185                     if (flags & O_APPEND)
186                         mode = "r+";
187                     else
188                         mode = "r";
189                     break;
190                 case O_WRONLY:
191                     if (flags & O_APPEND)
192                         mode = "a";
193                     else
194                         mode = "w";
195                     break;
196                 default:
197                     return(NULL);
198             }
199     }
200 #endif
201 
202     /*
203      * the FILE struct gets a new fd, so that it can be closed
204      * independently of the file descriptor given. The risk though is
205      * lack of sync. So at the python level sync must be implemented
206      * before and after a conversion took place. No way around it
207      * in the Python3 infrastructure !
208      * The duplicated fd and FILE * will be released in the subsequent
209      * call to libxml_PyFileRelease() which must be generated accordingly
210      */
211     fd = dup(fd);
212     if (fd == -1)
213         return(NULL);
214     res = fdopen(fd, mode);
215     if (res == NULL) {
216         close(fd);
217 	return(NULL);
218     }
219     return(res);
220 }
221 
libxml_PyFileRelease(FILE * f)222 void libxml_PyFileRelease(FILE *f) {
223     if (f != NULL)
224         fclose(f);
225 }
226 #endif
227 
228 PyObject *
libxml_intWrap(int val)229 libxml_intWrap(int val)
230 {
231     PyObject *ret;
232 
233     ret = PY_IMPORT_INT((long) val);
234     return (ret);
235 }
236 
237 PyObject *
libxml_longWrap(long val)238 libxml_longWrap(long val)
239 {
240     PyObject *ret;
241 
242     ret = PyLong_FromLong(val);
243     return (ret);
244 }
245 
246 PyObject *
libxml_doubleWrap(double val)247 libxml_doubleWrap(double val)
248 {
249     PyObject *ret;
250 
251     ret = PyFloat_FromDouble((double) val);
252     return (ret);
253 }
254 
255 PyObject *
libxml_charPtrWrap(char * str)256 libxml_charPtrWrap(char *str)
257 {
258     PyObject *ret;
259 
260     if (str == NULL) {
261         Py_INCREF(Py_None);
262         return (Py_None);
263     }
264     ret = PY_IMPORT_STRING(str);
265     xmlFree(str);
266     return (ret);
267 }
268 
269 PyObject *
libxml_charPtrConstWrap(const char * str)270 libxml_charPtrConstWrap(const char *str)
271 {
272     PyObject *ret;
273 
274     if (str == NULL) {
275         Py_INCREF(Py_None);
276         return (Py_None);
277     }
278     ret = PY_IMPORT_STRING(str);
279     return (ret);
280 }
281 
282 PyObject *
libxml_xmlCharPtrWrap(xmlChar * str)283 libxml_xmlCharPtrWrap(xmlChar * str)
284 {
285     PyObject *ret;
286 
287     if (str == NULL) {
288         Py_INCREF(Py_None);
289         return (Py_None);
290     }
291     ret = PY_IMPORT_STRING((char *) str);
292     xmlFree(str);
293     return (ret);
294 }
295 
296 PyObject *
libxml_xmlCharPtrConstWrap(const xmlChar * str)297 libxml_xmlCharPtrConstWrap(const xmlChar * str)
298 {
299     PyObject *ret;
300 
301     if (str == NULL) {
302         Py_INCREF(Py_None);
303         return (Py_None);
304     }
305     ret = PY_IMPORT_STRING((char *) str);
306     return (ret);
307 }
308 
309 PyObject *
libxml_constcharPtrWrap(const char * str)310 libxml_constcharPtrWrap(const char *str)
311 {
312     PyObject *ret;
313 
314     if (str == NULL) {
315         Py_INCREF(Py_None);
316         return (Py_None);
317     }
318     ret = PY_IMPORT_STRING(str);
319     return (ret);
320 }
321 
322 PyObject *
libxml_constxmlCharPtrWrap(const xmlChar * str)323 libxml_constxmlCharPtrWrap(const xmlChar * str)
324 {
325     PyObject *ret;
326 
327     if (str == NULL) {
328         Py_INCREF(Py_None);
329         return (Py_None);
330     }
331     ret = PY_IMPORT_STRING((char *) str);
332     return (ret);
333 }
334 
335 PyObject *
libxml_xmlDocPtrWrap(xmlDocPtr doc)336 libxml_xmlDocPtrWrap(xmlDocPtr doc)
337 {
338     PyObject *ret;
339 
340     if (doc == NULL) {
341         Py_INCREF(Py_None);
342         return (Py_None);
343     }
344     /* TODO: look at deallocation */
345     ret = PyCapsule_New((void *) doc, (char *) "xmlDocPtr", NULL);
346     return (ret);
347 }
348 
349 PyObject *
libxml_xmlNodePtrWrap(xmlNodePtr node)350 libxml_xmlNodePtrWrap(xmlNodePtr node)
351 {
352     PyObject *ret;
353 
354     if (node == NULL) {
355         Py_INCREF(Py_None);
356         return (Py_None);
357     }
358     ret = PyCapsule_New((void *) node, (char *) "xmlNodePtr", NULL);
359     return (ret);
360 }
361 
362 PyObject *
libxml_xmlURIPtrWrap(xmlURIPtr uri)363 libxml_xmlURIPtrWrap(xmlURIPtr uri)
364 {
365     PyObject *ret;
366 
367     if (uri == NULL) {
368         Py_INCREF(Py_None);
369         return (Py_None);
370     }
371     ret = PyCapsule_New((void *) uri, (char *) "xmlURIPtr", NULL);
372     return (ret);
373 }
374 
375 PyObject *
libxml_xmlNsPtrWrap(xmlNsPtr ns)376 libxml_xmlNsPtrWrap(xmlNsPtr ns)
377 {
378     PyObject *ret;
379 
380     if (ns == NULL) {
381         Py_INCREF(Py_None);
382         return (Py_None);
383     }
384     ret = PyCapsule_New((void *) ns, (char *) "xmlNsPtr", NULL);
385     return (ret);
386 }
387 
388 PyObject *
libxml_xmlAttrPtrWrap(xmlAttrPtr attr)389 libxml_xmlAttrPtrWrap(xmlAttrPtr attr)
390 {
391     PyObject *ret;
392 
393     if (attr == NULL) {
394         Py_INCREF(Py_None);
395         return (Py_None);
396     }
397     ret = PyCapsule_New((void *) attr, (char *) "xmlAttrPtr", NULL);
398     return (ret);
399 }
400 
401 PyObject *
libxml_xmlAttributePtrWrap(xmlAttributePtr attr)402 libxml_xmlAttributePtrWrap(xmlAttributePtr attr)
403 {
404     PyObject *ret;
405 
406     if (attr == NULL) {
407         Py_INCREF(Py_None);
408         return (Py_None);
409     }
410     ret = PyCapsule_New((void *) attr, (char *) "xmlAttributePtr", NULL);
411     return (ret);
412 }
413 
414 PyObject *
libxml_xmlElementPtrWrap(xmlElementPtr elem)415 libxml_xmlElementPtrWrap(xmlElementPtr elem)
416 {
417     PyObject *ret;
418 
419     if (elem == NULL) {
420         Py_INCREF(Py_None);
421         return (Py_None);
422     }
423     ret = PyCapsule_New((void *) elem, (char *) "xmlElementPtr", NULL);
424     return (ret);
425 }
426 
427 PyObject *
libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt)428 libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt)
429 {
430     PyObject *ret;
431 
432     if (ctxt == NULL) {
433         Py_INCREF(Py_None);
434         return (Py_None);
435     }
436 
437     ret = PyCapsule_New((void *) ctxt, (char *) "xmlParserCtxtPtr", NULL);
438     return (ret);
439 }
440 
441 #ifdef LIBXML_XPATH_ENABLED
442 PyObject *
libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt)443 libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt)
444 {
445     PyObject *ret;
446 
447     if (ctxt == NULL) {
448         Py_INCREF(Py_None);
449         return (Py_None);
450     }
451     ret = PyCapsule_New((void *) ctxt, (char *) "xmlXPathContextPtr", NULL);
452     return (ret);
453 }
454 
455 PyObject *
libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt)456 libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt)
457 {
458     PyObject *ret;
459 
460     if (ctxt == NULL) {
461         Py_INCREF(Py_None);
462         return (Py_None);
463     }
464     ret = PyCapsule_New((void *)ctxt, (char *)"xmlXPathParserContextPtr", NULL);
465     return (ret);
466 }
467 
468 /**
469  * libxml_xmlXPathDestructNsNode:
470  * cap: xmlNsPtr namespace node capsule object
471  *
472  * This function is called if and when a namespace node returned in
473  * an XPath node set is to be destroyed. That's the only kind of
474  * object returned in node set not directly linked to the original
475  * xmlDoc document, see xmlXPathNodeSetDupNs.
476  */
477 #if PY_VERSION_HEX < 0x02070000
478 static void
libxml_xmlXPathDestructNsNode(void * cap,void * desc ATTRIBUTE_UNUSED)479 libxml_xmlXPathDestructNsNode(void *cap, void *desc ATTRIBUTE_UNUSED)
480 #else
481 static void
482 libxml_xmlXPathDestructNsNode(PyObject *cap)
483 #endif
484 {
485 #if PY_VERSION_HEX < 0x02070000
486     xmlXPathNodeSetFreeNs((xmlNsPtr) cap);
487 #else
488     xmlXPathNodeSetFreeNs((xmlNsPtr) PyCapsule_GetPointer(cap, "xmlNsPtr"));
489 #endif
490 }
491 
492 PyObject *
libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj)493 libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj)
494 {
495     PyObject *ret;
496 
497     if (obj == NULL) {
498         Py_INCREF(Py_None);
499         return (Py_None);
500     }
501     switch (obj->type) {
502         case XPATH_XSLT_TREE: {
503             if ((obj->nodesetval == NULL) ||
504 		(obj->nodesetval->nodeNr == 0) ||
505 		(obj->nodesetval->nodeTab == NULL)) {
506                 ret = PyList_New(0);
507 	    } else {
508 		int i, len = 0;
509 		xmlNodePtr node;
510 
511 		node = obj->nodesetval->nodeTab[0]->children;
512 		while (node != NULL) {
513 		    len++;
514 		    node = node->next;
515 		}
516 		ret = PyList_New(len);
517 		node = obj->nodesetval->nodeTab[0]->children;
518 		for (i = 0;i < len;i++) {
519                     PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
520 		    node = node->next;
521 		}
522 	    }
523 	    /*
524 	     * Return now, do not free the object passed down
525 	     */
526 	    return (ret);
527 	}
528         case XPATH_NODESET:
529             if ((obj->nodesetval == NULL)
530                 || (obj->nodesetval->nodeNr == 0)) {
531                 ret = PyList_New(0);
532 	    } else {
533                 int i;
534                 xmlNodePtr node;
535 
536                 ret = PyList_New(obj->nodesetval->nodeNr);
537                 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
538                     node = obj->nodesetval->nodeTab[i];
539                     if (node->type == XML_NAMESPACE_DECL) {
540 		        PyObject *ns = PyCapsule_New((void *) node,
541                                      (char *) "xmlNsPtr",
542 				     libxml_xmlXPathDestructNsNode);
543 			PyList_SetItem(ret, i, ns);
544 			/* make sure the xmlNsPtr is not destroyed now */
545 			obj->nodesetval->nodeTab[i] = NULL;
546 		    } else {
547 			PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
548 		    }
549                 }
550             }
551             break;
552         case XPATH_BOOLEAN:
553             ret = PY_IMPORT_INT((long) obj->boolval);
554             break;
555         case XPATH_NUMBER:
556             ret = PyFloat_FromDouble(obj->floatval);
557             break;
558         case XPATH_STRING:
559 	    ret = PY_IMPORT_STRING((char *) obj->stringval);
560             break;
561         default:
562             Py_INCREF(Py_None);
563             ret = Py_None;
564     }
565     xmlXPathFreeObject(obj);
566     return (ret);
567 }
568 
569 xmlXPathObjectPtr
libxml_xmlXPathObjectPtrConvert(PyObject * obj)570 libxml_xmlXPathObjectPtrConvert(PyObject *obj)
571 {
572     xmlXPathObjectPtr ret = NULL;
573 
574     if (obj == NULL) {
575         return (NULL);
576     }
577     if (PyFloat_Check (obj)) {
578         ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
579     } else if (PyLong_Check(obj)) {
580 #ifdef PyLong_AS_LONG
581         ret = xmlXPathNewFloat((double) PyLong_AS_LONG(obj));
582 #else
583         ret = xmlXPathNewFloat((double) PyInt_AS_LONG(obj));
584 #endif
585 #ifdef PyBool_Check
586     } else if (PyBool_Check (obj)) {
587 
588         if (obj == Py_True) {
589           ret = xmlXPathNewBoolean(1);
590         }
591         else {
592           ret = xmlXPathNewBoolean(0);
593         }
594 #endif
595     } else if (PyBytes_Check (obj)) {
596         xmlChar *str;
597 
598         str = xmlStrndup((const xmlChar *) PyBytes_AS_STRING(obj),
599                          PyBytes_GET_SIZE(obj));
600         ret = xmlXPathWrapString(str);
601 #ifdef PyUnicode_Check
602     } else if (PyUnicode_Check (obj)) {
603 #if PY_VERSION_HEX >= 0x03030000
604         xmlChar *str;
605 	const char *tmp;
606 	Py_ssize_t size;
607 
608 	/* tmp doesn't need to be deallocated */
609         tmp = PyUnicode_AsUTF8AndSize(obj, &size);
610         str = xmlStrndup((const xmlChar *) tmp, (int) size);
611         ret = xmlXPathWrapString(str);
612 #else
613         xmlChar *str = NULL;
614         PyObject *b;
615 
616 	b = PyUnicode_AsUTF8String(obj);
617 	if (b != NULL) {
618 	    str = xmlStrndup((const xmlChar *) PyBytes_AS_STRING(b),
619 			     PyBytes_GET_SIZE(b));
620 	    Py_DECREF(b);
621 	}
622 	ret = xmlXPathWrapString(str);
623 #endif
624 #endif
625     } else if (PyList_Check (obj)) {
626         int i;
627         PyObject *node;
628         xmlNodePtr cur;
629         xmlNodeSetPtr set;
630 
631         set = xmlXPathNodeSetCreate(NULL);
632 
633         for (i = 0; i < PyList_Size(obj); i++) {
634             node = PyList_GetItem(obj, i);
635             if ((node == NULL) || (node->ob_type == NULL))
636                 continue;
637 
638             cur = NULL;
639             if (PyCapsule_CheckExact(node)) {
640                 cur = PyxmlNode_Get(node);
641             } else if ((PyObject_HasAttrString(node, (char *) "_o")) &&
642 	               (PyObject_HasAttrString(node, (char *) "get_doc"))) {
643 		PyObject *wrapper;
644 
645 		wrapper = PyObject_GetAttrString(node, (char *) "_o");
646 		if (wrapper != NULL)
647 		    cur = PyxmlNode_Get(wrapper);
648             } else {
649             }
650             if (cur != NULL) {
651                 xmlXPathNodeSetAdd(set, cur);
652             }
653         }
654         ret = xmlXPathWrapNodeSet(set);
655     } else {
656     }
657     return (ret);
658 }
659 #endif /* LIBXML_XPATH_ENABLED */
660 
661 PyObject *
libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid)662 libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid)
663 {
664 	PyObject *ret;
665 
666 	if (valid == NULL) {
667 		Py_INCREF(Py_None);
668 		return (Py_None);
669 	}
670 
671 	ret =
672 		PyCapsule_New((void *) valid,
673 									 (char *) "xmlValidCtxtPtr", NULL);
674 
675 	return (ret);
676 }
677 
678 #ifdef LIBXML_CATALOG_ENABLED
679 PyObject *
libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)680 libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)
681 {
682     PyObject *ret;
683 
684     if (catal == NULL) {
685         Py_INCREF(Py_None);
686         return (Py_None);
687     }
688     ret =
689         PyCapsule_New((void *) catal,
690                                      (char *) "xmlCatalogPtr", NULL);
691     return (ret);
692 }
693 #endif /* LIBXML_CATALOG_ENABLED */
694 
695 PyObject *
libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer)696 libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer)
697 {
698     PyObject *ret;
699 
700     if (buffer == NULL) {
701         Py_INCREF(Py_None);
702         return (Py_None);
703     }
704     ret =
705         PyCapsule_New((void *) buffer,
706                                      (char *) "xmlOutputBufferPtr", NULL);
707     return (ret);
708 }
709 
710 PyObject *
libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer)711 libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer)
712 {
713     PyObject *ret;
714 
715     if (buffer == NULL) {
716         Py_INCREF(Py_None);
717         return (Py_None);
718     }
719     ret =
720         PyCapsule_New((void *) buffer,
721                                      (char *) "xmlParserInputBufferPtr", NULL);
722     return (ret);
723 }
724 
725 #ifdef LIBXML_REGEXP_ENABLED
726 PyObject *
libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp)727 libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp)
728 {
729     PyObject *ret;
730 
731     if (regexp == NULL) {
732         Py_INCREF(Py_None);
733         return (Py_None);
734     }
735     ret =
736         PyCapsule_New((void *) regexp,
737                                      (char *) "xmlRegexpPtr", NULL);
738     return (ret);
739 }
740 #endif /* LIBXML_REGEXP_ENABLED */
741 
742 #ifdef LIBXML_READER_ENABLED
743 PyObject *
libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader)744 libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader)
745 {
746     PyObject *ret;
747 
748     if (reader == NULL) {
749         Py_INCREF(Py_None);
750         return (Py_None);
751     }
752     ret =
753         PyCapsule_New((void *) reader,
754                                      (char *) "xmlTextReaderPtr", NULL);
755     return (ret);
756 }
757 
758 PyObject *
libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator)759 libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator)
760 {
761     PyObject *ret;
762 
763     if (locator == NULL) {
764         Py_INCREF(Py_None);
765         return (Py_None);
766     }
767     ret =
768         PyCapsule_New((void *) locator,
769                                      (char *) "xmlTextReaderLocatorPtr", NULL);
770     return (ret);
771 }
772 #endif /* LIBXML_READER_ENABLED */
773 
774 #ifdef LIBXML_SCHEMAS_ENABLED
775 PyObject *
libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt)776 libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt)
777 {
778     PyObject *ret;
779 
780     if (ctxt == NULL) {
781         Py_INCREF(Py_None);
782         return (Py_None);
783     }
784     ret =
785         PyCapsule_New((void *) ctxt,
786                                      (char *) "xmlRelaxNGPtr", NULL);
787     return (ret);
788 }
789 
790 PyObject *
libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt)791 libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt)
792 {
793     PyObject *ret;
794 
795     if (ctxt == NULL) {
796         Py_INCREF(Py_None);
797         return (Py_None);
798     }
799     ret =
800         PyCapsule_New((void *) ctxt,
801                                      (char *) "xmlRelaxNGParserCtxtPtr", NULL);
802     return (ret);
803 }
804 PyObject *
libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid)805 libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid)
806 {
807     PyObject *ret;
808 
809     if (valid == NULL) {
810         Py_INCREF(Py_None);
811         return (Py_None);
812     }
813     ret =
814         PyCapsule_New((void *) valid,
815                                      (char *) "xmlRelaxNGValidCtxtPtr", NULL);
816     return (ret);
817 }
818 
819 PyObject *
libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt)820 libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt)
821 {
822 	PyObject *ret;
823 
824 	if (ctxt == NULL) {
825 		Py_INCREF(Py_None);
826 		return (Py_None);
827 	}
828 	ret =
829 		PyCapsule_New((void *) ctxt,
830 									 (char *) "xmlSchemaPtr", NULL);
831 	return (ret);
832 }
833 
834 PyObject *
libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt)835 libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt)
836 {
837 	PyObject *ret;
838 
839 	if (ctxt == NULL) {
840 		Py_INCREF(Py_None);
841 		return (Py_None);
842 	}
843 	ret =
844 		PyCapsule_New((void *) ctxt,
845 									 (char *) "xmlSchemaParserCtxtPtr", NULL);
846 
847 	return (ret);
848 }
849 
850 PyObject *
libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid)851 libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid)
852 {
853 	PyObject *ret;
854 
855 	if (valid == NULL) {
856 		Py_INCREF(Py_None);
857 		return (Py_None);
858 	}
859 
860 	ret =
861 		PyCapsule_New((void *) valid,
862 									 (char *) "xmlSchemaValidCtxtPtr", NULL);
863 
864 	return (ret);
865 }
866 #endif /* LIBXML_SCHEMAS_ENABLED */
867 
868 static void
libxml_xmlDestructError(PyObject * cap)869 libxml_xmlDestructError(PyObject *cap) {
870     xmlErrorPtr err = (xmlErrorPtr) PyCapsule_GetPointer(cap, "xmlErrorPtr");
871     xmlResetError(err);
872     xmlFree(err);
873 }
874 
875 PyObject *
libxml_xmlErrorPtrWrap(const xmlError * error)876 libxml_xmlErrorPtrWrap(const xmlError *error)
877 {
878     PyObject *ret;
879     xmlErrorPtr copy;
880 
881     if (error == NULL) {
882         Py_INCREF(Py_None);
883         return (Py_None);
884     }
885     copy = xmlMalloc(sizeof(*copy));
886     if (copy == NULL) {
887         Py_INCREF(Py_None);
888         return (Py_None);
889     }
890     memset(copy, 0, sizeof(*copy));
891     xmlCopyError(error, copy);
892     ret = PyCapsule_New(copy, "xmlErrorPtr", libxml_xmlDestructError);
893     return (ret);
894 }
895