X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcbuffmt.h;h=32aa9bb69a77f9493a0744ba17c2b690e82774d9;hp=e69e90bb6c6ce31cf11b0fe213cf5c30a807b8b8;hb=38b10925eeea619c2b6fa646892df4416e6dd08f;hpb=a818c5b5411bbc4436d1c5f011236985c96bb787 diff --git a/lib/silcutil/silcbuffmt.h b/lib/silcutil/silcbuffmt.h index e69e90bb..32aa9bb6 100644 --- a/lib/silcutil/silcbuffmt.h +++ b/lib/silcutil/silcbuffmt.h @@ -2,15 +2,14 @@ silcbuffmt.h - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 1997 - 2000 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - + the Free Software Foundation; version 2 of the License. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -18,269 +17,1012 @@ */ -/****h* silcutil/SilcBufferFormatAPI +/****h* silcutil/SILC Buffer Format Interface * * DESCRIPTION * - * SILC Buffer Format API provides a few functions for formatting - * various different data types into a buffer, and retrieving - * various data from buffer into specific data types. It is usefull - * to format for example packets and later unformat them. + * 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 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 -/* Buffer parameter types. - - _SI_ = signed - _UI_ = unsigned - - Any XXX_STRING_ALLOC types will allocate space for the data and - memcpy the data to the pointer sent as argument (in unformatting). - - Any XXX_STRING will not allocate or copy any data. Instead it - will set the pointer to the data. Note that the data pointer - returned (in unformatting) must not be freed. +/****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); -*/ -typedef enum { - SILC_BUFFER_PARAM_SI8_CHAR, - SILC_BUFFER_PARAM_UI8_CHAR, - - SILC_BUFFER_PARAM_SI16_SHORT, - SILC_BUFFER_PARAM_UI16_SHORT, - - SILC_BUFFER_PARAM_SI32_INT, - SILC_BUFFER_PARAM_UI32_INT, - - SILC_BUFFER_PARAM_SI64_INT, - SILC_BUFFER_PARAM_UI64_INT, - - SILC_BUFFER_PARAM_UI8_STRING, /* No copy */ - SILC_BUFFER_PARAM_UI8_STRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI16_STRING, /* No copy */ - SILC_BUFFER_PARAM_UI16_STRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI32_STRING, /* No copy */ - SILC_BUFFER_PARAM_UI32_STRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI8_NSTRING, /* No copy */ - SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI16_NSTRING, /* No copy */ - SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI32_NSTRING, /* No copy */ - SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC, /* Alloc + memcpy */ - SILC_BUFFER_PARAM_UI_XNSTRING, /* No copy */ - SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC, /* Alloc + memcpy */ - - SILC_BUFFER_PARAM_END -} SilcBufferParamType; - -/* Macros for expanding parameters into variable function argument list. - These are passed to silc_buffer_format and silc_buffer_unformat - functions. */ - -/* One signed/unsigned character. - - Formatting: SILC_STR_SI_CHAR(char) - SILC_STR_UI_CHAR(unsigned char) - Unformatting: SILC_STR_SI_CHAR(char *) - SILC_STR_UI_CHAR(unsigned char *) +/****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); -*/ -#define SILC_STR_SI_CHAR(x) SILC_BUFFER_PARAM_SI8_CHAR, (x) -#define SILC_STR_UI_CHAR(x) SILC_BUFFER_PARAM_UI8_CHAR, (x) +/* Prototypes */ -/* Signed/SilcUInt16. +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_format + * + * SYNOPSIS + * + * int silc_buffer_format(SilcBuffer dst, ...); + * + * DESCRIPTION + * + * 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; + * + * memset(&buffer, 0, sizeof(buffer)); + * ret = silc_buffer_format(&buffer, + * 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; + * + * // Free the allocated data + * silc_buffer_purge(&buffer); + * + * // Dynamically allocated zero size buffer + * SilcBuffer buf; + * buf = silc_buffer_alloc(0); + * ret = silc_buffer_format(buf, + * 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, ...); - Formatting: SILC_STR_SI_SHORT(short) - SILC_STR_UI_SHORT(SilcUInt16) - Unformatting: SILC_STR_SI_SHORT(short *) - SILC_STR_UI_SHORT(SilcUInt16 *) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat + * + * SYNOPSIS + * + * int silc_buffer_sformat(SilcStack stack, 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. 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, ...); -*/ -#define SILC_STR_SI_SHORT(x) SILC_BUFFER_PARAM_SI16_SHORT, (x) -#define SILC_STR_UI_SHORT(x) SILC_BUFFER_PARAM_UI16_SHORT, (x) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp + * + * SYNOPSIS + * + * int silc_buffer_format_vp(SilcBuffer dst, va_list vp); + * + * DESCRIPTION + * + * Formats a buffer from a variable argument list indicated by the `ap'. + * 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); -/* Signed/SilcUInt32. +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat_vp + * + * SYNOPSIS + * + * 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. 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); - Formatting: SILC_STR_SI_INT(int) - SILC_STR_UI_INT(SilcUInt32) - Unformatting: SILC_STR_SI_INT(int *) - SILC_STR_UI_INT(SilcUInt32 *) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat + * + * SYNOPSIS + * + * int silc_buffer_unformat(SilcBuffer src, ...); + * + * DESCRIPTION + * + * Unformats a buffer from a variable argument list. Returns -1 on error + * and the length of the unformatted buffer otherwise. Sets silc_errno + * in case of error. + * + * EXAMPLE + * + * ret = silc_buffer_unformat(buffer, + * SILC_STR_UINT32(&intval), + * SILC_STR_UINT8(&charval), + * SILC_STR_OFFSET(4), + * SILC_STR_UI16_NSTRING_ALLOC(&str, &str_len), + * SILC_STR_END); + * if (ret < 0) + * error; + * + ***/ +int silc_buffer_unformat(SilcBuffer src, ...); -*/ -#define SILC_STR_SI_INT(x) SILC_BUFFER_PARAM_SI32_INT, (x) -#define SILC_STR_UI_INT(x) SILC_BUFFER_PARAM_UI32_INT, (x) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat + * + * SYNOPSIS + * + * int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...); + * + * DESCRIPTION + * + * 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, ...); -/* Signed/SilcUInt64. +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp + * + * SYNOPSIS + * + * int silc_buffer_unformat_vp(SilcBuffer src, va_list vp); + * + * DESCRIPTION + * + * Unformats a buffer from a variable argument list indicated by the `ap'. + * Returns -1 on error and the length of the unformatted buffer otherwise. + * + ***/ +int silc_buffer_unformat_vp(SilcBuffer src, va_list ap); - Formatting: SILC_STR_SI_INT64(int) - SILC_STR_UI_INT64(SilcUInt32) - Unformatting: SILC_STR_SI_INT64(int *) - SILC_STR_UI_INT64(SilcUInt32 *) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat_vp + * + * SYNOPSIS + * + * int silc_buffer_sunformat_vp(SilcBuffer src, va_list vp); + * + * DESCRIPTION + * + * 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); -*/ -#define SILC_STR_SI_INT64(x) SILC_BUFFER_PARAM_SI64_INT, (x) -#define SILC_STR_UI_INT64(x) SILC_BUFFER_PARAM_UI64_INT, (x) +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat + * + * SYNOPSIS + * + * 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_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 + * + * ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END); + * if (ret < 0) + * error; + * + ***/ +int silc_buffer_strformat(SilcBuffer dst, ...); -/* Unsigned NULL terminated string. Note that the string must be - NULL terminated because strlen() will be used to get the length of - the string. +/****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat + * + * SYNOPSIS + * + * 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_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, ...); - Formatting: SILC_STR_UI32_STRING(unsigned char *) - Unformatting: SILC_STR_UI32_STRING(unsigned char **) +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT8 + * + * NAME + * + * #define SILC_STR_SINT8() ... + * + * DESCRIPTION + * + * One 8-bit signed integer. + * + * Formatting: SILC_STR_SINT8(SilcInt8) + * Unformatting: SILC_STR_SINT8(SilcInt8 *) + * + ***/ +#define SILC_STR_SINT8(x) SILC_PARAM_SINT8, (x) - 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 of the string because unformatting procedure will take it - automatically. +/****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) - Example: +/* Deprecated */ +#define SILC_STR_SI_CHAR(x) SILC_PARAM_SINT8, (x) +#define SILC_STR_UI_CHAR(x) SILC_PARAM_UINT8, (x) - Formatting: ..., SILC_STR_UI_INT(strlen(string)), - SILC_STR_UI32_STRING(string), ... - Unformatting: ..., SILC_STR_UI32_STRING(&string), ... +/****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) - I.e., you ignore the formatted length field in unformatting. If you don't - the unformatting procedure might fail and it definitely does not unformat - the data reliably. +/****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) - _ALLOC routines automatically allocates memory for the variable sent - as argument in unformatting. +/* Deprecated */ +#define SILC_STR_SI_SHORT(x) SILC_PARAM_SINT16, (x) +#define SILC_STR_UI_SHORT(x) SILC_PARAM_UINT16, (x) -*/ -#define SILC_STR_UI8_STRING(x) SILC_BUFFER_PARAM_UI8_STRING, (x) -#define SILC_STR_UI8_STRING_ALLOC(x) SILC_BUFFER_PARAM_UI8_STRING_ALLOC, (x) -#define SILC_STR_UI16_STRING(x) SILC_BUFFER_PARAM_UI16_STRING, (x) -#define SILC_STR_UI16_STRING_ALLOC(x) SILC_BUFFER_PARAM_UI16_STRING_ALLOC, (x) -#define SILC_STR_UI32_STRING(x) SILC_BUFFER_PARAM_UI32_STRING, (x) -#define SILC_STR_UI32_STRING_ALLOC(x) SILC_BUFFER_PARAM_UI32_STRING_ALLOC, (x) +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_SINT32 + * + * NAME + * + * #define SILC_STR_SINT32() ... + * + * DESCRIPTION + * + * SilcInt32. + * + * Formatting: SILC_STR_SINT32(SilcInt32) + * Unformatting: SILC_STR_SINT32(SilcInt32 *) + * + ***/ +#define SILC_STR_SINT32(x) SILC_PARAM_SINT32, (x) -/* Unsigned string. Second argument is the length of the string. +/****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) - Formatting: SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32) - Unformatting: SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *) +/* Deprecated */ +#define SILC_STR_SI_INT(x) SILC_PARAM_SINT32, (x) +#define SILC_STR_UI_INT(x) SILC_PARAM_UINT32, (x) - 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 of the string because unformatting procedure will take it - automatically. +/****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) - Example: +/****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) - Formatting: ..., SILC_STR_UI_INT(strlen(string)), - SILC_STR_UI32_NSTRING(string, strlen(string)), ... - Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ... +/* Deprecated */ +#define SILC_STR_SI_INT64(x) SILC_PARAM_SINT64, (x) +#define SILC_STR_UI_INT64(x) SILC_PARAM_UINT64, (x) - I.e., you ignore the formatted length field in unformatting. If you don't - the unformatting procedure might fail and it definitely does not unformat - the data reliably. The length taken from the buffer is returned to the - pointer sent as argument (&len in above example). +/****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) - UI/SI16 and UI/SI32 means that the length is considered to be either - short (16 bits) or int (32 bits) in unformatting. +/****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) - _ALLOC routines automatically allocates memory for the variable sent - as argument in unformatting. +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING + * + * NAME + * + * #define SILC_STR_UI8_STRING() ... + * #define SILC_STR_UI8_STRING_ALLOC() ... + * #define SILC_STR_UI16_STRING() ... + * #define SILC_STR_UI16_STRING_ALLOC() ... + * #define SILC_STR_UI32_STRING() ... + * #define SILC_STR_UI32_STRING_ALLOC() ... + * + * DESCRIPTION + * + * Unsigned NULL terminated string. Note that the string must be + * NULL terminated because strlen() will be used to get the length of + * the string. + * + * Formatting: SILC_STR_UI32_STRING(unsigned char *) + * Unformatting: SILC_STR_UI32_STRING(unsigned char **) + * + * 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 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_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 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 | 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 | 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 | SILC_PARAM_ALLOC, (x) -*/ -#define SILC_STR_UI8_NSTRING(x, l) SILC_BUFFER_PARAM_UI8_NSTRING, (x), (l) +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING + * + * NAME + * + * #define SILC_STR_UI8_NSTRING() ... + * #define SILC_STR_UI8_NSTRING_ALLOC() ... + * #define SILC_STR_UI16_NSTRING() ... + * #define SILC_STR_UI16_NSTRING_ALLOC() ... + * #define SILC_STR_UI32_NSTRING() ... + * #define SILC_STR_UI32_NSTRING_ALLOC() ... + * + * DESCRIPTION + * + * Unsigned string. Second argument is the length of the string. + * + * Formatting: SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32) + * Unformatting: SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *) + * + * 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 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_UINT32(strlen(string)), + * SILC_STR_UI32_NSTRING(string, strlen(string)), ... + * Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ... + * + * I.e., you can ignore the formatted length field in unformatting. The + * length taken from the buffer is returned to the pointer sent as + * argument (&len in above example). + * + * UI8, UI16 and UI32 means that the length is considered to be + * either UINT8, UINT16 or UINT32 in unformatting. + * + * _ALLOC routines automatically allocates memory for the variable sent + * as argument in unformatting. + * + ***/ +#define SILC_STR_UI8_NSTRING(x, l) SILC_PARAM_UI8_NSTRING, (x), (l) #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \ - SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC, (x), (l) -#define SILC_STR_UI16_NSTRING(x, l) SILC_BUFFER_PARAM_UI16_NSTRING, (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_BUFFER_PARAM_UI16_NSTRING_ALLOC, (x), (l) -#define SILC_STR_UI32_NSTRING(x, l) SILC_BUFFER_PARAM_UI32_NSTRING, (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_BUFFER_PARAM_UI32_NSTRING_ALLOC, (x), (l) + SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC, (x), (l) + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA + * + * NAME + * + * #define SILC_STR_DATA() ... + * #define SILC_STR_DATA_ALLOC() ... + * + * DESCRIPTION + * + * Binary data formatting. Second argument is the length of the data. + * + * Formatting: SILC_STR_DATA(unsigned char *, SilcUInt32) + * Unformatting: SILC_STR_DATA(unsigned char **, SilcUInt32) + * + * This type can be used to take arbitrary size data block from the buffer + * by sending the requested amount of bytes as argument. + * + * _ALLOC routines automatically allocates memory for the variable sent + * as argument in unformatting. + * + ***/ +#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_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 + * + * NAME + * + * #define SILC_STR_BUFFER() ... + * #define SILC_STR_BUFFER_ALLOC() ... + * + * DESCRIPTION + * + * SilcBuffer formatting. + * + * Formatting: SILC_STR_BUFFER(SilcBuffer) + * Unformatting: SILC_STR_BUFFER(SilcBuffer) + * + * 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_PARAM_BUFFER, (x) +#define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER | SILC_PARAM_ALLOC, (x) -/* Extended Unsigned string formatting. Second argument is the length of - the string. +/****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) - Formatting: This is equal to using *_NSTRING - Unformatting: SILC_STR_UI_XNSTRING(unsigned char **, SilcUInt32) +/****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, - This type can be used to take arbitrary length string from the buffer - by sending the requested amount of bytes as argument. This differs - from *_STRING and *_NSTRING so that this doesn't try to find the - length of the data from the buffer but the length of the data is - sent as argument. This a handy way to unformat fixed length strings - from the buffer without having the length of the string formatted - in the buffer. + /* 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, - _ALLOC routines automatically allocates memory for the variable sent - as argument in unformatting. + /* By default only the first match is found. Set this flag to find + all matches. */ + SILC_STR_REGEX_ALL = 0x00000002, -*/ -#define SILC_STR_UI_XNSTRING(x, l) SILC_BUFFER_PARAM_UI_XNSTRING, (x), (l) -#define SILC_STR_UI_XNSTRING_ALLOC(x, l) \ - SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC, (x), (l) + /* 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, -/* Marks end of the argument list. This must be at the end of the - argument list or error will occur. */ -#define SILC_STR_END SILC_BUFFER_PARAM_END + /* 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, -/* Prototypes */ + /* 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, -/****f* silcutil/SilcBufferFormatAPI/silc_buffer_format + /* 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 * - * SYNOPSIS + * NAME * - * int silc_buffer_format(SilcBuffer dst, ...); + * #define SILC_STR_REGEX() ... * * DESCRIPTION * - * Formats a buffer from a variable argument list. Returns -1 on error - * and the length of the formatted buffer otherwise. + * 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); * ***/ -int silc_buffer_format(SilcBuffer dst, ...); +#define SILC_STR_REGEX(regex, flags) SILC_PARAM_REGEX, (regex), (flags) -/****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET * - * SYNOPSIS + * NAME * - * int silc_buffer_unformat(SilcBuffer src, ...); + * #define SILC_STR_OFFSET() ... * * DESCRIPTION * - * Formats a buffer from a variable argument list. Returns -1 on error - * and the length of the formatted buffer otherwise. + * Offset in buffer. This can be used in formatting and unformatting to + * move the data pointer of the buffer either forwards (positive offset) + * or backwards (negative offset). It can be used to for example skip + * some types during unformatting. + * + * Example: + * + * ..., SILC_STR_OFFSET(5), ... + * ..., SILC_STR_OFFSET(-3), ... + * + * Moves the data pointer at the point of the offset either forward + * or backward and then moves to the next type. Multiple SILC_STR_OFFSETs + * can be used in formatting and unformatting at the same time. * ***/ -int silc_buffer_unformat(SilcBuffer src, ...); +#define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x) -/****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET_START * - * SYNOPSIS + * NAME * - * int silc_buffer_format_vp(SilcBuffer dst, va_list vp); + * #define SILC_STR_OFFSET_START ... * * 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. + * Moves the buffer position to the start of the data area. + * + * Example: + * + * ..., SILC_STR_OFFSET_START, ... * ***/ -int silc_buffer_format_vp(SilcBuffer dst, va_list ap); +#define SILC_STR_OFFSET_START SILC_PARAM_OFFSET_START -/****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET_END * - * SYNOPSIS + * NAME * - * int silc_buffer_unformat_vp(SilcBuffer src, va_list vp); + * #define SILC_STR_OFFSET_END ... * * 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. + * Moves the buffer position to the end of the data area. + * + * Example: + * + * ..., SILC_STR_OFFSET_END, ... * ***/ -int silc_buffer_unformat_vp(SilcBuffer src, va_list ap); +#define SILC_STR_OFFSET_END SILC_PARAM_OFFSET_END + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE + * + * NAME + * + * #define SILC_STR_ADVANCE ... + * + * DESCRIPTION + * + * 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 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 + * + * do { + * len = read(fd, buf, sizeof(buf)); + * if (len > 0) + * // Add read data to the buffer + * silc_buffer_format(buffer, + * SILC_STR_ADVANCE, + * SILC_STR_DATA(buf, len), + * SILC_STR_END); + * } while (len > 0); + * + * // Move to beginning of buffer + * silc_buffer_start(buffer); + * + ***/ +#define SILC_STR_ADVANCE SILC_PARAM_ADVANCE + +/****d* silcutil/SilcBufferFormatAPI/SILC_STR_END + * + * NAME + * + * #define SILC_STR_END ... + * + * DESCRIPTION + * + * Marks end of the argument list. This must be at the end of the + * argument list or error will occur. + * + ***/ +#define SILC_STR_END SILC_PARAM_END + +/****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END + * + * NAME + * + * #define SILC_STRFMT_END ... + * + * DESCRIPTION + * + * Marks end of the argument list in silc_buffer_strformat function. + * This must be at the end of the argument list or error will occur. + * + ***/ +#define SILC_STRFMT_END (void *)SILC_STR_END -#endif +#endif /* !SILCBUFFMT_H */