Add routines for text trimming on both ends, substring, and string position.
authorThomas G. Lockhart
Tue, 29 Jul 1997 16:12:07 +0000 (16:12 +0000)
committerThomas G. Lockhart
Tue, 29 Jul 1997 16:12:07 +0000 (16:12 +0000)
Used to support SQL92 compatibility.

src/backend/utils/adt/oracle_compat.c
src/backend/utils/adt/varlena.c

index 7f509aa48c45383600985036b00d237fdd9db6a2..6082311c54aa3bd272e15e0380c6cd11d82ad78a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Edmund Mergl 
  *
- *  $Id: oracle_compat.c,v 1.6 1997/05/07 02:46:45 scrappy Exp $
+ *  $Id: oracle_compat.c,v 1.7 1997/07/29 16:12:01 thomas Exp $
  *
  */
 
@@ -15,6 +15,7 @@ text *upper(text *string);
 text *initcap(text *string);
 text *lpad(text *string1, int4 len, text *string2);
 text *rpad(text *string1, int4 len, text *string2);
+text *btrim(text *string, text *set);
 text *ltrim(text *string, text *set);
 text *rtrim(text *string, text *set);
 text *substr(text *string, int4 m, int4 n);
@@ -246,6 +247,81 @@ rpad(text *string1, int4 len, text *string2)
 }
 
 
+/********************************************************************
+ *
+ * btrim
+ *
+ * Syntax:
+ *
+ *   text *btrim(text *string, text *set)
+ *
+ * Purpose:
+ *
+ *   Returns string with characters removed from the front and back
+ *   up to the first character not in set.
+ *
+ ********************************************************************/
+
+text *
+btrim(text *string, text *set)
+{
+  text *ret;
+  char *ptr, *end, *ptr2, *end2;
+  int m;
+
+  if ((string == (text *)NULL) ||
+      ((m = VARSIZE(string) - VARHDRSZ) <= 0) ||
+      (set == (text *)NULL) ||
+      ((VARSIZE(set) - VARHDRSZ) <= 0))
+    return string;
+
+  ptr  = VARDATA(string);
+  ptr2 = VARDATA(set);
+  end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1;
+  
+  while (m--) {
+    while (ptr2 <= end2) {
+      if (*ptr == *ptr2) {
+        break;
+      }
+      ++ptr2;
+    }
+    if (*ptr != *ptr2) {
+      break;
+    }
+    ptr++;
+    ptr2 = VARDATA(set);
+  }
+
+  ++m;
+
+  end  = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1;
+  ptr2 = VARDATA(set);
+
+  while (m--) {
+    while (ptr2 <= end2) {
+      if (*end == *ptr2) {
+        break;
+      }
+      ++ptr2;
+    }
+    if (*end != *ptr2) {
+      break;
+    }
+    --end;
+    ptr2 = VARDATA(set);
+  }
+
+  ++m;
+
+  ret = (text *)palloc(VARHDRSZ + m);
+  VARSIZE(ret) = VARHDRSZ + m;
+  memcpy(VARDATA(ret),ptr,m);
+
+  return ret;
+} /* btrim() */
+
+
 /********************************************************************
  *
  * ltrim
@@ -265,7 +341,7 @@ text *
 ltrim(text *string, text *set)
 {
   text *ret;
-  char *ptr, *ptr2, *end2, *ptr_ret;
+  char *ptr, *ptr2, *end2;
   int m;
 
   if ((string == (text *)NULL) ||
@@ -297,11 +373,7 @@ ltrim(text *string, text *set)
   ret = (text *)palloc(VARHDRSZ + m);
   VARSIZE(ret) = VARHDRSZ + m;
 
-  ptr_ret = VARDATA(ret);
-
-  while (m--) {
-    *ptr_ret++ = *ptr++;
-  }
+  memcpy(VARDATA(ret),ptr,m);
 
   return ret;
 }
@@ -357,6 +429,9 @@ rtrim(text *string, text *set)
 
   ret = (text *)palloc(VARHDRSZ + m);
   VARSIZE(ret) = VARHDRSZ + m;
+#if FALSE
+  memcpy(VARDATA(ret),ptr-VARSIZE(ret)+m,m);
+#endif
 
   ptr_ret = VARDATA(ret) + m - 1;
 
@@ -454,11 +529,3 @@ translate(text *string, char from, char to)
 
 
 /* EOF */
