From 0e9f7cb23616b1a84d8fe0ddb123354f37ecf895 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sat, 5 Jan 2008 18:36:44 +0000 Subject: [PATCH] Added SILC_STR_DELETE buffer format macro. --- CHANGES.RUNTIME | 6 ++++ lib/silcutil/silcbuffmt.c | 54 ++++++++++++++++++++++------ lib/silcutil/silcbuffmt.h | 47 +++++++++++++++++++++++- lib/silcutil/silctypes.h | 4 ++- lib/silcutil/tests/test_silcbuffmt.c | 19 +++++++++- 5 files changed, 116 insertions(+), 14 deletions(-) diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index b04693d6..0372c00a 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,9 @@ +Sat Jan 5 20:19:28 EET 2008 Pekka Riikonen + + * 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 * Added silc_buffer_equal to lib/silcutil/silcbuffer.h. diff --git a/lib/silcutil/silcbuffmt.c b/lib/silcutil/silcbuffmt.c index 559e7309..7f92c6bf 100644 --- a/lib/silcutil/silcbuffmt.c +++ b/lib/silcutil/silcbuffmt.c @@ -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)); diff --git a/lib/silcutil/silcbuffmt.h b/lib/silcutil/silcbuffmt.h index 32aa9bb6..0a01efbd 100644 --- a/lib/silcutil/silcbuffmt.h +++ b/lib/silcutil/silcbuffmt.h @@ -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 diff --git a/lib/silcutil/silctypes.h b/lib/silcutil/silctypes.h index f060a3e0..eabb83f0 100644 --- a/lib/silcutil/silctypes.h +++ b/lib/silcutil/silctypes.h @@ -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 */ diff --git a/lib/silcutil/tests/test_silcbuffmt.c b/lib/silcutil/tests/test_silcbuffmt.c index 16c4483c..052be536 100644 --- a/lib/silcutil/tests/test_silcbuffmt.c +++ b/lib/silcutil/tests/test_silcbuffmt.c @@ -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/'")); -- 2.24.0