Add ICU message format support
[chromium-blink-merge.git] / third_party / libxslt / libexslt / strings.c
blob045cc14b63e7a23d687d9dcf2e2530f4970de974
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
10 #include <libxml/tree.h>
11 #include <libxml/xpath.h>
12 #include <libxml/xpathInternals.h>
13 #include <libxml/parser.h>
14 #include <libxml/encoding.h>
15 #include <libxml/uri.h>
17 #include <libxslt/xsltconfig.h>
18 #include <libxslt/xsltutils.h>
19 #include <libxslt/xsltInternals.h>
20 #include <libxslt/extensions.h>
22 #include "exslt.h"
24 /**
25 * exsltStrTokenizeFunction:
26 * @ctxt: an XPath parser context
27 * @nargs: the number of arguments
29 * Splits up a string on the characters of the delimiter string and returns a
30 * node set of token elements, each containing one token from the string.
32 static void
33 exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
35 xsltTransformContextPtr tctxt;
36 xmlChar *str, *delimiters, *cur;
37 const xmlChar *token, *delimiter;
38 xmlNodePtr node;
39 xmlDocPtr container;
40 xmlXPathObjectPtr ret = NULL;
41 int clen;
43 if ((nargs < 1) || (nargs > 2)) {
44 xmlXPathSetArityError(ctxt);
45 return;
48 if (nargs == 2) {
49 delimiters = xmlXPathPopString(ctxt);
50 if (xmlXPathCheckError(ctxt))
51 return;
52 } else {
53 delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");
55 if (delimiters == NULL)
56 return;
58 str = xmlXPathPopString(ctxt);
59 if (xmlXPathCheckError(ctxt) || (str == NULL)) {
60 xmlFree(delimiters);
61 return;
64 /* Return a result tree fragment */
65 tctxt = xsltXPathGetTransformContext(ctxt);
66 if (tctxt == NULL) {
67 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
68 "exslt:tokenize : internal error tctxt == NULL\n");
69 goto fail;
72 container = xsltCreateRVT(tctxt);
73 if (container != NULL) {
74 xsltRegisterLocalRVT(tctxt, container);
75 ret = xmlXPathNewNodeSet(NULL);
76 if (ret != NULL) {
77 for (cur = str, token = str; *cur != 0; cur += clen) {
78 clen = xmlUTF8Size(cur);
79 if (*delimiters == 0) { /* empty string case */
80 xmlChar ctmp;
81 ctmp = *(cur+clen);
82 *(cur+clen) = 0;
83 node = xmlNewDocRawNode(container, NULL,
84 (const xmlChar *) "token", cur);
85 xmlAddChild((xmlNodePtr) container, node);
86 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
87 *(cur+clen) = ctmp; /* restore the changed byte */
88 token = cur + clen;
89 } else for (delimiter = delimiters; *delimiter != 0;
90 delimiter += xmlUTF8Size(delimiter)) {
91 if (!xmlUTF8Charcmp(cur, delimiter)) {
92 if (cur == token) {
93 /* discard empty tokens */
94 token = cur + clen;
95 break;
97 *cur = 0; /* terminate the token */
98 node = xmlNewDocRawNode(container, NULL,
99 (const xmlChar *) "token", token);
100 xmlAddChild((xmlNodePtr) container, node);
101 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
102 *cur = *delimiter; /* restore the changed byte */
103 token = cur + clen;
104 break;
108 if (token != cur) {
109 node = xmlNewDocRawNode(container, NULL,
110 (const xmlChar *) "token", token);
111 xmlAddChild((xmlNodePtr) container, node);
112 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
115 * Mark it as a function result in order to avoid garbage
116 * collecting of tree fragments
118 xsltExtensionInstructionResultRegister(tctxt, ret);
122 fail:
123 if (str != NULL)
124 xmlFree(str);
125 if (delimiters != NULL)
126 xmlFree(delimiters);
127 if (ret != NULL)
128 valuePush(ctxt, ret);
129 else
130 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
134 * exsltStrSplitFunction:
135 * @ctxt: an XPath parser context
136 * @nargs: the number of arguments
138 * Splits up a string on a delimiting string and returns a node set of token
139 * elements, each containing one token from the string.
141 static void
142 exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {
143 xsltTransformContextPtr tctxt;
144 xmlChar *str, *delimiter, *cur;
145 const xmlChar *token;
146 xmlNodePtr node;
147 xmlDocPtr container;
148 xmlXPathObjectPtr ret = NULL;
149 int delimiterLength;
151 if ((nargs < 1) || (nargs > 2)) {
152 xmlXPathSetArityError(ctxt);
153 return;
156 if (nargs == 2) {
157 delimiter = xmlXPathPopString(ctxt);
158 if (xmlXPathCheckError(ctxt))
159 return;
160 } else {
161 delimiter = xmlStrdup((const xmlChar *) " ");
163 if (delimiter == NULL)
164 return;
165 delimiterLength = xmlStrlen (delimiter);
167 str = xmlXPathPopString(ctxt);
168 if (xmlXPathCheckError(ctxt) || (str == NULL)) {
169 xmlFree(delimiter);
170 return;
173 /* Return a result tree fragment */
174 tctxt = xsltXPathGetTransformContext(ctxt);
175 if (tctxt == NULL) {
176 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
177 "exslt:tokenize : internal error tctxt == NULL\n");
178 goto fail;
182 * OPTIMIZE TODO: We are creating an xmlDoc for every split!
184 container = xsltCreateRVT(tctxt);
185 if (container != NULL) {
186 xsltRegisterLocalRVT(tctxt, container);
187 ret = xmlXPathNewNodeSet(NULL);
188 if (ret != NULL) {
189 for (cur = str, token = str; *cur != 0; cur++) {
190 if (delimiterLength == 0) {
191 if (cur != token) {
192 xmlChar tmp = *cur;
193 *cur = 0;
194 node = xmlNewDocRawNode(container, NULL,
195 (const xmlChar *) "token", token);
196 xmlAddChild((xmlNodePtr) container, node);
197 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
198 *cur = tmp;
199 token++;
202 else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) {
203 if (cur == token) {
204 /* discard empty tokens */
205 cur = cur + delimiterLength - 1;
206 token = cur + 1;
207 continue;
209 *cur = 0;
210 node = xmlNewDocRawNode(container, NULL,
211 (const xmlChar *) "token", token);
212 xmlAddChild((xmlNodePtr) container, node);
213 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
214 *cur = *delimiter;
215 cur = cur + delimiterLength - 1;
216 token = cur + 1;
219 if (token != cur) {
220 node = xmlNewDocRawNode(container, NULL,
221 (const xmlChar *) "token", token);
222 xmlAddChild((xmlNodePtr) container, node);
223 xmlXPathNodeSetAddUnique(ret->nodesetval, node);
226 * Mark it as a function result in order to avoid garbage
227 * collecting of tree fragments
229 xsltExtensionInstructionResultRegister(tctxt, ret);
233 fail:
234 if (str != NULL)
235 xmlFree(str);
236 if (delimiter != NULL)
237 xmlFree(delimiter);
238 if (ret != NULL)
239 valuePush(ctxt, ret);
240 else
241 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
245 * exsltStrEncodeUriFunction:
246 * @ctxt: an XPath parser context
247 * @nargs: the number of arguments
249 * URI-Escapes a string
251 static void
252 exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
253 int escape_all = 1, str_len = 0;
254 xmlChar *str = NULL, *ret = NULL, *tmp;
256 if ((nargs < 2) || (nargs > 3)) {
257 xmlXPathSetArityError(ctxt);
258 return;
261 if (nargs >= 3) {
262 /* check for UTF-8 if encoding was explicitly given;
263 we don't support anything else yet */
264 tmp = xmlXPathPopString(ctxt);
265 if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
266 xmlXPathReturnEmptyString(ctxt);
267 xmlFree(tmp);
268 return;
270 xmlFree(tmp);
273 escape_all = xmlXPathPopBoolean(ctxt);
275 str = xmlXPathPopString(ctxt);
276 str_len = xmlUTF8Strlen(str);
278 if (str_len == 0) {
279 xmlXPathReturnEmptyString(ctxt);
280 xmlFree(str);
281 return;
284 ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]"));
285 xmlXPathReturnString(ctxt, ret);
287 if (str != NULL)
288 xmlFree(str);
292 * exsltStrDecodeUriFunction:
293 * @ctxt: an XPath parser context
294 * @nargs: the number of arguments
296 * reverses URI-Escaping of a string
298 static void
299 exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
300 int str_len = 0;
301 xmlChar *str = NULL, *ret = NULL, *tmp;
303 if ((nargs < 1) || (nargs > 2)) {
304 xmlXPathSetArityError(ctxt);
305 return;
308 if (nargs >= 2) {
309 /* check for UTF-8 if encoding was explicitly given;
310 we don't support anything else yet */
311 tmp = xmlXPathPopString(ctxt);
312 if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
313 xmlXPathReturnEmptyString(ctxt);
314 xmlFree(tmp);
315 return;
317 xmlFree(tmp);
320 str = xmlXPathPopString(ctxt);
321 str_len = xmlUTF8Strlen(str);
323 if (str_len == 0) {
324 xmlXPathReturnEmptyString(ctxt);
325 xmlFree(str);
326 return;
329 ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL);
330 if (!xmlCheckUTF8(ret)) {
331 /* FIXME: instead of throwing away the whole URI, we should
332 only discard the invalid sequence(s). How to do that? */
333 xmlXPathReturnEmptyString(ctxt);
334 xmlFree(str);
335 xmlFree(ret);
336 return;
339 xmlXPathReturnString(ctxt, ret);
341 if (str != NULL)
342 xmlFree(str);
346 * exsltStrPaddingFunction:
347 * @ctxt: an XPath parser context
348 * @nargs: the number of arguments
350 * Creates a padding string of a certain length.
352 static void
353 exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
354 int number, str_len = 0;
355 xmlChar *str = NULL, *ret = NULL, *tmp;
357 if ((nargs < 1) || (nargs > 2)) {
358 xmlXPathSetArityError(ctxt);
359 return;
362 if (nargs == 2) {
363 str = xmlXPathPopString(ctxt);
364 str_len = xmlUTF8Strlen(str);
366 if (str_len == 0) {
367 if (str != NULL) xmlFree(str);
368 str = xmlStrdup((const xmlChar *) " ");
369 str_len = 1;
372 number = (int) xmlXPathPopNumber(ctxt);
374 if (number <= 0) {
375 xmlXPathReturnEmptyString(ctxt);
376 xmlFree(str);
377 return;
380 while (number >= str_len) {
381 ret = xmlStrncat(ret, str, str_len);
382 number -= str_len;
384 tmp = xmlUTF8Strndup (str, number);
385 ret = xmlStrcat(ret, tmp);
386 if (tmp != NULL)
387 xmlFree (tmp);
389 xmlXPathReturnString(ctxt, ret);
391 if (str != NULL)
392 xmlFree(str);
396 * exsltStrAlignFunction:
397 * @ctxt: an XPath parser context
398 * @nargs: the number of arguments
400 * Aligns a string within another string.
402 static void
403 exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {
404 xmlChar *str, *padding, *alignment, *ret;
405 int str_l, padding_l;
407 if ((nargs < 2) || (nargs > 3)) {
408 xmlXPathSetArityError(ctxt);
409 return;
412 if (nargs == 3)
413 alignment = xmlXPathPopString(ctxt);
414 else
415 alignment = NULL;
417 padding = xmlXPathPopString(ctxt);
418 str = xmlXPathPopString(ctxt);
420 str_l = xmlUTF8Strlen (str);
421 padding_l = xmlUTF8Strlen (padding);
423 if (str_l == padding_l) {
424 xmlXPathReturnString (ctxt, str);
425 xmlFree(padding);
426 xmlFree(alignment);
427 return;
430 if (str_l > padding_l) {
431 ret = xmlUTF8Strndup (str, padding_l);
432 } else {
433 if (xmlStrEqual(alignment, (const xmlChar *) "right")) {
434 ret = xmlUTF8Strndup (padding, padding_l - str_l);
435 ret = xmlStrcat (ret, str);
436 } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {
437 int left = (padding_l - str_l) / 2;
438 int right_start;
440 ret = xmlUTF8Strndup (padding, left);
441 ret = xmlStrcat (ret, str);
443 right_start = xmlUTF8Strsize (padding, left + str_l);
444 ret = xmlStrcat (ret, padding + right_start);
445 } else {
446 int str_s;
448 str_s = xmlStrlen (str);
449 ret = xmlStrdup (str);
450 ret = xmlStrcat (ret, padding + str_s);
454 xmlXPathReturnString (ctxt, ret);
456 xmlFree(str);
457 xmlFree(padding);
458 xmlFree(alignment);
462 * exsltStrConcatFunction:
463 * @ctxt: an XPath parser context
464 * @nargs: the number of arguments
466 * Takes a node set and returns the concatenation of the string values
467 * of the nodes in that node set. If the node set is empty, it
468 * returns an empty string.
470 static void
471 exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
472 xmlXPathObjectPtr obj;
473 xmlChar *ret = NULL;
474 int i;
476 if (nargs != 1) {
477 xmlXPathSetArityError(ctxt);
478 return;
481 if (!xmlXPathStackIsNodeSet(ctxt)) {
482 xmlXPathSetTypeError(ctxt);
483 return;
486 obj = valuePop (ctxt);
488 if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
489 xmlXPathReturnEmptyString(ctxt);
490 return;
493 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
494 xmlChar *tmp;
495 tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
497 ret = xmlStrcat (ret, tmp);
499 xmlFree(tmp);
502 xmlXPathFreeObject (obj);
504 xmlXPathReturnString(ctxt, ret);
508 * exsltStrReturnString:
509 * @ctxt: an XPath parser context
510 * @str: a string
511 * @len: length of string
513 * Returns a string as a node set.
515 static int
516 exsltStrReturnString(xmlXPathParserContextPtr ctxt, const xmlChar *str,
517 int len)
519 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
520 xmlDocPtr container;
521 xmlNodePtr text_node;
522 xmlXPathObjectPtr ret;
524 container = xsltCreateRVT(tctxt);
525 if (container == NULL) {
526 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
527 return(-1);
529 xsltRegisterLocalRVT(tctxt, container);
531 text_node = xmlNewTextLen(str, len);
532 if (text_node == NULL) {
533 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
534 return(-1);
536 xmlAddChild((xmlNodePtr) container, text_node);
538 ret = xmlXPathNewNodeSet(text_node);
539 if (ret == NULL) {
540 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
541 return(-1);
544 xsltExtensionInstructionResultRegister(tctxt, ret);
545 valuePush(ctxt, ret);
547 return(0);
551 * exsltStrReplaceFunction:
552 * @ctxt: an XPath parser context
553 * @nargs: the number of arguments
555 * Takes a string, and two node sets and returns the string with all strings in
556 * the first node set replaced by all strings in the second node set.
558 static void
559 exsltStrReplaceFunction (xmlXPathParserContextPtr ctxt, int nargs) {
560 int i, i_empty, n, slen0, rlen0, *slen, *rlen;
561 void *mem = NULL;
562 const xmlChar *src, *start;
563 xmlChar *string, *search_str = NULL, *replace_str = NULL;
564 xmlChar **search, **replace;
565 xmlNodeSetPtr search_set = NULL, replace_set = NULL;
566 xmlBufferPtr buf;
568 if (nargs != 3) {
569 xmlXPathSetArityError(ctxt);
570 return;
573 /* get replace argument */
575 if (!xmlXPathStackIsNodeSet(ctxt))
576 replace_str = xmlXPathPopString(ctxt);
577 else
578 replace_set = xmlXPathPopNodeSet(ctxt);
580 if (xmlXPathCheckError(ctxt))
581 goto fail_replace;
583 /* get search argument */
585 if (!xmlXPathStackIsNodeSet(ctxt)) {
586 search_str = xmlXPathPopString(ctxt);
587 n = 1;
589 else {
590 search_set = xmlXPathPopNodeSet(ctxt);
591 n = search_set != NULL ? search_set->nodeNr : 0;
594 if (xmlXPathCheckError(ctxt))
595 goto fail_search;
597 /* get string argument */
599 string = xmlXPathPopString(ctxt);
600 if (xmlXPathCheckError(ctxt))
601 goto fail_string;
603 /* check for empty search node list */
605 if (n <= 0) {
606 exsltStrReturnString(ctxt, string, xmlStrlen(string));
607 goto done_empty_search;
610 /* allocate memory for string pointer and length arrays */
612 if (n == 1) {
613 search = &search_str;
614 replace = &replace_str;
615 slen = &slen0;
616 rlen = &rlen0;
618 else {
619 mem = xmlMalloc(2 * n * (sizeof(const xmlChar *) + sizeof(int)));
620 if (mem == NULL) {
621 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
622 goto fail_malloc;
624 search = (xmlChar **) mem;
625 replace = search + n;
626 slen = (int *) (replace + n);
627 rlen = slen + n;
630 /* process arguments */
632 i_empty = -1;
634 for (i=0; i<n; ++i) {
635 if (search_set != NULL) {
636 search[i] = xmlXPathCastNodeToString(search_set->nodeTab[i]);
637 if (search[i] == NULL) {
638 n = i;
639 goto fail_process_args;
643 slen[i] = xmlStrlen(search[i]);
644 if (i_empty < 0 && slen[i] == 0)
645 i_empty = i;
647 if (replace_set != NULL) {
648 if (i < replace_set->nodeNr) {
649 replace[i] = xmlXPathCastNodeToString(replace_set->nodeTab[i]);
650 if (replace[i] == NULL) {
651 n = i + 1;
652 goto fail_process_args;
655 else
656 replace[i] = NULL;
658 else {
659 if (i == 0)
660 replace[i] = replace_str;
661 else
662 replace[i] = NULL;
665 if (replace[i] == NULL)
666 rlen[i] = 0;
667 else
668 rlen[i] = xmlStrlen(replace[i]);
671 if (i_empty >= 0 && rlen[i_empty] == 0)
672 i_empty = -1;
674 /* replace operation */
676 buf = xmlBufferCreate();
677 if (buf == NULL) {
678 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
679 goto fail_buffer;
681 src = string;
682 start = string;
684 while (*src != 0) {
685 int max_len = 0, i_match = 0;
687 for (i=0; i<n; ++i) {
688 if (*src == search[i][0] &&
689 slen[i] > max_len &&
690 xmlStrncmp(src, search[i], slen[i]) == 0)
692 i_match = i;
693 max_len = slen[i];
697 if (max_len == 0) {
698 if (i_empty >= 0 && start < src) {
699 if (xmlBufferAdd(buf, start, src - start) ||
700 xmlBufferAdd(buf, replace[i_empty], rlen[i_empty]))
702 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
703 goto fail_buffer_add;
705 start = src;
708 src += xmlUTF8Size(src);
710 else {
711 if ((start < src &&
712 xmlBufferAdd(buf, start, src - start)) ||
713 (rlen[i_match] &&
714 xmlBufferAdd(buf, replace[i_match], rlen[i_match])))
716 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
717 goto fail_buffer_add;
720 src += slen[i_match];
721 start = src;
725 if (start < src && xmlBufferAdd(buf, start, src - start)) {
726 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR);
727 goto fail_buffer_add;
730 /* create result node set */
732 exsltStrReturnString(ctxt, xmlBufferContent(buf), xmlBufferLength(buf));
734 /* clean up */
736 fail_buffer_add:
737 xmlBufferFree(buf);
739 fail_buffer:
740 fail_process_args:
741 if (search_set != NULL) {
742 for (i=0; i<n; ++i)
743 xmlFree(search[i]);
745 if (replace_set != NULL) {
746 for (i=0; i<n; ++i) {
747 if (replace[i] != NULL)
748 xmlFree(replace[i]);
752 if (mem != NULL)
753 xmlFree(mem);
755 fail_malloc:
756 done_empty_search:
757 xmlFree(string);
759 fail_string:
760 if (search_set != NULL)
761 xmlXPathFreeNodeSet(search_set);
762 else
763 xmlFree(search_str);
765 fail_search:
766 if (replace_set != NULL)
767 xmlXPathFreeNodeSet(replace_set);
768 else
769 xmlFree(replace_str);
771 fail_replace:
772 return;
776 * exsltStrRegister:
778 * Registers the EXSLT - Strings module
781 void
782 exsltStrRegister (void) {
783 xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",
784 EXSLT_STRINGS_NAMESPACE,
785 exsltStrTokenizeFunction);
786 xsltRegisterExtModuleFunction ((const xmlChar *) "split",
787 EXSLT_STRINGS_NAMESPACE,
788 exsltStrSplitFunction);
789 xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri",
790 EXSLT_STRINGS_NAMESPACE,
791 exsltStrEncodeUriFunction);
792 xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri",
793 EXSLT_STRINGS_NAMESPACE,
794 exsltStrDecodeUriFunction);
795 xsltRegisterExtModuleFunction ((const xmlChar *) "padding",
796 EXSLT_STRINGS_NAMESPACE,
797 exsltStrPaddingFunction);
798 xsltRegisterExtModuleFunction ((const xmlChar *) "align",
799 EXSLT_STRINGS_NAMESPACE,
800 exsltStrAlignFunction);
801 xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
802 EXSLT_STRINGS_NAMESPACE,
803 exsltStrConcatFunction);
804 xsltRegisterExtModuleFunction ((const xmlChar *) "replace",
805 EXSLT_STRINGS_NAMESPACE,
806 exsltStrReplaceFunction);
810 * exsltStrXpathCtxtRegister:
812 * Registers the EXSLT - Strings module for use outside XSLT
815 exsltStrXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
817 if (ctxt
818 && prefix
819 && !xmlXPathRegisterNs(ctxt,
820 prefix,
821 (const xmlChar *) EXSLT_STRINGS_NAMESPACE)
822 && !xmlXPathRegisterFuncNS(ctxt,
823 (const xmlChar *) "encode-uri",
824 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
825 exsltStrEncodeUriFunction)
826 && !xmlXPathRegisterFuncNS(ctxt,
827 (const xmlChar *) "decode-uri",
828 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
829 exsltStrDecodeUriFunction)
830 && !xmlXPathRegisterFuncNS(ctxt,
831 (const xmlChar *) "padding",
832 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
833 exsltStrPaddingFunction)
834 && !xmlXPathRegisterFuncNS(ctxt,
835 (const xmlChar *) "align",
836 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
837 exsltStrAlignFunction)
838 && !xmlXPathRegisterFuncNS(ctxt,
839 (const xmlChar *) "concat",
840 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
841 exsltStrConcatFunction)
842 && !xmlXPathRegisterFuncNS(ctxt,
843 (const xmlChar *) "replace",
844 (const xmlChar *) EXSLT_STRINGS_NAMESPACE,
845 exsltStrReplaceFunction)) {
846 return 0;
848 return -1;