Added SILC_STR_DELETE buffer format macro.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 5 Jan 2008 18:36:44 +0000 (18:36 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 5 Jan 2008 18:36:44 +0000 (18:36 +0000)
CHANGES.RUNTIME
lib/silcutil/silcbuffmt.c
lib/silcutil/silcbuffmt.h
lib/silcutil/silctypes.h
lib/silcutil/tests/test_silcbuffmt.c

index b04693d63cf5ba80b67676e7a79616a557dc04eb..0372c00a0d85e60a0037f195ebeca05e1b6b9c8f 100644 (file)
@@ -1,3 +1,9 @@
+Sat Jan  5 20:19:28 EET 2008  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added SILC_STR_DELETE buffer format macro.  Added support for
+         deleting data after regex match with SILC_STR_REGEX.  Affected
+         files are lib/silcutil/silcbuffmt.[ch].
+
 Sat Jan  5 18:00:06 EET 2008  Pekka Riikonen <priikone@silcnet.org>
 
        * Added silc_buffer_equal to lib/silcutil/silcbuffer.h.
index 559e7309d9cf700ce2cc9259dbe173ea7a4e60b4..7f92c6bf0dc2f84fd6c138ed772436932b217b35 100644 (file)
@@ -99,11 +99,11 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
       {
        const char *regex = va_arg(ap, char *);
        SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
-       SilcBufferStruct match, saved;
+       SilcBufferStruct match;
        SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
        SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
        SilcBool ret;
-       SilcUInt32 inclusive_pos = 0;
+       SilcUInt32 saved_pos = 0, inclusive_pos = 0;
        int matched = 0, ret_len;
        va_list cp;
 
@@ -113,13 +113,11 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
        if (!regex)
          goto fail;
 
-       memset(&saved, 0, sizeof(saved));
-
        if (match_nl) {
        start_nl_match:
          /* Match for '\n' in the buffer.  If not found, treat as line
             without '\n' (buffer has only one line, or this is last line). */
-         saved = *dst;
+         saved_pos = silc_buffer_headlen(dst) + silc_buffer_len(dst);
          if (silc_regex_buffer(dst, "\n", &match, NULL))
            dst->tail = match.tail;
        }
@@ -178,7 +176,9 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
          flen += (dst->tail - dst->data);
          if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
            goto fail;
-         if (!silc_buffer_pull_tail(dst, (saved.tail - dst->tail)))
+         if (!silc_buffer_pull_tail(dst, (saved_pos -
+                                          silc_buffer_headlen(dst) +
+                                          silc_buffer_len(dst))))
            goto fail;
 
          if (silc_buffer_len(dst) > 0)
@@ -388,6 +388,34 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
       }
       break;
 
+    case SILC_PARAM_DELETE:
+      {
+       int n = va_arg(ap, int);
+
+       if (!process)
+         break;
+
+       if (n == -1) {
+         /* Move all data from tail to data area */
+         if (dst->data != dst->tail) {
+           memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
+           memset(dst->end - silc_buffer_len(dst), 0, silc_buffer_len(dst));
+           silc_buffer_push_tail(dst, silc_buffer_len(dst));
+         }
+         break;
+       }
+
+       if (n > silc_buffer_len(dst))
+         goto fail;
+
+       memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
+               silc_buffer_taillen(dst));
+       memset(dst->end - n, 0, n);
+       silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
+
+       break;
+      }
+
     case SILC_PARAM_OFFSET:
       {
        int offst = va_arg(ap, int);
@@ -538,11 +566,11 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
       {
        const char *regex = va_arg(ap, char *);
        SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
-       SilcBufferStruct match, saved;
+       SilcBufferStruct match;
        SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
        SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
        SilcBool ret;
-       SilcUInt32 inclusive_pos = 0;
+       SilcUInt32 saved_pos = 0, inclusive_pos = 0;
        int matched = 0, ret_len;
        va_list cp;
 
@@ -552,13 +580,12 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
        if (!regex)
          goto fail;
 
-       memset(&saved, 0, sizeof(saved));
 
        if (match_nl) {
        start_nl_match:
          /* Match for '\n' in the buffer.  If not found, treat as line
             without '\n' (buffer has only one line, or this is last line). */
-         saved = *src;
+         saved_pos = silc_buffer_headlen(src) + silc_buffer_len(src);
          if (silc_regex_buffer(src, "\n", &match, NULL))
            src->tail = match.tail;
        }
@@ -617,7 +644,9 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
          UNFORMAT_HAS_SPACE(src, src->tail - src->data);
          if (!silc_buffer_pull(src, (src->tail - src->data)))
            goto fail;
-         if (!silc_buffer_pull_tail(src, (saved.tail - src->tail)))
+         if (!silc_buffer_pull_tail(src, (saved_pos -
+                                          silc_buffer_headlen(src) +
+                                          silc_buffer_len(src))))
            goto fail;
 
          if (silc_buffer_len(src) > 0)
@@ -1096,6 +1125,9 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
       goto ok;
       break;
 
+    case SILC_PARAM_DELETE:
+      break;
+
     default:
       SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
                      "format the data.", fmt));
