Added SILC_STR_ADVANCE.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 18 Sep 2006 21:09:36 +0000 (21:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 18 Sep 2006 21:09:36 +0000 (21:09 +0000)
silc_buffer_strformat preserves buffer locations.

lib/silcutil/silcbuffmt.c
lib/silcutil/silcbuffmt.h

index 6ba9ac9638a134b7bc6b67150cab6aeee86ce4db..4dd54965084e33a18a8351c6e6da426d0311dc31 100644 (file)
@@ -78,6 +78,7 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
 {
   SilcBufferParamType fmt;
   int flen = 0;
+  SilcBool advance = FALSE;
 
   /* Parse the arguments by formatting type. */
   while (1) {
@@ -194,10 +195,12 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
     case SILC_BUFFER_PARAM_UI16_NSTRING:
     case SILC_BUFFER_PARAM_UI32_NSTRING:
     case SILC_BUFFER_PARAM_UI_XNSTRING:
+    case SILC_BUFFER_PARAM_DATA:
     case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
     case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
     case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
+    case SILC_BUFFER_PARAM_DATA_ALLOC:
       {
        unsigned char *x = va_arg(ap, unsigned char *);
        SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
@@ -211,6 +214,9 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
     case SILC_BUFFER_PARAM_END:
       goto ok;
       break;
+    case SILC_BUFFER_PARAM_ADVANCE:
+      advance = TRUE;
+      break;
     default:
       SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
                      "format the data.", fmt));
@@ -221,12 +227,14 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
 
  fail:
   SILC_LOG_DEBUG(("Error occured while formatting data"));
-  silc_buffer_push(dst, flen);
+  if (!advance)
+    silc_buffer_push(dst, flen);
   return -1;
 
  ok:
   /* Push the buffer back to where it belongs. */
-  silc_buffer_push(dst, flen);
+  if (!advance)
+    silc_buffer_push(dst, flen);
   return flen;
 }
 
@@ -510,6 +518,7 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
        break;
       }
     case SILC_BUFFER_PARAM_UI_XNSTRING:
+    case SILC_BUFFER_PARAM_DATA:
       {
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len = va_arg(ap, SilcUInt32);
@@ -520,6 +529,7 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
        break;
       }
     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
+    case SILC_BUFFER_PARAM_DATA_ALLOC:
       {
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len = va_arg(ap, SilcUInt32);
@@ -534,6 +544,8 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
     case SILC_BUFFER_PARAM_END:
       goto ok;
       break;
+    case SILC_BUFFER_PARAM_ADVANCE:
+      break;
     default:
       SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
                      "format the data.", fmt));
@@ -563,6 +575,7 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
 int silc_buffer_strformat(SilcBuffer dst, ...)
 {
   int len = silc_buffer_truelen(dst);
+  int hlen = silc_buffer_headlen(dst);
   va_list va;
 
   va_start(va, dst);
@@ -594,7 +607,7 @@ int silc_buffer_strformat(SilcBuffer dst, ...)
 
  ok:
   dst->end = dst->head + len;
-  dst->data = dst->head;
+  dst->data = dst->head + hlen;
   dst->tail = dst->end;
 
   va_end(va);
index 339459ce2ef786381fd8c65796a99f0aa329b9aa..cf0ed7b3f2f2f9b7204d43f87e9d48d58fd035ea 100644 (file)
@@ -49,6 +49,7 @@
  * EXAMPLE
  *
  *    SilcBufferStruct buffer;
+ *    SilcBuffer buf;
  *
  *    memset(&buffer, 0, sizeof(buffer));
  *    ret = silc_buffer_format(&buffer,
  *    // Free the allocated data
  *    silc_buffer_purge(&buffer);
  *
+ *    // Allocate zero size buffer
+ *    buf = silc_buffer_alloc();
+ *    ret = silc_buffer_format(buf,
+ *                             SILC_STR_INT(intval),
+ *                             SILC_STR_CHAR(charval),
+ *                             SILC_STR_END);
+ *
+ *    // Free the allocated buffer
+ *    silc_buffer_free(buf);
+ *
  ***/
 int silc_buffer_format(SilcBuffer dst, ...);
 
@@ -235,8 +246,11 @@ typedef enum {
   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_DATA,              /* No copy */
+  SILC_BUFFER_PARAM_DATA_ALLOC,                /* Alloc + memcpy */
 
   SILC_BUFFER_PARAM_OFFSET,
+  SILC_BUFFER_PARAM_ADVANCE,
 
   SILC_BUFFER_PARAM_END
 } SilcBufferParamType;
@@ -424,33 +438,32 @@ typedef enum {
 #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \
   SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC, (x), (l)
 
-/****d* silcutil/SilcBufferFormatAPI/SILC_STR_UI_XNSTRING
+/****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
  *
  * NAME
  *
- *    #define SILC_STR_UI_XNSTRING() ...
- *    #define SILC_STR_UI_XNSTRING_ALLOC() ...
+ *    #define SILC_STR_DATA() ...
+ *    #define SILC_STR_DATA_ALLOC() ...
  *
  * DESCRIPTION
  *
- *    Extended Unsigned string formatting. Second argument is the length of
- *    the string.
+ *    Binary data formatting.  Second argument is the lenght of the data.
  *
- *    Formatting:    SILC_STR_UI_XNSTRING(unsigned char *, SilcUInt32)
- *    Unformatting:  SILC_STR_UI_XNSTRING(unsigned char **, SilcUInt32)
+ *    Formatting:    SILC_STR_DATA(unsigned char *, SilcUInt32)
+ *    Unformatting:  SILC_STR_DATA(unsigned char **, SilcUInt32)
  *
- *    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.
+ *    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_BUFFER_PARAM_DATA, (x), (l)
+#define SILC_STR_DATA_ALLOC(x, l) \
+  SILC_BUFFER_PARAM_DATA_ALLOC, (x), (l)
+
+/* Deprecated */
 #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)
@@ -480,6 +493,38 @@ typedef enum {
  ***/
 #define SILC_STR_OFFSET(x) SILC_BUFFER_PARAM_OFFSET, (x)
 
+/****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 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
+ *    easy to add new data immediately after the previously added data.
+ *
+ * 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_UI_XNSTRING(buf, len),
+ *                           SILC_STR_END);
+ *    } while (len > 0);
+ *
+ *    // Move to beginning of buffer
+ *    silc_buffer_push(buffer, silc_buffer_truelen(buffer));
+ *
+ ***/
+#define SILC_STR_ADVANCE SILC_BUFFER_PARAM_ADVANCE
+
 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
  *
  * NAME