-
-
-
-
-
-
-
-
index d33ea702bbb59a28fd0bc7e18f87da8d7b46759f..91bfdfaca230c4d8170a36f3455894599fe23c5d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.16 1997/06/11 05:18:02 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.17 1997/07/29 16:12:07 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -216,40 +216,81 @@ int textlen (text* t)
 /*
  * textcat -
  *    takes two text* and returns a text* that is the concatentation of 
- *  the two
- */
-
-/*
- * Rewrited by Sapa, [email protected]. 8-Jul-96.
+ *    the two.
+ *
+ * Rewritten by Sapa, [email protected]. 8-Jul-96.
+ * Updated by Thomas, [email protected] 1997-07-10.
+ * Allocate space for output in all cases.
+ * XXX - thomas 1997-07-10
+ * As in previous code, allow concatenation when one string is NULL.
+ * Is this OK?
  */
 
 text* 
 textcat(text* t1, text* t2)
 {
-    int len1, len2, newlen;
+    int len1, len2, len;
     char *ptr;
     text* result;
 
-    /* Check for NULL strings... */
-    if (t1 == NULL) return t2;
-    if (t2 == NULL) return t1;
+    if (!PointerIsValid(t1) && !PointerIsValid(t2))
+   return(NULL);
 
-    /* Check for ZERO-LENGTH strings... */
-    /* I use <= instead of == , I know - it's paranoia, but... */
-    if((len1 = VARSIZE(t1) - VARHDRSZ) <= 0) return t2;
-    if((len2 = VARSIZE(t2) - VARHDRSZ) <= 0) return t1;
+    len1 = (PointerIsValid(t1)? (VARSIZE(t1) - VARHDRSZ): 0);
+    if (len1 < 0) len1 = 0;
+    len2 = (PointerIsValid(t2)? (VARSIZE(t2) - VARHDRSZ): 0);
+    if (len2 < 0) len2 = 0;
 
-    result = (text *)palloc(newlen = len1 + len2 + VARHDRSZ);
+    result = PALLOC(len = len1 + len2 + VARHDRSZ);
 
     /* Fill data field of result string... */
-    memcpy(ptr = VARDATA(result), VARDATA(t1), len1);
-    memcpy(ptr + len1, VARDATA(t2), len2);
+    ptr = VARDATA(result);
+    if (PointerIsValid(t1)) memcpy(ptr, VARDATA(t1), len1);
+    if (PointerIsValid(t2)) memcpy(ptr + len1, VARDATA(t2), len2);
 
     /* Set size of result string... */
-    VARSIZE(result) = newlen;
+    VARSIZE(result) = len;
 
-    return result;
-}
+    return(result);
+} /* textcat() */
+
+/*
+ * textpos -
+ *    Return the position of the specified substring.
+ *    Implements the SQL92 POSITION() function.
+ *    Ref: A Guide To The SQL Standard, Date & Darwen, 1997
+ * - thomas 1997-07-27
+ */
+
+int32
+textpos(text* t1, text* t2)
+{
+    int pos;
+    int px, p;
+    int len1, len2;
+    char *p1, *p2;
+
+    if (!PointerIsValid(t1) || !PointerIsValid(t2))
+   return(0);
+
+    if (VARSIZE(t2) <= 0)
+   return(1);
+
+    len1 = (VARSIZE(t1) - VARHDRSZ);
+    len2 = (VARSIZE(t2) - VARHDRSZ);
+    p1 = VARDATA(t1);
+    p2 = VARDATA(t2);
+    pos = 0;
+    px = (len1 - len2);
+    for (p = 0; p <= px; p++) {
+   if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0)) {
+       pos = p + 1;
+       break;
+   };
+   p1++;
+    };
+    return(pos);
+} /* textpos() */
 
 /*
  * texteq      - returns 1 iff arguments are equal
@@ -269,15 +310,15 @@ texteq(struct varlena *arg1, struct varlena *arg2)
     a2p = arg2->vl_dat;
     /*
      * Varlenas are stored as the total size (data + size variable)
-     * followed by the data.  The size variable is an int32 so the
-     * length of the data is the total length less sizeof(int32)
+     * followed by the data.
+     * Use VARHDRSZ instead of explicit sizeof() - thomas 1997-07-10
      */
-    len -= sizeof(int32);
+    len -= VARHDRSZ;
     while (len-- != 0)
    if (*a1p++ != *a2p++)
        return((bool) 0);
     return((bool) 1);
-}
+} /* texteq() */
 
 bool
 textne(struct varlena *arg1, struct varlena *arg2)