X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcbuffmt.c;h=6534696384896110510b0844fa623379fb38f49b;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=366c4478fa9d84eecaa579c2ac4a5ab76c2998cb;hpb=f2462c5dd7e885e3daa00066fbf53e166fd361e0;p=silc.git diff --git a/lib/silcutil/silcbuffmt.c b/lib/silcutil/silcbuffmt.c index 366c4478..65346963 100644 --- a/lib/silcutil/silcbuffmt.c +++ b/lib/silcutil/silcbuffmt.c @@ -31,6 +31,16 @@ do { \ flen += req; \ } while(0) +/* Check that buffer has enough room to format data in it, if not + allocate more. This will append, thus not replacing any existing data. */ +#define FORMAT_HAS_SPACE_APPEND(s, b, req) \ +do { \ + if (silc_buffer_len(b) < req) \ + if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \ + goto fail; \ + flen += req; \ +} while(0) + /* Check that there is data to be unformatted */ #define UNFORMAT_HAS_SPACE(b, req) \ do { \ @@ -39,11 +49,89 @@ do { \ goto fail; \ } \ if (silc_unlikely((req + 1) <= 0)) { \ - silc_set_errno(SILC_ERR_UNDERFLOW); \ + silc_set_errno(SILC_ERR_OVERFLOW); \ goto fail; \ } \ } while(0) +#if defined(SILC_DEBUG) +static const char *silc_param_string(SilcParam fmt) +{ + if (fmt == SILC_PARAM_SINT8) + return "SINT8"; + if (fmt == SILC_PARAM_UINT8) + return "UINT8"; + if (fmt == SILC_PARAM_SINT16) + return "SINT16"; + if (fmt == SILC_PARAM_UINT16) + return "UINT16"; + if (fmt == SILC_PARAM_SINT32) + return "SINT32"; + if (fmt == SILC_PARAM_UINT32) + return "UINT32"; + if (fmt == SILC_PARAM_SINT64) + return "SINT64"; + if (fmt == SILC_PARAM_UINT64) + return "UINT64"; + if (fmt == SILC_PARAM_SICHAR) + return "SICHAR"; + if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC)) + return "SICHAR ALLOC"; + if (fmt == SILC_PARAM_UICHAR) + return "UICHAR"; + if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC)) + return "UICHAR ALLOC"; + if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE)) + return "UICHAR REPLACE"; + if (fmt == SILC_PARAM_BUFFER) + return "BUFFER"; + if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC)) + return "BUFFER ALLOC"; + if (fmt == SILC_PARAM_PTR) + return "PTR"; + if (fmt == SILC_PARAM_END) + return "END"; + if (fmt == SILC_PARAM_UI8_STRING) + return "UI8_STRING"; + if (fmt == SILC_PARAM_UI16_STRING) + return "UI16_STRING"; + if (fmt == SILC_PARAM_UI32_STRING) + return "UI32_STRING"; + if (fmt == SILC_PARAM_UI8_NSTRING) + return "UI8_STRING"; + if (fmt == SILC_PARAM_UI16_NSTRING) + return "UI16_STRING"; + if (fmt == SILC_PARAM_UI32_NSTRING) + return "UI32_STRING"; + if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC)) + return "UI8_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC)) + return "UI16_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC)) + return "UI32_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC)) + return "UI8_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC)) + return "UI16_STRING ALLOC"; + if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC)) + return "UI32_STRING"; + if (fmt == SILC_PARAM_OFFSET) + return "OFFSET"; + if (fmt == SILC_PARAM_ADVANCE) + return "ADDVANCE"; + if (fmt == SILC_PARAM_FUNC) + return "FUNC"; + if (fmt == SILC_PARAM_REGEX) + return "REGEX"; + if (fmt == SILC_PARAM_OFFSET_START) + return "OFFSET_START"; + if (fmt == SILC_PARAM_OFFSET_END) + return "OFFSET_END"; + if (fmt == SILC_PARAM_DELETE) + return "DELETE"; + return ""; +} +#endif /* SILC_DEBUG */ /******************************* Formatting *********************************/ @@ -58,7 +146,11 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, while (1) { fmt = va_arg(ap, SilcParam); - SILC_LOG_DEBUG(("Buffer format type %d", fmt)); +#if defined(SILC_DEBUG) + if (process) + SILC_LOG_DEBUG(("Buffer format type %s (%d)", + silc_param_string(fmt), fmt)); +#endif /* SILC_DEBUG */ switch (fmt) { case SILC_PARAM_FUNC: @@ -82,18 +174,18 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, silc_buffer_pull(dst, tmp_len); flen += tmp_len; } + break; } - break; case SILC_PARAM_REGEX: { 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; - unsigned char *saved_incl = NULL; + SilcUInt32 inclusive_pos = 0; int matched = 0, ret_len; va_list cp; @@ -101,15 +193,12 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, break; if (!regex) - goto fail; - - memset(&saved, 0, sizeof(saved)); + break; 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; if (silc_regex_buffer(dst, "\n", &match, NULL)) dst->tail = match.tail; } @@ -138,7 +227,7 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, } if (rflags & SILC_STR_REGEX_INCLUSIVE) { - saved_incl = dst->tail; + inclusive_pos = dst->tail - match.tail; dst->tail = match.tail; } @@ -150,7 +239,8 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, goto fail; if (rflags & SILC_STR_REGEX_INCLUSIVE) - dst->tail = saved_incl; + if (!silc_buffer_pull_tail(dst, inclusive_pos)) + goto fail; /* Advance buffer after formatting */ flen += ret_len; @@ -167,7 +257,7 @@ 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, silc_buffer_taillen(dst))) goto fail; if (silc_buffer_len(dst) > 0) @@ -176,8 +266,8 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, /* Skip to the next SILC_PARAM_END */ silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE); + break; } - break; case SILC_PARAM_UI8_STRING: case SILC_PARAM_UI16_STRING: @@ -194,12 +284,49 @@ int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap, if (x && tmp_len) { FORMAT_HAS_SPACE(stack, dst, tmp_len); - silc_buffer_put(dst, (unsigned char *)x, tmp_len); + silc_buffer_put(dst, x, tmp_len); silc_buffer_pull(dst, tmp_len); } break; } + case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE: + { + unsigned char *x = va_arg(ap, unsigned char *); + SilcUInt32 x_len = va_arg(ap, SilcUInt32); + + if (!process) + break; + + if (!x) + break; + + if (silc_buffer_len(dst) == x_len) { + /* Replace */ + if (x_len) { + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + flen += x_len; + } + } else if (silc_buffer_len(dst) < x_len) { + /* Append */ + if (x_len) { + FORMAT_HAS_SPACE_APPEND(stack, dst, x_len); + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + } + } else { + /* Delete */ + if (x_len) { + silc_buffer_put(dst, x, x_len); + silc_buffer_pull(dst, x_len); + flen += x_len; + } + goto delete_rest; + } + break; + } + case SILC_PARAM_UI8_NSTRING: case SILC_PARAM_UI16_NSTRING: case SILC_PARAM_UI32_NSTRING: @@ -359,6 +486,39 @@ 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) { + delete_rest: + n = silc_buffer_len(dst); + memmove(dst->data, dst->tail, silc_buffer_taillen(dst)); + silc_buffer_push_tail(dst, n); + if (!silc_buffer_srealloc(stack, dst, + silc_buffer_truelen(dst) - n)) + goto fail; + } + break; + } + + if (n > silc_buffer_len(dst)) + goto fail; + + memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) + + silc_buffer_taillen(dst)); + silc_buffer_push_tail(dst, silc_buffer_len(dst) - n); + if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n)) + goto fail; + + break; + } + case SILC_PARAM_OFFSET: { int offst = va_arg(ap, int); @@ -479,7 +639,8 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, while (1) { fmt = va_arg(ap, SilcParam); - SILC_LOG_DEBUG(("Buffer unformat type %d", fmt)); + SILC_LOG_DEBUG(("Buffer unformat type %s (%d)", + silc_param_string(fmt), fmt)); switch (fmt) { case SILC_PARAM_FUNC: @@ -509,11 +670,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; - unsigned char *saved_incl = NULL; + SilcUInt32 inclusive_pos = 0; int matched = 0, ret_len; va_list cp; @@ -521,15 +682,12 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, break; if (!regex) - goto fail; - - memset(&saved, 0, sizeof(saved)); + break; 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; if (silc_regex_buffer(src, "\n", &match, NULL)) src->tail = match.tail; } @@ -552,13 +710,12 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) { /* Advance buffer after match */ - UNFORMAT_HAS_SPACE(src, (match.data - src->data)); if (!silc_buffer_pull(src, (match.data - src->data))) goto fail; } if (rflags & SILC_STR_REGEX_INCLUSIVE) { - saved_incl = src->tail; + inclusive_pos = src->tail - match.tail; src->tail = match.tail; } @@ -570,10 +727,10 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, goto fail; if (rflags & SILC_STR_REGEX_INCLUSIVE) - src->tail = saved_incl; + if (!silc_buffer_pull_tail(src, inclusive_pos)) + goto fail; /* Advance buffer after formatting */ - UNFORMAT_HAS_SPACE(src, ret_len); if (!silc_buffer_pull(src, ret_len)) goto fail; @@ -584,10 +741,9 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, if (match_nl) { /* Go to next line, it is at the end of the data area. Adjust the tail area of the target buffer to show rest of the buffer. */ - 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, silc_buffer_taillen(src))) goto fail; if (silc_buffer_len(src) > 0) @@ -596,6 +752,7 @@ int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap, /* Skip to the next SILC_PARAM_END */ silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE); + break; } break; @@ -1066,6 +1223,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));