index 32aa9bb69a77f9493a0744ba17c2b690e82774d9..0a01efbd75c41e37658c7c179ce76693da1b2f66 100644 (file)
@@ -876,13 +876,22 @@ typedef enum {
  *
  *    // sed 's/foo/barbar/g', replace all foo's with barbar, without
  *    // overwriting any data in the buffer, but appending it.  The match
- *    // must be SILC_STR_REGEX_INCLUSIVE to make appending work.
+ *    // must be inclusive to make appending work.
  *    silc_buffer_format(buffer,
  *                       SILC_STR_REGEX("foo", SILC_STR_REGEX_ALL |
  *                                             SILC_STR_REGEX_INCLUSIVE),
  *                         SILC_STR_STRING_APPEND("barbar"),
  *                       SILC_STR_END, SILC_STR_END);
  *
+ *    // sed 's/foo/B/', replace foo with B, deleting rest of the match from
+ *    // the buffer.  The match must be inclusive to make deleting work.
+ *    silc_buffer_format(buffer,
+ *                       SILC_STR_REGEX("foo", SILC_STR_REGEX_ALL |
+ *                                             SILC_STR_REGEX_INCLUSIVE),
+ *                         SILC_STR_STRING("B"),
+ *                         SILC_STR_DELETE(-1),
+ *                       SILC_STR_END, SILC_STR_END);
+ *
  *    // sed '/baz/s/foo/bar/g, replace all foo's with bar on lines with baz
  *    silc_buffer_format(buffer,
  *                       SILC_STR_REGEX("baz", SILC_STR_REGEX_NL),
@@ -905,6 +914,42 @@ typedef enum {
  ***/
 #define SILC_STR_REGEX(regex, flags) SILC_PARAM_REGEX, (regex), (flags)
 
+/****d* silcutil/SilcBufferFormatAPI/SILC_STR_DELETE
+ *
+ * NAME
+ *
+ *    #define SILC_STR_DELETE(n) ...
+ *
+ * DESCRIPTION
+ *
+ *    Deletes bytes from the buffer by moving data in order to delete it.
+ *    The size of the buffer remains same but the tail area of the buffer
+ *    will get larger as data is deleted from the current data area.
+ *
+ *    The `n' specifies the number of bytes to delete from the current
+ *    data area.  If `n' is -1 this deletes all bytes from the data area.
+ *    This effectively moves the data from the tail area into the current
+ *    data area.  The length of the data area after this is 0 and the tail
+ *    area is larger.
+ *
+ *    Use this only for formatting.
+ *
+ *    Formatting:  SILC_STR_DELETE(int bytes)
+ *
+ * EXAMPLE
+ *
+ *    // sed 's/foo/B/', replace foo with B, deleting rest of the match from
+ *    // the buffer.  The match must be inclusive to make deleting work.
+ *    silc_buffer_format(buffer,
+ *                       SILC_STR_REGEX("foo", SILC_STR_REGEX_ALL |
+ *                                             SILC_STR_REGEX_INCLUSIVE),
+ *                         SILC_STR_STRING("B"),
+ *                         SILC_STR_DELETE(-1),
+ *                       SILC_STR_END, SILC_STR_END);
+ *
+ ***/
+#define SILC_STR_DELETE(x) SILC_PARAM_DELETE, (x)
+
 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
  *
  * NAME
index f060a3e08f80e04d1b6a2815b6fb8d8a706d149c..eabb83f032537e6f6906463bcf8d336a55045da8 100644 (file)
@@ -299,7 +299,8 @@ typedef SilcUInt32 SilcParam;
 #define SILC_PARAM_END           0xfeeefff1     /* End of parameters */
 /***/
 
-/* Internal parameter types, not publicly documented */
+/* Internal parameter types, not publicly documented, used mainly by the
+   SILC Buffer Format API (silcbuffmt.h). */
 #define SILC_PARAM_UI8_STRING    100           /* String (max len 8-bits) */
 #define SILC_PARAM_UI16_STRING   101           /* String (max len 16-bits) */
 #define SILC_PARAM_UI32_STRING   102           /* String (max len 32-bits) */
@@ -313,6 +314,7 @@ typedef SilcUInt32 SilcParam;
 #define SILC_PARAM_OFFSET_START  110
 #define SILC_PARAM_OFFSET_END    111
 #define SILC_PARAM_APPEND        112
+#define SILC_PARAM_DELETE        113
 #define SILC_PARAM_ALLOC         0x00010000     /* Allocate, bitmask */
 
 /* Macros */
index 16c4483cf9cc554bdc8cfd7b6a30d9a7aafd9e23..052be536edc8460f2a1535ad900d8d05682409bb 100644 (file)
@@ -15,7 +15,7 @@ int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
   char string[1024], *astring;
-  SilcBufferStruct buf, buf2;
+  SilcBufferStruct buf;
 
   if (argc > 1 && !strcmp(argv[1], "-d")) {
     silc_log_debug(TRUE);
@@ -55,6 +55,23 @@ int main(int argc, char **argv)
     goto err;
   silc_buffer_purge(&buf);
 
+  silc_snprintf(string, sizeof(string), "This is foobar string foo!!");
+  astring = silc_memdup(string, strlen(string));
+  silc_buffer_set(&buf, astring, strlen(astring) + 1);
+  SILC_LOG_DEBUG(("sed 's/foo//g'"));
+  SILC_LOG_DEBUG(("string: %s", astring));
+  if (silc_buffer_format(&buf,
+                        SILC_STR_REGEX("foo", SILC_STR_REGEX_ALL |
+                                              SILC_STR_REGEX_INCLUSIVE),
+                          SILC_STR_DELETE(-1),
+                        SILC_STR_END,
+                        SILC_STR_END) < 0)
+    goto err;
+  silc_buffer_printf(&buf, TRUE);
+  if (strcmp("This is bar string !!", silc_buffer_data(&buf)))
+    goto err;
+  silc_buffer_purge(&buf);
+
   silc_snprintf(string, sizeof(string), "This is foobar\n");
   silc_buffer_set(&buf, string, strlen(string));
   SILC_LOG_DEBUG(("sed 's/\\n/\\0/'"));