Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
*/
/* $Id$ */
-#include "silcincludes.h"
+#include "silc.h"
-/* Macro to check whether there is enough free space to add the
+/* Macros to check whether there is enough free space to add the
required amount of data. For unformatting this means that there must
be the data that is to be extracted. */
-#define MY_HAS_SPACE(__x__, __req__) \
+#define FORMAT_HAS_SPACE(__x__, __req__) \
do { \
- if (__req__ > (__x__)->len) \
+ if (__req__ > silc_buffer_len((__x__))) \
+ goto fail; \
+ } while(0)
+#define UNFORMAT_HAS_SPACE(__x__, __req__) \
+ do { \
+ if (__req__ > silc_buffer_len((__x__))) \
+ goto fail; \
+ if ((__req__ + 1) <= 0) \
goto fail; \
} while(0)
fmt = va_arg(ap, SilcBufferParamType);
switch(fmt) {
+ case SILC_BUFFER_PARAM_OFFSET:
+ {
+ int offst = va_arg(ap, int);
+ if (!offst)
+ break;
+ if (offst > 1) {
+ FORMAT_HAS_SPACE(dst, offst);
+ silc_buffer_pull(dst, offst);
+ } else {
+ silc_buffer_push(dst, -(offst));
+ }
+ break;
+ }
case SILC_BUFFER_PARAM_SI8_CHAR:
{
char x = (char)va_arg(ap, int);
- MY_HAS_SPACE(dst, 1);
+ FORMAT_HAS_SPACE(dst, 1);
silc_buffer_put(dst, &x, 1);
silc_buffer_pull(dst, 1);
break;
case SILC_BUFFER_PARAM_UI8_CHAR:
{
unsigned char x = (unsigned char)va_arg(ap, int);
- MY_HAS_SPACE(dst, 1);
+ FORMAT_HAS_SPACE(dst, 1);
silc_buffer_put(dst, &x, 1);
silc_buffer_pull(dst, 1);
break;
{
unsigned char xf[2];
SilcInt16 x = (SilcInt16)va_arg(ap, int);
- MY_HAS_SPACE(dst, 2);
+ FORMAT_HAS_SPACE(dst, 2);
SILC_PUT16_MSB(x, xf);
silc_buffer_put(dst, xf, 2);
silc_buffer_pull(dst, 2);
{
unsigned char xf[2];
SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
- MY_HAS_SPACE(dst, 2);
+ FORMAT_HAS_SPACE(dst, 2);
SILC_PUT16_MSB(x, xf);
silc_buffer_put(dst, xf, 2);
silc_buffer_pull(dst, 2);
{
unsigned char xf[4];
SilcInt32 x = va_arg(ap, SilcInt32);
- MY_HAS_SPACE(dst, 4);
+ FORMAT_HAS_SPACE(dst, 4);
SILC_PUT32_MSB(x, xf);
silc_buffer_put(dst, xf, 4);
silc_buffer_pull(dst, 4);
{
unsigned char xf[4];
SilcUInt32 x = va_arg(ap, SilcUInt32);
- MY_HAS_SPACE(dst, 4);
+ FORMAT_HAS_SPACE(dst, 4);
SILC_PUT32_MSB(x, xf);
silc_buffer_put(dst, xf, 4);
silc_buffer_pull(dst, 4);
{
unsigned char xf[8];
SilcInt64 x = va_arg(ap, SilcInt64);
- MY_HAS_SPACE(dst, sizeof(SilcInt64));
+ FORMAT_HAS_SPACE(dst, sizeof(SilcInt64));
SILC_PUT64_MSB(x, xf);
silc_buffer_put(dst, xf, sizeof(SilcInt64));
silc_buffer_pull(dst, sizeof(SilcInt64));
{
unsigned char xf[8];
SilcUInt64 x = va_arg(ap, SilcUInt64);
- MY_HAS_SPACE(dst, sizeof(SilcUInt64));
+ FORMAT_HAS_SPACE(dst, sizeof(SilcUInt64));
SILC_PUT64_MSB(x, xf);
silc_buffer_put(dst, xf, sizeof(SilcUInt64));
silc_buffer_pull(dst, sizeof(SilcUInt64));
{
unsigned char *x = va_arg(ap, unsigned char *);
SilcUInt32 tmp_len = strlen(x);
- MY_HAS_SPACE(dst, tmp_len);
+ FORMAT_HAS_SPACE(dst, tmp_len);
silc_buffer_put(dst, x, tmp_len);
silc_buffer_pull(dst, tmp_len);
break;
{
unsigned char *x = va_arg(ap, unsigned char *);
SilcUInt32 len = va_arg(ap, SilcUInt32);
- MY_HAS_SPACE(dst, len);
- silc_buffer_put(dst, x, len);
- silc_buffer_pull(dst, len);
+ if (x && len) {
+ FORMAT_HAS_SPACE(dst, len);
+ silc_buffer_put(dst, x, len);
+ silc_buffer_pull(dst, len);
+ }
break;
}
case SILC_BUFFER_PARAM_END:
fmt = va_arg(ap, SilcBufferParamType);
switch(fmt) {
+ case SILC_BUFFER_PARAM_OFFSET:
+ {
+ int offst = va_arg(ap, int);
+ if (!offst)
+ break;
+ if (offst > 1) {
+ UNFORMAT_HAS_SPACE(src, offst);
+ silc_buffer_pull(src, offst);
+ } else {
+ silc_buffer_push(src, -(offst));
+ }
+ break;
+ }
case SILC_BUFFER_PARAM_SI8_CHAR:
{
char *x = va_arg(ap, char *);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
if (x)
*x = src->data[0];
silc_buffer_pull(src, 1);
case SILC_BUFFER_PARAM_UI8_CHAR:
{
unsigned char *x = va_arg(ap, unsigned char *);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
if (x)
*x = src->data[0];
silc_buffer_pull(src, 1);
case SILC_BUFFER_PARAM_SI16_SHORT:
{
SilcInt16 *x = va_arg(ap, SilcInt16 *);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
if (x)
SILC_GET16_MSB(*x, src->data);
silc_buffer_pull(src, 2);
case SILC_BUFFER_PARAM_UI16_SHORT:
{
SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
if (x)
SILC_GET16_MSB(*x, src->data);
silc_buffer_pull(src, 2);
case SILC_BUFFER_PARAM_SI32_INT:
{
SilcInt32 *x = va_arg(ap, SilcInt32 *);
- MY_HAS_SPACE(src, 4);
+ UNFORMAT_HAS_SPACE(src, 4);
if (x)
SILC_GET32_MSB(*x, src->data);
silc_buffer_pull(src, 4);
case SILC_BUFFER_PARAM_UI32_INT:
{
SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
- MY_HAS_SPACE(src, 4);
+ UNFORMAT_HAS_SPACE(src, 4);
if (x)
SILC_GET32_MSB(*x, src->data);
silc_buffer_pull(src, 4);
case SILC_BUFFER_PARAM_SI64_INT:
{
SilcInt64 *x = va_arg(ap, SilcInt64 *);
- MY_HAS_SPACE(src, sizeof(SilcInt64));
+ UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
if (x)
SILC_GET64_MSB(*x, src->data);
silc_buffer_pull(src, sizeof(SilcInt64));
case SILC_BUFFER_PARAM_UI64_INT:
{
SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
- MY_HAS_SPACE(src, sizeof(SilcUInt64));
+ UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
if (x)
SILC_GET64_MSB(*x, src->data);
silc_buffer_pull(src, sizeof(SilcUInt64));
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x)
*x = src->data;
silc_buffer_pull(src, len2);
{
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x)
*x = src->data;
silc_buffer_pull(src, len2);
{
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x && len2) {
*x = silc_calloc(len2 + 1, sizeof(unsigned char));
memcpy(*x, src->data, len2);
{
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x && len2) {
*x = silc_calloc(len2 + 1, sizeof(unsigned char));
memcpy(*x, src->data, len2);
{
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 4);
+ UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x)
*x = src->data;
silc_buffer_pull(src, len2);
{
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
- MY_HAS_SPACE(src, 4);
+ UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (x && len2) {
*x = silc_calloc(len2 + 1, sizeof(unsigned char));
memcpy(*x, src->data, len2);
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (len)
*len = len2;
if (x)
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (len)
*len = len2;
if (x)
SilcUInt8 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
- MY_HAS_SPACE(src, 1);
+ UNFORMAT_HAS_SPACE(src, 1);
len2 = (SilcUInt8)src->data[0];
silc_buffer_pull(src, 1);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (len)
*len = len2;
if (x && len2) {
SilcUInt16 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
- MY_HAS_SPACE(src, 2);
+ UNFORMAT_HAS_SPACE(src, 2);
SILC_GET16_MSB(len2, src->data);
silc_buffer_pull(src, 2);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (len)
*len = len2;
if (x && len2) {
SilcUInt32 len2;
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
- MY_HAS_SPACE(src, 4);
+ UNFORMAT_HAS_SPACE(src, 4);
SILC_GET32_MSB(len2, src->data);
silc_buffer_pull(src, 4);
- MY_HAS_SPACE(src, len2);
+ UNFORMAT_HAS_SPACE(src, len2);
if (len)
*len = len2;
if (x)
{
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 len = va_arg(ap, SilcUInt32);
- MY_HAS_SPACE(src, len);
+ UNFORMAT_HAS_SPACE(src, len);
if (len && x)
*x = src->data;
silc_buffer_pull(src, len);
{
unsigned char **x = va_arg(ap, unsigned char **);
SilcUInt32 len = va_arg(ap, SilcUInt32);
- MY_HAS_SPACE(src, len);
+ UNFORMAT_HAS_SPACE(src, len);
if (len && x) {
*x = silc_calloc(len + 1, sizeof(unsigned char));
memcpy(*x, src->data, len);
int silc_buffer_strformat(SilcBuffer dst, ...)
{
- int len = dst->truelen;
+ int len = silc_buffer_truelen(dst);
+ va_list va;
+
+ va_start(va, dst);
+
+ /* Parse the arguments by formatting type. */
+ while(1) {
+ char *string = va_arg(va, char *);
+ unsigned char *d;
+ SilcInt32 slen;
+
+ if (!string)
+ continue;
+ if (string == (char *)SILC_BUFFER_PARAM_END)
+ goto ok;
+
+ slen = strlen(string);
+ d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
+ if (!d)
+ return -1;
+ dst->head = d;
+ memcpy(dst->head + len, string, slen);
+ len += slen;
+ dst->head[len] = '\0';
+ }
+
+ SILC_LOG_DEBUG(("Error occured while formatting buffer"));
+ va_end(va);
+ return -1;
+
+ ok:
+ dst->end = dst->head + len;
+ dst->data = dst->head;
+ dst->tail = dst->end;
+
+ va_end(va);
+ return len;
+}
+
+/* Formats strings into a buffer. Allocates memory from SilcStack. */
+
+int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
+{
+ int len = silc_buffer_truelen(dst);
va_list va;
va_start(va, dst);
/* Parse the arguments by formatting type. */
while(1) {
char *string = va_arg(va, char *);
+ unsigned char *d;
+ SilcInt32 slen;
if (!string)
continue;
if (string == (char *)SILC_BUFFER_PARAM_END)
goto ok;
- dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
- (strlen(string) + len));
- memcpy(dst->head + len, string, strlen(string));
- len += strlen(string);
+ slen = strlen(string);
+ d = silc_srealloc_ua(stack, len, dst->head,
+ sizeof(*dst->head) * (slen + len + 1));
+ if (!d)
+ return -1;
+ dst->head = d;
+ memcpy(dst->head + len, string, slen);
+ len += slen;
+ dst->head[len] = '\0';
}
SILC_LOG_DEBUG(("Error occured while formatting buffer"));
ok:
dst->end = dst->head + len;
- dst->tail = dst->data = dst->end;
- dst->len = 0;
- dst->truelen = len;
+ dst->data = dst->head;
+ dst->tail = dst->end;
va_end(va);
return len;