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 { \
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 saved_pos = 0, inclusive_pos = 0;
int matched = 0, ret_len;
va_list cp;
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;
}
}
if (rflags & SILC_STR_REGEX_INCLUSIVE) {
- saved_incl = dst->tail;
+ inclusive_pos = dst->tail - match.tail;
dst->tail = match.tail;
}
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;
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)
/* 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:
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_UI8_STRING | SILC_PARAM_APPEND:
+ case SILC_PARAM_UI16_STRING | SILC_PARAM_APPEND:
+ case SILC_PARAM_UI32_STRING | SILC_PARAM_APPEND:
+ {
+ char *x = va_arg(ap, char *);
+ SilcUInt32 tmp_len = x ? strlen(x) : 0;
+
+ if (!process)
+ break;
+
+ if (x && tmp_len) {
+ FORMAT_HAS_SPACE_APPEND(stack, dst, tmp_len);
+ silc_buffer_put(dst, x, tmp_len);
silc_buffer_pull(dst, tmp_len);
}
break;
}
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);
{
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 saved_pos = 0, inclusive_pos = 0;
int matched = 0, ret_len;
va_list cp;
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;
}
}
if (rflags & SILC_STR_REGEX_INCLUSIVE) {
- saved_incl = src->tail;
+ inclusive_pos = src->tail - match.tail;
src->tail = match.tail;
}
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);
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)
goto ok;
break;
+ case SILC_PARAM_DELETE:
+ break;
+
default:
SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
"format the data.", fmt));