92a6c18dbaeb7ead19130d4ced63e6246f28bbd1
[platform/upstream/libxslt.git] / libxslt / extensions.c
1 /*
2  * extensions.c: Implemetation of the extensions support
3  *
4  * Reference:
5  *   http://www.w3.org/TR/1999/REC-xslt-19991116
6  *
7  * See Copyright for the status of this software.
8  *
9  * daniel@veillard.com
10  */
11
12 #include "libxslt.h"
13
14 #include <string.h>
15
16 #include <libxml/xmlmemory.h>
17 #include <libxml/tree.h>
18 #include <libxml/hash.h>
19 #include <libxml/xmlerror.h>
20 #include <libxml/parserInternals.h>
21 #include "xslt.h"
22 #include "xsltInternals.h"
23 #include "xsltutils.h"
24 #include "extensions.h"
25
26 #ifdef WITH_XSLT_DEBUG
27 #define WITH_XSLT_DEBUG_EXTENSIONS
28 #endif
29
30 typedef struct _xsltExtDef xsltExtDef;
31 typedef xsltExtDef *xsltExtDefPtr;
32 struct _xsltExtDef {
33     struct _xsltExtDef *next;
34     xmlChar *prefix;
35     xmlChar *URI;
36     void    *data;
37 };
38
39 /************************************************************************
40  *                                                                      *
41  *                      Type functions                                  *
42  *                                                                      *
43  ************************************************************************/
44
45 /**
46  * xsltNewExtDef:
47  * @prefix:  the extension prefix
48  * @URI:  the namespace URI
49  *
50  * Create a new XSLT ExtDef
51  *
52  * Returns the newly allocated xsltExtDefPtr or NULL in case of error
53  */
54 static xsltExtDefPtr
55 xsltNewExtDef(const xmlChar *prefix, const xmlChar *URI) {
56     xsltExtDefPtr cur;
57
58     cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef));
59     if (cur == NULL) {
60         xsltGenericError(xsltGenericErrorContext,
61                 "xsltNewExtDef : malloc failed\n");
62         return(NULL);
63     }
64     memset(cur, 0, sizeof(xsltExtDef));
65     if (prefix != NULL)
66         cur->prefix = xmlStrdup(prefix);
67     if (URI != NULL)
68         cur->URI = xmlStrdup(URI);
69     return(cur);
70 }
71
72 /**
73  * xsltFreeExtDef:
74  * @extensiond:  an XSLT extension definition
75  *
76  * Free up the memory allocated by @extensiond
77  */
78 static void
79 xsltFreeExtDef(xsltExtDefPtr extensiond) {
80     if (extensiond == NULL)
81         return;
82     if (extensiond->prefix != NULL)
83         xmlFree(extensiond->prefix);
84     if (extensiond->URI != NULL)
85         xmlFree(extensiond->URI);
86     memset(extensiond, -1, sizeof(xsltExtDef));
87     xmlFree(extensiond);
88 }
89
90 /**
91  * xsltFreeExtDefList:
92  * @extensiond:  an XSLT extension definition list
93  *
94  * Free up the memory allocated by all the elements of @extensiond
95  */
96 static void
97 xsltFreeExtDefList(xsltExtDefPtr extensiond) {
98     xsltExtDefPtr cur;
99
100     while (extensiond != NULL) {
101         cur = extensiond;
102         extensiond = extensiond->next;
103         xsltFreeExtDef(cur);
104     }
105 }
106
107
108 /************************************************************************
109  *                                                                      *
110  *              The interpreter for the precompiled patterns            *
111  *                                                                      *
112  ************************************************************************/
113
114
115 /**
116  * xsltFreeExts:
117  * @style: an XSLT stylesheet
118  *
119  * Free up the memory used by XSLT extensions in a stylesheet
120  */
121 void
122 xsltFreeExts(xsltStylesheetPtr style) {
123     if (style->nsDefs != NULL)
124         xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs);
125 }
126
127 /**
128  * xsltRegisterExtPrefix:
129  * @style: an XSLT stylesheet
130  * @prefix: the prefix used
131  * @URI: the URI associated to the extension
132  *
133  * Registers an extension namespace
134  *
135  * Returns 0 in case of success, -1 in case of failure
136  */
137 int
138 xsltRegisterExtPrefix(xsltStylesheetPtr style,
139                       const xmlChar *prefix, const xmlChar *URI) {
140     xsltExtDefPtr def, ret;
141
142     if ((style == NULL) || (prefix == NULL) | (URI == NULL))
143         return(-1);
144
145     def = (xsltExtDefPtr) style->nsDefs;
146     while (def != NULL) {
147         if (xmlStrEqual(prefix, def->prefix))
148             return(-1);
149         def = def->next;
150     }
151     ret = xsltNewExtDef(prefix, URI);
152     if (ret == NULL)
153         return(-1);
154     ret->next = (xsltExtDefPtr) style->nsDefs;
155     style->nsDefs = ret;
156     return(0);
157 }
158
159 /**
160  * xsltRegisterExtFunction:
161  * @ctxt: an XSLT transformation context
162  * @name: the name of the element
163  * @URI: the URI associated to the element
164  * @function: the actual implementation which should be called 
165  *
166  * Registers an extension function
167  *
168  * Returns 0 in case of success, -1 in case of failure
169  */
170 int
171 xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name,
172                         const xmlChar *URI, xmlXPathEvalFunc function) {
173     if ((ctxt == NULL) || (name == NULL) ||
174         (URI == NULL) || (function == NULL))
175         return(-1);
176     if (ctxt->extFunctions == NULL)
177         ctxt->extFunctions = xmlHashCreate(10);
178     return(xmlHashAddEntry2(ctxt->extFunctions, name, URI, (void *) function));
179 }
180
181 /**
182  * xsltRegisterExtElement:
183  * @ctxt: an XSLT transformation context
184  * @name: the name of the element
185  * @URI: the URI associated to the element
186  * @function: the actual implementation which should be called 
187  *
188  * Registers an extension element
189  *
190  * Returns 0 in case of success, -1 in case of failure
191  */
192 int     
193 xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar *name,
194                        const xmlChar *URI, xsltTransformFunction function) {
195     if ((ctxt == NULL) || (name == NULL) ||
196         (URI == NULL) || (function == NULL))
197         return(-1);
198     if (ctxt->extElements == NULL)
199         ctxt->extElements = xmlHashCreate(10);
200     return(xmlHashAddEntry2(ctxt->extElements, name, URI, (void *) function));
201 }
202
203 /**
204  * xsltFreeCtxtExts:
205  * @ctxt: an XSLT transformation context
206  *
207  * Free the XSLT extension data
208  */
209 void
210 xsltFreeCtxtExts(xsltTransformContextPtr ctxt) {
211     if (ctxt->extElements != NULL)
212         xmlHashFree(ctxt->extElements, NULL);
213     if (ctxt->extFunctions != NULL)
214         xmlHashFree(ctxt->extFunctions, NULL);
215 }
216
217 /**
218  * xsltCheckExtPrefix:
219  * @style: the stylesheet
220  * @prefix: the namespace prefix (possibly NULL)
221  *
222  * Check if the given prefix is one of the declared extensions
223  *
224  * Returns 1 if this is an extension, 0 otherwise
225  */
226 int
227 xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar *prefix) {
228     xsltExtDefPtr cur;
229
230     if ((style == NULL) || (style->nsDefs == NULL))
231         return(0);
232
233     cur = (xsltExtDefPtr) style->nsDefs;
234     while (cur != NULL) {
235         if (xmlStrEqual(prefix, cur->prefix))
236             return(1);
237         cur = cur->next;
238     }
239     return(0);
240 }
241