X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcbuffmt.h;h=32aa9bb69a77f9493a0744ba17c2b690e82774d9;hp=d1745d1a8b85428111d01a858b68ba1d89094f7f;hb=38b10925eeea619c2b6fa646892df4416e6dd08f;hpb=b04c7fe6184af5fb9d51008c12e785de7c97a0ee diff --git a/lib/silcutil/silcbuffmt.h b/lib/silcutil/silcbuffmt.h index d1745d1a..32aa9bb6 100644 --- a/lib/silcutil/silcbuffmt.h +++ b/lib/silcutil/silcbuffmt.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,9 +23,19 @@ * * SILC Buffer Format API provides functions for formatting different data * types into a buffer and retrieving different data types from a buffer - * into specified data types. It is especially useful to format packets, + * into specified data types. It is especially useful to encode packets, * protocol payloads and such. * + * It also provides many advanced features like calling user specified + * encoder and decoder functions that are free to do anything to the buffer. + * The API also provides powerful regular expression matching capabilities + * within the buffer, enabling caller to not only match regular expressions + * but to make the API behave like Stream Editor (Sed) and Awk. The buffer + * can be matched against regular expression and then edited. Caller can + * do anything they want to the buffer after a match. The SILC_STR_REGEX + * macro provides many different flags that can change the behavior of the + * matching, with capabilities to also mimic Sed behavior. + * * As the SilcBuffer API is not thread-safe these routines may not be used * in multithreaded environment with a same SilcBuffer context without * concurrency control. @@ -36,15 +46,21 @@ * * memset(&buffer, 0, sizeof(buffer)); * ret = silc_buffer_format(&buffer, - * SILC_STR_UI_INT(intval), - * SILC_STR_CHAR(charval), - * SILC_STR_UI_INT(intval), - * SILC_STR_SHORT(str_len), + * SILC_STR_UINT32(intval), + * SILC_STR_UINT8(charval), + * SILC_STR_UINT64(longintval), + * SILC_STR_UINT16(str_len), * SILC_STR_DATA(str, str_len), * SILC_STR_END); * if (ret < 0) * error; * + * // sed 's/foo/bar/', replace first foo with bar + * silc_buffer_format(buffer, + * SILC_STR_REGEX("foo", 0), + * SILC_STR_STRING("bar"), + * SILC_STR_END, SILC_STR_END); + * ***/ #ifndef SILCBUFFMT_H @@ -123,7 +139,7 @@ typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer, * Formats a buffer from a variable argument list. Returns -1 if the * system is out of memory and the length of the formatted buffer otherwise. * The buffer is enlarged automatically during formatting, if it doesn't - * already have enough space. + * already have enough space. Sets silc_errno in case of error. * * EXAMPLE * @@ -134,10 +150,10 @@ typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer, * * memset(&buffer, 0, sizeof(buffer)); * ret = silc_buffer_format(&buffer, - * SILC_STR_UI_INT(intval), - * SILC_STR_CHAR(charval), - * SILC_STR_UI_INT(intval), - * SILC_STR_SHORT(str_len), + * SILC_STR_UINT32(intval), + * SILC_STR_UINT8(charval), + * SILC_STR_UINT32(intval), + * SILC_STR_UINT16(str_len), * SILC_STR_DATA(str, str_len), * SILC_STR_END); * if (ret < 0) @@ -150,8 +166,8 @@ typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer, * SilcBuffer buf; * buf = silc_buffer_alloc(0); * ret = silc_buffer_format(buf, - * SILC_STR_UI_INT(intval), - * SILC_STR_CHAR(charval), + * SILC_STR_UINT32(intval), + * SILC_STR_UINT8(charval), * SILC_STR_END); * if (ret < 0) * error; @@ -163,7 +179,7 @@ typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer, * SilcBuffer buf; * buf = silc_buffer_alloc(2 + str_len); * ret = silc_buffer_format(buf, - * SILC_STR_UI_SHORT(str_len), + * SILC_STR_UINT16(str_len), * SILC_STR_DATA(str, str_len), * SILC_STR_END); * if (ret < 0) @@ -182,7 +198,7 @@ int silc_buffer_format(SilcBuffer dst, ...); * * Same as silc_buffer_format but uses `stack' to allocate the memory. * if `stack' is NULL reverts back to silc_buffer_format call. Returns - * -1 if system is out of memory. + * -1 if system is out of memory. Sets silc_errno in case of error. * * Note that this call consumes the `stack'. The caller should push the * stack before calling the function and pop it later. @@ -215,7 +231,7 @@ int silc_buffer_format_vp(SilcBuffer dst, va_list ap); * * Same as silc_buffer_format_vp but uses `stack' to allocate the memory. * if `stack' is NULL reverts back to silc_buffer_format_vp call. Returns - * -1 if system is out of memory. + * -1 if system is out of memory. Sets silc_errno in case of error. * * Note that this call consumes the `stack'. The caller should push the * stack before calling the function and pop it later. @@ -232,13 +248,14 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap); * DESCRIPTION * * Unformats a buffer from a variable argument list. Returns -1 on error - * and the length of the unformatted buffer otherwise. + * and the length of the unformatted buffer otherwise. Sets silc_errno + * in case of error. * * EXAMPLE * * ret = silc_buffer_unformat(buffer, - * SILC_STR_UI_INT(&intval), - * SILC_STR_CHAR(&charval), + * SILC_STR_UINT32(&intval), + * SILC_STR_UINT8(&charval), * SILC_STR_OFFSET(4), * SILC_STR_UI16_NSTRING_ALLOC(&str, &str_len), * SILC_STR_END); @@ -309,7 +326,8 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap); * be end with SILC_STRFMT_END argument. This allows that a string in * the list can be NULL, in which case it is skipped. This automatically * allocates the space for the buffer data but `dst' must be already - * allocated by the caller. Returns -1 if system is out of memory. + * allocated by the caller. Returns -1 if system is out of memory and + * sets silc_errno. * * EXAMPLE * @@ -335,7 +353,7 @@ int silc_buffer_strformat(SilcBuffer dst, ...); * allocates the space for the buffer data but `dst' must be already * allocated by the caller. This function is equivalent to * silc_buffer_strformat but allocates memory from `stack'. Returns -1 - * if system is out of memory. + * if system is out of memory and sets silc_errno. * * Note that this call consumes the `stack'. The caller should push the * stack before calling the function and pop it later. @@ -343,139 +361,210 @@ int silc_buffer_strformat(SilcBuffer dst, ...); ***/ int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...); -/****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT8 * * NAME * - * typedef enum { ... } SilcBufferParamType; + * #define SILC_STR_SINT8() ... * * DESCRIPTION * - * Buffer parameter types. These are not needed when formatting or - * unformatting buffers. Use the macros such as SILC_STR_UI_CHAR and - * others instead. These types may be used when describing what a - * buffer looks like, and how it may be formatted and unformatted. + * One 8-bit signed integer. * - * SOURCE - */ -typedef enum { - SILC_PARAM_SI8_CHAR, /* Signed 8-bit char */ - SILC_PARAM_UI8_CHAR, /* Unsigned 8-bit char */ - SILC_PARAM_SI16_SHORT, /* Signed 16-bit int */ - SILC_PARAM_UI16_SHORT, /* Unsigned 16-bit int */ - SILC_PARAM_SI32_INT, /* Signed 32-bit int */ - SILC_PARAM_UI32_INT, /* Unsigned 32-bit int */ - SILC_PARAM_SI64_INT, /* Signed 64-bit int */ - SILC_PARAM_UI64_INT, /* Unsigned 64-bit int */ - SILC_PARAM_UI8_STRING, /* String (max len 8-bits)*/ - SILC_PARAM_UI16_STRING, /* String (max len 16-bits) */ - SILC_PARAM_UI32_STRING, /* String (max len 32-bits) */ - SILC_PARAM_BUFFER, /* SilcBuffer */ - - /* Internal types */ - SILC_PARAM_DATA, /* Binary data */ - SILC_PARAM_UI8_NSTRING, /* String (max len 8-bits) */ - SILC_PARAM_UI16_NSTRING, /* String (max len 16-bits) */ - SILC_PARAM_UI32_NSTRING, /* String (max len 32-bits) */ - SILC_PARAM_UI8_STRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_UI16_STRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_UI32_STRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_UI8_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_UI16_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_UI32_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_DATA_ALLOC, /* Alloc + memcpy */ - SILC_PARAM_BUFFER_ALLOC, /* Alloc + memcpy */ - - SILC_PARAM_OFFSET, - SILC_PARAM_ADVANCE, - SILC_PARAM_FUNC, - - SILC_PARAM_UI_XNSTRING, - SILC_PARAM_UI_XNSTRING_ALLOC, - - SILC_PARAM_END -} SilcBufferParamType; -/***/ + * Formatting: SILC_STR_SINT8(SilcInt8) + * Unformatting: SILC_STR_SINT8(SilcInt8 *) + * + ***/ +#define SILC_STR_SINT8(x) SILC_PARAM_SINT8, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT8 + * + * NAME + * + * #define SILC_STR_UINT8() ... + * + * DESCRIPTION + * + * One 8-bit unsigned integer. + * + * Formatting: SILC_STR_UINT8(SilcUInt8) + * Unformatting: SILC_STR_UINT8(SilcUInt8 *) + * + ***/ +#define SILC_STR_UINT8(x) SILC_PARAM_UINT8, (x) + +/* Deprecated */ +#define SILC_STR_SI_CHAR(x) SILC_PARAM_SINT8, (x) +#define SILC_STR_UI_CHAR(x) SILC_PARAM_UINT8, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT16 + * + * NAME + * + * #define SILC_STR_SINT16() ... + * + * DESCRIPTION + * + * SilcInt16. + * + * Formatting: SILC_STR_SINT16(SilcInt16) + * Unformatting: SILC_STR_SINT16(SilcInt16 *) + * + ***/ +#define SILC_STR_SINT16(x) SILC_PARAM_SINT16, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT16 + * + * NAME + * + * #define SILC_STR_UINT16() ... + * + * DESCRIPTION + * + * SilcUInt16. + * + * Formatting: SILC_STR_UINT16(SilcUInt16) + * Unformatting: SILC_STR_UINT16(SilcUInt16 *) + * + ***/ +#define SILC_STR_UINT16(x) SILC_PARAM_UINT16, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR +/* Deprecated */ +#define SILC_STR_SI_SHORT(x) SILC_PARAM_SINT16, (x) +#define SILC_STR_UI_SHORT(x) SILC_PARAM_UINT16, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT32 * * NAME * - * #define SILC_STR_UI_CHAR() ... - * #define SILC_STR_SI_CHAR() ... + * #define SILC_STR_SINT32() ... * * DESCRIPTION * - * One signed/unsigned character. + * SilcInt32. * - * Formatting: SILC_STR_SI_CHAR(char) - * SILC_STR_UI_CHAR(unsigned char) - * Unformatting: SILC_STR_SI_CHAR(char *) - * SILC_STR_UI_CHAR(unsigned char *) + * Formatting: SILC_STR_SINT32(SilcInt32) + * Unformatting: SILC_STR_SINT32(SilcInt32 *) * ***/ -#define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x) -#define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x) +#define SILC_STR_SINT32(x) SILC_PARAM_SINT32, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT32 * * NAME * - * #define SILC_STR_UI_SHORT() ... - * #define SILC_STR_SI_SHORT() ... + * #define SILC_STR_UINT32() ... * * DESCRIPTION * - * SilcInt16/SilcUInt16. + * SilcUInt32. * - * Formatting: SILC_STR_SI_SHORT(SilcInt16) - * SILC_STR_UI_SHORT(SilcUInt16) - * Unformatting: SILC_STR_SI_SHORT(SilcInt16 *) - * SILC_STR_UI_SHORT(SilcUInt16 *) + * Formatting: SILC_STR_UINT32(SilcUInt32) + * Unformatting: SILC_STR_UINT32(SilcUInt32 *) * ***/ -#define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x) -#define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x) +#define SILC_STR_UINT32(x) SILC_PARAM_UINT32, (x) + +/* Deprecated */ +#define SILC_STR_SI_INT(x) SILC_PARAM_SINT32, (x) +#define SILC_STR_UI_INT(x) SILC_PARAM_UINT32, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT64 * * NAME * - * #define SILC_STR_UI_INT() ... - * #define SILC_STR_SI_INT() ... + * #define SILC_STR_SINT64() ... * * DESCRIPTION * - * SilcInt32/SilcUInt32. + * SilcInt64. * - * Formatting: SILC_STR_SI_INT(SilcInt32) - * SILC_STR_UI_INT(SilcUInt32) - * Unformatting: SILC_STR_SI_INT(SilcInt32 *) - * SILC_STR_UI_INT(SilcUInt32 *) + * Formatting: SILC_STR_SINT64(SilcInt64) + * Unformatting: SILC_STR_SINT64(SilcInt64 *) * ***/ -#define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x) -#define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x) +#define SILC_STR_SI_INT64(x) SILC_PARAM_SINT64, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64 +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT64 * * NAME * - * #define SILC_STR_UI_INT64() ... - * #define SILC_STR_SI_INT64() ... + * #define SILC_STR_UINT64() ... * * DESCRIPTION * - * SilcInt64/SilcUInt64. + * SilcUInt64. * - * Formatting: SILC_STR_SI_INT64(SilcInt64) - * SILC_STR_UI_INT64(SilcUInt64) - * Unformatting: SILC_STR_SI_INT64(SilcInt64 *) - * SILC_STR_UI_INT64(SilcUInt64 *) + * Formatting: SILC_STR_UINT64(SilcUInt64) + * Unformatting: SILC_STR_UINT64(SilcUInt64 *) * ***/ -#define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x) -#define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x) +#define SILC_STR_UI_INT64(x) SILC_PARAM_UINT64, (x) + +/* Deprecated */ +#define SILC_STR_SI_INT64(x) SILC_PARAM_SINT64, (x) +#define SILC_STR_UI_INT64(x) SILC_PARAM_UINT64, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_STRING + * + * NAME + * + * #define SILC_STR_STRING() ... + * + * DESCRIPTION + * + * Encode NULL terminated string. Use this only for formatting. + * + * Formatting: SILC_STR_STRING(char *) + * + * For unformatting use one of the SILC_STR_*_STRING macros, which + * automatically gets the length of the string from the buffer. Note + * SILC_STR_STRING does not save the length of the string into the buffer. + * The caller must do that in order for the unformatting macros to work. + * + * Example: + * + * Formatting: ..., SILC_STR_UINT32(strlen(string)), + * SILC_STR_STRING(string), ... + * Unformatting: ..., SILC_STR_UI32_STRING(&string), ... + * + ***/ +#define SILC_STR_STRING(x) SILC_PARAM_UI8_STRING, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_STRING_APPEND + * + * NAME + * + * #define SILC_STR_STRING_APPEND() ... + * + * DESCRIPTION + * + * Encode NULL terminated string and append it to the buffer without + * replacing any data if the end of the data area is reached before + * encoding the whole string. If buffer has tail area, it will not be + * replaced if the string is longer than the current data area, but the + * buffer will be enlarged and the tail area will be copied to the new + * tail area in order not to replace any data while appending the string. + * This will then enlarge the current data area. + * + * Use this only for formatting. + * + * Formatting: SILC_STR_STRING_APPEND(char *) + * + * For unformatting use one of the SILC_STR_*_STRING macros, which + * automatically gets the length of the string from the buffer. Note + * SILC_STR_STRING_APPEND does not save the length of the string into the + * buffer. The caller must do that in order for the unformatting macros + * to work. + * + * Example: + * + * Formatting: ..., SILC_STR_UINT32(strlen(string)), + * SILC_STR_STRING_APPEND(string), ... + * Unformatting: ..., SILC_STR_UI32_STRING(&string), ... + * + ***/ +#define SILC_STR_STRING_APPEND(x) SILC_PARAM_UI8_STRING | SILC_PARAM_APPEND, (x) /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING * @@ -499,33 +588,32 @@ typedef enum { * * Unformatting procedure will check for length of the string from the * buffer before trying to get the string out. Thus, one *must* format the - * length as UI_INT or UI_SHORT into the buffer *before* formatting the - * actual string to the buffer, and, in unformatting one must ignore the + * length as UINT32 or UINT16 or UINT8 into the buffer *before* formatting + * the actual string to the buffer, and, in unformatting one ignores the * length of the string because unformatting procedure will take it * automatically. * * Example: * - * Formatting: ..., SILC_STR_UI_INT(strlen(string)), + * Formatting: ..., SILC_STR_UINT32(strlen(string)), * SILC_STR_UI32_STRING(string), ... * Unformatting: ..., SILC_STR_UI32_STRING(&string), ... * * I.e., you can ignore the formatted length field in unformatting. * * UI8, UI16 and UI32 means that the length is considered to be - * either char (8 bits), short (16 bits) or int (32 bits) in - * unformatting. + * either UINT8, UINT16 or UINT32 in unformatting. * * _ALLOC routines automatically allocates memory for the variable sent * as argument in unformatting. * ***/ #define SILC_STR_UI8_STRING(x) SILC_PARAM_UI8_STRING, (x) -#define SILC_STR_UI8_STRING_ALLOC(x) SILC_PARAM_UI8_STRING_ALLOC, (x) +#define SILC_STR_UI8_STRING_ALLOC(x) SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC, (x) #define SILC_STR_UI16_STRING(x) SILC_PARAM_UI16_STRING, (x) -#define SILC_STR_UI16_STRING_ALLOC(x) SILC_PARAM_UI16_STRING_ALLOC, (x) +#define SILC_STR_UI16_STRING_ALLOC(x) SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC, (x) #define SILC_STR_UI32_STRING(x) SILC_PARAM_UI32_STRING, (x) -#define SILC_STR_UI32_STRING_ALLOC(x) SILC_PARAM_UI32_STRING_ALLOC, (x) +#define SILC_STR_UI32_STRING_ALLOC(x) SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC, (x) /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING * @@ -547,14 +635,14 @@ typedef enum { * * Unformatting procedure will check for length of the string from the * buffer before trying to get the string out. Thus, one *must* format the - * length as UI_INT or UI_SHORT into the buffer *before* formatting the - * actual string to the buffer, and, in unformatting one must ignore the + * length as UINT32 or UINT16 or UINT8 into the buffer *before* formatting + * the actual string to the buffer, and, in unformatting one ignores the * length of the string because unformatting procedure will take it * automatically. * * Example: * - * Formatting: ..., SILC_STR_UI_INT(strlen(string)), + * Formatting: ..., SILC_STR_UINT32(strlen(string)), * SILC_STR_UI32_NSTRING(string, strlen(string)), ... * Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ... * @@ -563,8 +651,7 @@ typedef enum { * argument (&len in above example). * * UI8, UI16 and UI32 means that the length is considered to be - * either char (8 bits), short (16 bits) or int (32 bits) in - * unformatting. + * either UINT8, UINT16 or UINT32 in unformatting. * * _ALLOC routines automatically allocates memory for the variable sent * as argument in unformatting. @@ -572,13 +659,13 @@ typedef enum { ***/ #define SILC_STR_UI8_NSTRING(x, l) SILC_PARAM_UI8_NSTRING, (x), (l) #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \ - SILC_PARAM_UI8_NSTRING_ALLOC, (x), (l) + SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC, (x), (l) #define SILC_STR_UI16_NSTRING(x, l) SILC_PARAM_UI16_NSTRING, (x), (l) #define SILC_STR_UI16_NSTRING_ALLOC(x, l) \ - SILC_PARAM_UI16_NSTRING_ALLOC, (x), (l) + SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC, (x), (l) #define SILC_STR_UI32_NSTRING(x, l) SILC_PARAM_UI32_NSTRING, (x), (l) #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \ - SILC_PARAM_UI32_NSTRING_ALLOC, (x), (l) + SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC, (x), (l) /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA * @@ -601,12 +688,12 @@ typedef enum { * as argument in unformatting. * ***/ -#define SILC_STR_DATA(x, l) SILC_PARAM_DATA, (x), (l) -#define SILC_STR_DATA_ALLOC(x, l) SILC_PARAM_DATA_ALLOC, (x), (l) +#define SILC_STR_DATA(x, l) SILC_PARAM_UICHAR, (x), (l) +#define SILC_STR_DATA_ALLOC(x, l) SILC_PARAM_UICHAR | SILC_PARAM_ALLOC, (x), (l) /* Deprecated */ -#define SILC_STR_UI_XNSTRING(x, l) SILC_PARAM_UI_XNSTRING, (x), (l) -#define SILC_STR_UI_XNSTRING_ALLOC(x, l) SILC_PARAM_UI_XNSTRING_ALLOC, (x), (l) +#define SILC_STR_UI_XNSTRING(x, l) SILC_PARAM_UICHAR, (x), (l) +#define SILC_STR_UI_XNSTRING_ALLOC(x, l) SILC_PARAM_UICHAR | SILC_PARAM_ALLOC, (x), (l) /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER * @@ -632,7 +719,7 @@ typedef enum { * ***/ #define SILC_STR_BUFFER(x) SILC_PARAM_BUFFER, (x) -#define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x) +#define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER | SILC_PARAM_ALLOC, (x) /****d* silcutil/SilcBufferFormatAPI/SILC_STR_FUNC * @@ -642,7 +729,7 @@ typedef enum { * * DESCRIPTION * - * SilcBuffer formatting. + * Formatting and unformatting of arbitrary data. * * Formatting: SILC_STR_FUNC(function, void *value, void *context) * Unformatting: SILC_STR_FUNC(function, void **value, void *context) @@ -668,7 +755,7 @@ typedef enum { * // Encode payload, encrypt and compute MAC. * silc_buffer_format(buf, * SILC_STR_FUNC(foo_encode_id, id, ctx), - * SILC_STR_UI_SHORT(len), + * SILC_STR_UINT16(len), * SILC_STR_DATA(data, len), * SILC_STR_FUNC(foo_buf_encrypt, NULL, key), * SILC_STR_FUNC(foo_buf_hmac, NULL, hmac), @@ -680,13 +767,144 @@ typedef enum { * SILC_STR_FUNC(foo_buf_hmac, NULL, hmac), * SILC_STR_FUNC(foo_buf_decrypt, NULL, key), * SILC_STR_FUNC(foo_decode_id, &id, ctx), - * SILC_STR_UI_SHORT(&len), + * SILC_STR_UINT16(&len), * SILC_STR_END); * ***/ #define SILC_STR_FUNC(func, val, context) SILC_PARAM_FUNC, \ func, (val), (context) +/****d* silcutil/SilcBufferFormatAPI/SilcBufferRegexFlags + * + * NAME + * + * typedef enum { ... } SilcBufferRegexFlags; + * + * DESCRIPTION + * + * Regular expression flags for SILC_STR_REGEX macro. The flags can be + * used to manipulate the behavior of the SILC_STR_REGEX. All flags + * may be combined unless otherwise stated. + * + * SOURCE + */ +typedef enum { + SILC_STR_REGEX_NONE = 0x00000000, + + /* By default mismatch will be skipped. Set this flag if mismatch should + cause error and stopping of the formatting/unformatting. */ + SILC_STR_REGEX_MISMATCH = 0x00000001, + + /* By default only the first match is found. Set this flag to find + all matches. */ + SILC_STR_REGEX_ALL = 0x00000002, + + /* By default the buffer position is advanced to the position of the + first match. Set this flag if the buffer should not be advanced to + the match. */ + SILC_STR_REGEX_NO_ADVANCE = 0x00000004, + + /* By default SILC_STR_REGEX performs the match on the whole buffer. Set + this flag to make it behave like sed and match line by line. Each line + must end with '\n'. If buffer doesn't have '\n' it is considered to be + one line. Note that, any formatting done immediately after SILC_STR_REGEX + block with this flag will be formatted to the end of the buffer (after + last line). Use SILC_STR_OFFSET* macros to change the position if + needed. Also note that, any encoding macro inside the SILC_STR_REGEX + block will see only the matched line (including '\n'), instead of whole + buffer after the match. */ + SILC_STR_REGEX_NL = 0x00000008, + + /* Set this flag to not match the regular expression, but to match everything + else. When combined with SILC_STR_REGEX_NL this flag matches all other + lines except the ones with matching regular expression. */ + SILC_STR_REGEX_NOT = 0x00000010, + + /* By default the buffer is advanced to the first match and the rest of the + buffer remains as is. Set this flag to pass the exact match to the + SILC_STR_* macros in the SILC_STR_REGEX block; macros see the start of + the match and the end of the match, but not rest of the buffer (ie. with + match 'foo' the size of the buffer is 3 bytes). */ + SILC_STR_REGEX_INCLUSIVE = 0x00000020, +} SilcBufferRegexFlags; +/***/ + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_REGEX + * + * NAME + * + * #define SILC_STR_REGEX() ... + * + * DESCRIPTION + * + * Regular expression matching within the buffer. + * + * Formatting: SILC_STR_REGEX(char *regex, SilcBufferRegexFlags flags) + * Unformatting: SILC_STR_REGEX(char *regex, SilcBufferRegexFlags flags) + * + * SILC_STR_REGEX can be used to do regular expression matching within + * the SilcBuffer. When the string in the buffer matches the regular + * expression the position of the buffer is advanced to the position of + * the first match (rest of the buffer remains intact). If the regular + * expression does not match it is skipped, unless the flags specify + * otherwise. If flags are not needed they can be set to 0. + * + * In addition of matching regular expressions it can be used in a + * Stream Editor (sed) and Awk like fashion. The regular expression can be + * matched and then edited by any of the SILC_STR_* macros. The flags + * can be used to perform complex operations on the data. Some sed + * features that cannot be directly done with the flags can be done with + * SILC_STR_FUNC and other macros (the SILC_STR_FUNC could do anything + * after the match). + * + * The SILC_STR_REGEX itself is used as an opening of a block of encoding + * macros and must be closed with SILC_STR_END. This means that for + * each SILC_STR_REGEX there must be one SILC_STR_END. See examples for + * more information. + * + * The SILC_STR_REGEX can be used in buffer unformatting also to do + * string matching and parsing, but not editing, except with SILC_STR_FUNC + * macro, which can do anything caller wants. + * + * EXAMPLE + * + * // sed 's/foo/bar/', replace first foo with bar + * silc_buffer_format(buffer, + * SILC_STR_REGEX("foo", 0), + * SILC_STR_STRING("bar"), + * SILC_STR_END, SILC_STR_END); + * + * // 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. + * 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 '/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), + * SILC_STR_REGEX("foo", SILC_STR_REGEX_ALL), + * SILC_STR_STRING("bar"), + * SILC_STR_END, + * SILC_STR_END, SILC_STR_END); + * + * // Print all lines that start with 'R' + * int print(SilcStack stack, SilcBuffer buf, void *value, void *context) + * { + * return fwrite(silc_buffer_data(buf), 1, silc_buffer_len(buf), stdout); + * } + * + * silc_buffer_unformat(buffer, + * SILC_STR_REGEX("^R", SILC_STR_REGEX_NL), + * SILC_STR_FUNC(print, NULL, NULL), + * SILC_STR_END, SILC_STR_END); + * + ***/ +#define SILC_STR_REGEX(regex, flags) SILC_PARAM_REGEX, (regex), (flags) + /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET * * NAME @@ -712,6 +930,40 @@ typedef enum { ***/ #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x) +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET_START + * + * NAME + * + * #define SILC_STR_OFFSET_START ... + * + * DESCRIPTION + * + * Moves the buffer position to the start of the data area. + * + * Example: + * + * ..., SILC_STR_OFFSET_START, ... + * + ***/ +#define SILC_STR_OFFSET_START SILC_PARAM_OFFSET_START + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET_END + * + * NAME + * + * #define SILC_STR_OFFSET_END ... + * + * DESCRIPTION + * + * Moves the buffer position to the end of the data area. + * + * Example: + * + * ..., SILC_STR_OFFSET_END, ... + * + ***/ +#define SILC_STR_OFFSET_END SILC_PARAM_OFFSET_END + /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE * * NAME @@ -722,8 +974,8 @@ typedef enum { * * Advance the buffer to the end of the data after the formatting is * done. In normal operation when the formatted data is written the - * buffer is located at the start of the data. With SILC_STR_ADVANCE - * the buffer will be located at the end of the data. This makes it + * buffer is positioned at the start of the data. With SILC_STR_ADVANCE + * the buffer will be positioned at the end of the data. This makes it * easy to add new data immediately after the previously added data. * The SILC_STR_ADVANCE may also be used in unformatting. *