X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcbuffmt.h;h=32aa9bb69a77f9493a0744ba17c2b690e82774d9;hp=4c2a4d69f3e011fb128b0ca3bf0a9efe3bae0e8e;hb=38b10925eeea619c2b6fa646892df4416e6dd08f;hpb=1ab360ada0014740f16c867dcae273d31e6fd0b8 diff --git a/lib/silcutil/silcbuffmt.h b/lib/silcutil/silcbuffmt.h index 4c2a4d69..32aa9bb6 100644 --- a/lib/silcutil/silcbuffmt.h +++ b/lib/silcutil/silcbuffmt.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2006 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,18 +23,109 @@ * * 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. * + * EXAMPLE + * + * SilcBufferStruct buffer; + * + * memset(&buffer, 0, sizeof(buffer)); + * ret = silc_buffer_format(&buffer, + * 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 #define SILCBUFFMT_H +/****f* silcutil/SilcBufferFormatAPI/SilcBufferFormatFunc + * + * SYNOPSIS + * + * typedef int (*SilcBuffeSFormatFunc)(SilcStack stack, + * SilcBuffer buffer, + * void *value, + * void *context); + * + * DESCRIPTION + * + * Formatting function callback given with SILC_STR_FUNC type. The + * `buffer' is the buffer being formatted at the location where the + * SILC_STR_FUNC was placed in formatting. The function should call + * silc_buffer_senlarge before it adds the data to the buffer to make + * sure that it has enough space. The buffer->head points to the + * start of the buffer and silc_buffer_headlen() gives the length + * of the currently formatted data area. It is also possible to use + * silc_buffer_sformat with `buffer' which will enlarge the buffer if + * needed. + * + * The `value' is the value given to SILC_STR_FUNC that is to be formatted + * into the buffer. It may be NULL if the function is not formatting + * new data into the buffer. The `context' is caller specific context. + * Returns -1 on error and length of the formatted value otherwise, and + * 0 if nothing was formatted. + * + ***/ +typedef int (*SilcBufferFormatFunc)(SilcStack stack, SilcBuffer buffer, + void *value, void *context); + +/****f* silcutil/SilcBufferFormatAPI/SilcBufferUnformatFunc + * + * SYNOPSIS + * + * typedef int (*SilcBufferUnformatFunc)(SilcBuffer buffer, + * void **value, + * void *context); + * + * DESCRIPTION + * + * Unformatting function callback given with SILC_STR_FUNC type. The + * `buffer' is the buffer being unformatted and is at the location where + * the SILC_STR_FUNC was placed in unformatting. The function should + * check there is enough data in the `buffer' before trying to decode + * from it. + * + * If this function unformats anything from the buffer its value is to + * be returned to the `value' pointer. The implementation should itself + * decide whether the unformatted value is allocated or not. If this + * function does not unformat anything, nothing is returned to `value' + * + * The `context' is caller specific context. Returns -1 on error, and + * length of the unformatted value otherwise, and 0 if nothing was + * unformatted. + * + ***/ +typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer, + void **value, void *context); + /* Prototypes */ /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format @@ -45,23 +136,25 @@ * * DESCRIPTION * - * Formats a buffer from a variable argument list. Returns -1 on error - * and the length of the formatted buffer otherwise. The buffer is - * enlarged automatically during formatting, if it doesn't already have - * enough space. + * 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. Sets silc_errno in case of error. * * EXAMPLE * + * Three basic ways of using silc_buffer_format: + * + * // Statically allocated zero size buffer * SilcBufferStruct buffer; - * SilcBuffer buf; * * memset(&buffer, 0, sizeof(buffer)); * ret = silc_buffer_format(&buffer, - * SILC_STR_INT(intval), - * SILC_STR_CHAR(charval), - * SILC_STR_INT(intval), - * SILC_STR_SHORT(str_len), - * SILC_STR_UI_XNSTRING(str, 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) * error; @@ -69,16 +162,29 @@ * // Free the allocated data * silc_buffer_purge(&buffer); * - * // Allocate zero size buffer + * // Dynamically allocated zero size buffer + * SilcBuffer buf; * buf = silc_buffer_alloc(0); * ret = silc_buffer_format(buf, - * SILC_STR_INT(intval), - * SILC_STR_CHAR(charval), + * SILC_STR_UINT32(intval), + * SILC_STR_UINT8(charval), * SILC_STR_END); + * if (ret < 0) + * error; * * // Free the allocated buffer * silc_buffer_free(buf); * + * // Dynamically allocated buffer with enough space + * SilcBuffer buf; + * buf = silc_buffer_alloc(2 + str_len); + * ret = silc_buffer_format(buf, + * SILC_STR_UINT16(str_len), + * SILC_STR_DATA(str, str_len), + * SILC_STR_END); + * if (ret < 0) + * error; + * ***/ int silc_buffer_format(SilcBuffer dst, ...); @@ -91,7 +197,11 @@ int silc_buffer_format(SilcBuffer dst, ...); * DESCRIPTION * * Same as silc_buffer_format but uses `stack' to allocate the memory. - * if `stack' is NULL reverts back to silc_buffer_format call. + * if `stack' is NULL reverts back to silc_buffer_format call. Returns + * -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. * ***/ int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...); @@ -105,21 +215,26 @@ int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...); * DESCRIPTION * * Formats a buffer from a variable argument list indicated by the `ap'. - * Returns -1 on error and the length of the formatted buffer otherwise. + * Returns -1 if system is out of memory and the length of the formatted + * buffer otherwise. * ***/ int silc_buffer_format_vp(SilcBuffer dst, va_list ap); -/****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat_vp * * SYNOPSIS * - * int silc_buffer_format_vp(SilcBuffer dst, va_list vp); + * int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list vp); * * DESCRIPTION * * 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. + * if `stack' is NULL reverts back to silc_buffer_format_vp call. Returns + * -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. * ***/ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap); @@ -133,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_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); @@ -160,6 +276,9 @@ int silc_buffer_unformat(SilcBuffer src, ...); * Same as silc_buffer_unformat but uses `stack' to allocate the memory. * if `stack' is NULL reverts back to silc_buffer_format call. * + * Note that this call consumes the `stack'. The caller should push the + * stack before calling the function and pop it later. + * ***/ int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...); @@ -188,6 +307,9 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap); * Same as silc_buffer_unformat_vp but uses `stack' to allocate the * memory. if `stack' is NULL reverts back to silc_buffer_format_vp call. * + * Note that this call consumes the `stack'. The caller should push the + * stack before calling the function and pop it later. + * ***/ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap); @@ -195,16 +317,17 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap); * * SYNOPSIS * - * int silc_buffer_strformat(SilcBuffer dst, ...); + * int silc_buffer_strformat(SilcBuffer dst, ...); * * DESCRIPTION * - * Formats a buffer from variable argument list of strings. Each - * string must be NULL-terminated and the variable argument list must - * be end with SILC_STR_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. + * Formats a buffer from variable argument list of strings. Each + * string must be NULL-terminated and the variable argument list must + * 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 and + * sets silc_errno. * * EXAMPLE * @@ -219,153 +342,229 @@ int silc_buffer_strformat(SilcBuffer dst, ...); * * SYNOPSIS * - * int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...); + * int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...); * * DESCRIPTION * - * Formats a buffer from variable argument list of strings. Each - * string must be NULL-terminated and the variable argument list must - * be end with SILC_STR_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. This function is equivalent to - * silc_buffer_strformat but allocates memory from `stack'. + * Formats a buffer from variable argument list of strings. Each + * string must be NULL-terminated and the variable argument list must + * 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. This function is equivalent to + * silc_buffer_strformat but allocates memory from `stack'. Returns -1 + * 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. * ***/ 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_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_*_CHAR +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT8 * * NAME * - * #define SILC_STR_UI_CHAR() ... - * #define SILC_STR_SI_CHAR() ... + * #define SILC_STR_UINT8() ... * * DESCRIPTION * - * One signed/unsigned character. + * One 8-bit unsigned integer. * - * 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_UINT8(SilcUInt8) + * Unformatting: SILC_STR_UINT8(SilcUInt8 *) * ***/ -#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_UINT8(x) SILC_PARAM_UINT8, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT +/* 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_UI_SHORT() ... - * #define SILC_STR_SI_SHORT() ... + * #define SILC_STR_SINT16() ... * * DESCRIPTION * - * SilcInt16/SilcUInt16. + * SilcInt16. * - * Formatting: SILC_STR_SI_SHORT(short) - * SILC_STR_UI_SHORT(SilcUInt16) - * Unformatting: SILC_STR_SI_SHORT(short *) - * SILC_STR_UI_SHORT(SilcUInt16 *) + * Formatting: SILC_STR_SINT16(SilcInt16) + * Unformatting: SILC_STR_SINT16(SilcInt16 *) * ***/ -#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_SINT16(x) SILC_PARAM_SINT16, (x) -/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT16 * * NAME * - * #define SILC_STR_UI_INT() ... - * #define SILC_STR_SI_INT() ... + * #define SILC_STR_UINT16() ... * * DESCRIPTION * - * SilcInt32/SilcUInt32. + * SilcUInt16. * - * Formatting: SILC_STR_SI_INT(int) - * SILC_STR_UI_INT(SilcUInt32) - * Unformatting: SILC_STR_SI_INT(int *) - * SILC_STR_UI_INT(SilcUInt32 *) + * Formatting: SILC_STR_UINT16(SilcUInt16) + * Unformatting: SILC_STR_UINT16(SilcUInt16 *) * ***/ -#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_UINT16(x) SILC_PARAM_UINT16, (x) + +/* 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_*_INT64 +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT32 * * NAME * - * #define SILC_STR_UI_INT64() ... - * #define SILC_STR_SI_INT64() ... + * #define SILC_STR_SINT32() ... * * DESCRIPTION * - * SilcInt64/SilcUInt64. + * SilcInt32. * - * Formatting: SILC_STR_SI_INT64(int) - * SILC_STR_UI_INT64(SilcUInt32) - * Unformatting: SILC_STR_SI_INT64(int *) - * SILC_STR_UI_INT64(SilcUInt32 *) + * Formatting: SILC_STR_SINT32(SilcInt32) + * Unformatting: SILC_STR_SINT32(SilcInt32 *) * ***/ -#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_SINT32(x) SILC_PARAM_SINT32, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT32 + * + * NAME + * + * #define SILC_STR_UINT32() ... + * + * DESCRIPTION + * + * SilcUInt32. + * + * Formatting: SILC_STR_UINT32(SilcUInt32) + * Unformatting: SILC_STR_UINT32(SilcUInt32 *) + * + ***/ +#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_SINT64 + * + * NAME + * + * #define SILC_STR_SINT64() ... + * + * DESCRIPTION + * + * SilcInt64. + * + * Formatting: SILC_STR_SINT64(SilcInt64) + * Unformatting: SILC_STR_SINT64(SilcInt64 *) + * + ***/ +#define SILC_STR_SI_INT64(x) SILC_PARAM_SINT64, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UINT64 + * + * NAME + * + * #define SILC_STR_UINT64() ... + * + * DESCRIPTION + * + * SilcUInt64. + * + * Formatting: SILC_STR_UINT64(SilcUInt64) + * Unformatting: SILC_STR_UINT64(SilcUInt64 *) + * + ***/ +#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 * @@ -389,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 * @@ -437,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), ... * @@ -453,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. @@ -462,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 * @@ -491,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 * @@ -509,19 +706,204 @@ typedef enum { * * SilcBuffer formatting. * - * Formatting: SILC_STR_DATA(SilcBuffer) - * Unformatting: SILC_STR_DATA(SilcBuffer) + * Formatting: SILC_STR_BUFFER(SilcBuffer) + * Unformatting: SILC_STR_BUFFER(SilcBuffer) * - * This type can be used to format and unformat SilcBuffer. The lenght - * of the buffer will be automatically encoded into the buffer as a 32-bit - * integer. In unformatting the SilcBuffer context must be pre-allocated. + * This type can be used to format and unformat SilcBuffer. Note that, the + * length of the buffer will be automatically encoded into the buffer as + * a 32-bit integer. In unformatting the SilcBuffer context must be + * pre-allocated. * * _ALLOC routines automatically allocates memory inside SilcBuffer in * unformatting. * ***/ -#define SILC_STR_BUFFER(x) SILC_BUFFER_DATA, (x) -#define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x) +#define SILC_STR_BUFFER(x) SILC_PARAM_BUFFER, (x) +#define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER | SILC_PARAM_ALLOC, (x) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_FUNC + * + * NAME + * + * #define SILC_STR_FUNC() ... + * + * DESCRIPTION + * + * Formatting and unformatting of arbitrary data. + * + * Formatting: SILC_STR_FUNC(function, void *value, void *context) + * Unformatting: SILC_STR_FUNC(function, void **value, void *context) + * + * This type can be used to call the `function' of the type + * SilcBufferFormatFunc or SilcBufferUnformatFunc to encode or decode + * the `value'. In encoding the `value' will be passed to the `function' + * and can be encoded into the buffer. The buffer will be passed as + * well to the `function' at the location where SILC_STR_FUNC is placed + * in formatting. The `context' delivers caller specific context to + * the `function' + * + * In unformatting the `function' will decode the encoded type and + * return it to `value' pointer. The decoding function should decide + * itself whether to allocate or not the decoded value. + * + * The `function' does not have to encode anything and passing `value' + * as NULL is allowed. The `function' could for example modify the + * existing buffer. + * + * EXAMPLE + * + * // Encode payload, encrypt and compute MAC. + * silc_buffer_format(buf, + * SILC_STR_FUNC(foo_encode_id, id, ctx), + * 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), + * SILC_STR_DATA(iv, iv_len); + * SILC_STR_END); + * + * // Check MAC, decrypt and decode payload + * silc_buffer_unformat(buf, + * 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_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 * @@ -548,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 @@ -558,9 +974,10 @@ 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. * * EXAMPLE * @@ -570,12 +987,12 @@ typedef enum { * // Add read data to the buffer * silc_buffer_format(buffer, * SILC_STR_ADVANCE, - * SILC_STR_UI_XNSTRING(buf, len), + * SILC_STR_DATA(buf, len), * SILC_STR_END); * } while (len > 0); * * // Move to beginning of buffer - * silc_buffer_push(buffer, silc_buffer_truelen(buffer)); + * silc_buffer_start(buffer); * ***/ #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE