[libxml2] Normalize XPath strings in-place



commit 57b81c208cd066c078b2efb158c7f0b60360e7dd
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Sat Mar 5 18:20:29 2022 +0100

    Normalize XPath strings in-place
    
    Simplify the code and fix a potential memory leak.
    
    Fixes #343.

 result/XPath/expr/strings | 24 +++++++++++++++++
 test/XPath/expr/strings   |  8 ++++++
 xpath.c                   | 65 +++++++++++++++++++++--------------------------
 3 files changed, 61 insertions(+), 36 deletions(-)
---
diff --git a/result/XPath/expr/strings b/result/XPath/expr/strings
index 4b0125cf..5527b506 100644
--- a/result/XPath/expr/strings
+++ b/result/XPath/expr/strings
@@ -150,3 +150,27 @@ Object is a number : 0
 ========================
 Expression: string-length("titi")
 Object is a number : 4
+
+========================
+Expression: normalize-space("  abc  def  ")
+Object is a string : abc def
+
+========================
+Expression: normalize-space("  abc  def")
+Object is a string : abc def
+
+========================
+Expression: normalize-space("abc  def  ")
+Object is a string : abc def
+
+========================
+Expression: normalize-space(" abcdef   ")
+Object is a string : abcdef
+
+========================
+Expression: normalize-space("   abcdef")
+Object is a string : abcdef
+
+========================
+Expression: normalize-space("abcdef ")
+Object is a string : abcdef
diff --git a/test/XPath/expr/strings b/test/XPath/expr/strings
index c741ee25..ef292514 100644
--- a/test/XPath/expr/strings
+++ b/test/XPath/expr/strings
@@ -36,3 +36,11 @@ substring("12345",-0.7,4)
 substring("12345",-5000000000,5000000004)
 string-length("")
 string-length("titi")
+normalize-space("  abc  def  ")
+normalize-space("  abc  def")
+normalize-space("abc  def  ")
+normalize-space(" abcdef   ")
+normalize-space("   abcdef")
+normalize-space("abcdef ")
+
+
diff --git a/xpath.c b/xpath.c
index 314cd91f..61e34e6d 100644
--- a/xpath.c
+++ b/xpath.c
@@ -9226,52 +9226,45 @@ xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
  */
 void
 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
-  xmlXPathObjectPtr obj = NULL;
-  xmlChar *source = NULL;
-  xmlBufPtr target;
-  xmlChar blank;
-
-  if (ctxt == NULL) return;
-  if (nargs == 0) {
-    /* Use current context node */
-      valuePush(ctxt,
-         xmlXPathCacheWrapString(ctxt->context,
-           xmlXPathCastNodeToString(ctxt->context->node)));
-    nargs = 1;
-  }
+    xmlChar *source, *target;
+    int blank;
 
-  CHECK_ARITY(1);
-  CAST_TO_STRING;
-  CHECK_TYPE(XPATH_STRING);
-  obj = valuePop(ctxt);
-  source = obj->stringval;
+    if (ctxt == NULL) return;
+    if (nargs == 0) {
+        /* Use current context node */
+        valuePush(ctxt,
+            xmlXPathCacheWrapString(ctxt->context,
+                xmlXPathCastNodeToString(ctxt->context->node)));
+        nargs = 1;
+    }
 
-  target = xmlBufCreate();
-  if (target && source) {
+    CHECK_ARITY(1);
+    CAST_TO_STRING;
+    CHECK_TYPE(XPATH_STRING);
+    source = ctxt->value->stringval;
+    if (source == NULL)
+        return;
+    target = source;
 
     /* Skip leading whitespaces */
     while (IS_BLANK_CH(*source))
-      source++;
+        source++;
 
     /* Collapse intermediate whitespaces, and skip trailing whitespaces */
     blank = 0;
     while (*source) {
-      if (IS_BLANK_CH(*source)) {
-       blank = 0x20;
-      } else {
-       if (blank) {
-         xmlBufAdd(target, &blank, 1);
-         blank = 0;
-       }
-       xmlBufAdd(target, source, 1);
-      }
-      source++;
+        if (IS_BLANK_CH(*source)) {
+           blank = 1;
+        } else {
+            if (blank) {
+                *target++ = 0x20;
+                blank = 0;
+            }
+            *target++ = *source;
+        }
+        source++;
     }
-    valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
-       xmlBufContent(target)));
-    xmlBufFree(target);
-  }
-  xmlXPathReleaseObject(ctxt->context, obj);
+    *target = 0;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]