/*

  silcargument.h

  Author: Pekka Riikonen <priikone@silcnet.org>

  Copyright (C) 2001 - 2007 Pekka Riikonen

  The contents of this file are subject to one of the Licenses specified 
  in the COPYING file;  You may not use this file except in compliance 
  with the License.

  The software distributed under the License is distributed on an "AS IS"
  basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
  KIND, either expressed or implied.  See the COPYING file for more
  information.

*/

/****h* silccore/SILC Argument Interface
 *
 * DESCRIPTION
 *
 * Implementations of the Argument Payload and Argument List Payload, that
 * is used to include arguments to other payload that needs arguments.
 *
 ***/

#ifndef SILCARGUMENT_H
#define SILCARGUMENT_H

/****s* silccore/SilcArgumentAPI/SilcArgumentPayload
 *
 * NAME
 *
 *    typedef struct SilcArgumentPayloadStruct *SilcArgumentPayload;
 *
 * DESCRIPTION
 *
 *    This context is the actual Argument Payload and is allocated
 *    by silc_argument_payload_parse and given as argument usually to
 *    all silc_argument_payload_* functions.  It is freed by the
 *    silc_argument_payload_free function.
 *
 ***/
typedef struct SilcArgumentPayloadStruct *SilcArgumentPayload;

/****f* silccore/SilcArgumentAPI/silc_argument_payload_parse
 *
 * SYNOPSIS
 *
 *    SilcArgumentPayload
 *    silc_argument_payload_parse(const unsigned char *payload,
 *                                SilcUInt32 payload_len,
 *                                SilcUInt32 argc);
 *
 * DESCRIPTION
 *
 *    Parses arguments and returns them into Argument Payload structure.
 *    the `buffer' is raw Argument Payload data buffer. The `argc' is
 *    the number of arguments in the Argument Payload. The caller must
 *    know the number of the arguments. This is always known as the
 *    Argument payload is associated with other payloads which defines
 *    the number of the arguments.
 *
 ***/
SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
						SilcUInt32 payload_len,
						SilcUInt32 argc);

/****f* silccore/SilcArgumentAPI/silc_argument_payload_encode
 *
 * SYNOPSIS
 *
 *    SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
 *                                            unsigned char **argv,
 *                                            SilcUInt32 *argv_lens,
 *                                            SilcUInt32 *argv_types);
 *
 * DESCRIPTION
 *
 *    Encodes arguments in to Argument Paylods returning them to SilcBuffer.
 *    The `argv' is the array of the arguments, the `argv_lens' array of
 *    the length of the `argv' arguments and the `argv_types' array of
 *    the argument types of the `argv' arguments. The `argc' is the
 *    number of arguments.
 *
 ***/
SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
					unsigned char **argv,
					SilcUInt32 *argv_lens,
					SilcUInt32 *argv_types);

/****f* silccore/SilcArgumentAPI/silc_argument_payload_encode_one
 *
 * SYNOPSIS
 *
 *    SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
 *                                                unsigned char *arg,
 *                                                SilcUInt32 arg_len,
 *                                                SilcUInt32 arg_type);
 *
 * DESCRIPTION
 *
 *    Same as silc_argument_payload_encode but encodes one argument to
 *    the buffer `args' and returns the buffer.  The returned buffer
 *    may be different than the `args'.  If `args' is NULL for the first
 *    argument this allocates the buffer and returns it.
 *
 ***/
SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
					    unsigned char *arg,
					    SilcUInt32 arg_len,
					    SilcUInt32 arg_type);

/****f* silccore/SilcArgumentAPI/silc_argument_payload_encode_payload
 *
 * SYNOPSIS
 *
 *    SilcBuffer
 *    silc_argument_payload_encode_payload(SilcArgumentPayload payload);
 *
 * DESCRIPTION
 *
 *    Same as silc_argument_payload_encode but encodes the payload from
 *    already allocated SilcArgumentPayload structure instead of raw data.
 *
 ***/
SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload);

/****f* silccore/SilcArgumentAPI/silc_argument_payload_free
 *
 * SYNOPSIS
 *
 *    void silc_argument_payload_free(SilcArgumentPayload payload);
 *
 * DESCRIPTION
 *
 *    Frees the Argument Payload and all data in it.
 *
 ***/
void silc_argument_payload_free(SilcArgumentPayload payload);

/****f* silccore/SilcArgumentAPI/silc_argument_get_arg_num
 *
 * SYNOPSIS
 *
 *    SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload);
 *
 * DESCRIPTION
 *
 *    Returns the number of arguments in the Argument Payload.
 *
 ***/
SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload);

/****f* silccore/SilcArgumentAPI/silc_argument_get_first_arg
 *
 * SYNOPSIS
 *
 *    unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
 *                                               SilcUInt32 *type,
 *                                               SilcUInt32 *ret_len);
 *
 * DESCRIPTION
 *
 *    Returns the first argument in the Argument Payload. The lenght
 *    of the argument is returned to `ret_len'. The caller must not
 *    free the returned argument. Returns NULL on error.
 *
 ***/
unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
					   SilcUInt32 *type,
					   SilcUInt32 *ret_len);

/****f* silccore/SilcArgumentAPI/silc_argument_get_next_arg
 *
 * SYNOPSIS
 *
 *    unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
 *                                              SilcUInt32 *ret_len);
 *
 * DESCRIPTION
 *
 *    Returns next argument from the Argument Payload. The length of
 *    the argument is returned to `ret_len'. The caller must not free
 *    the returned argument. This returns NULL when there are no more
 *    arguments in the payload.
 *
 ***/
unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
					  SilcUInt32 *type,
					  SilcUInt32 *ret_len);

/****f* silccore/SilcArgumentAPI/silc_argument_get_arg_type
 *
 * SYNOPSIS
 *
 *    unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
 *                                              SilcUInt32 type,
 *                                              SilcUInt32 *ret_len);
 *
 * DESCRIPTION
 *
 *    Returns argument by type. The returned argument has type `type'
 *    in the Argument Payload. Each argument has their own type (or zero
 *    if no specific type is set). The length of the argument is returned
 *    to the `ret_len'. The caller must not free the returned argument.
 *    Returns NULL on error.
 *
 ***/
unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
					  SilcUInt32 type,
					  SilcUInt32 *ret_len);

/****d* silccore/SilcArgumentAPI/SilcArgumentDecodeType
 *
 * NAME
 *
 *    typedef enum { ... } SilcArgumentDecodeType;
 *
 * DESCRIPTION
 *
 *    Argument decode types used with silc_argument_get_decoded.
 *
 * SOURCE
 */
typedef enum {
  SILC_ARGUMENT_ID,		/* SilcID */
  SILC_ARGUMENT_PUBLIC_KEY,	/* SilcPublicKey (always alloc) */
  SILC_ARGUMENT_ATTRIBUTES,	/* SilcDList (always alloc) */
  SILC_ARGUMENT_UINT32,		/* SilcUInt32 */
  SILC_ARGUMENT_BOOL,		/* SilcBool */
} SilcArgumentDecodeType;
/***/

/****f* silccore/SilcArgumentAPI/silc_argument_get_decoded
 *
 * SYNOPSIS
 *
 *    SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
 *                                       SilcUInt32 type,
 *                                       SilcArgumentDecodeType dec_type,
 *                                       void *ret_arg,
 *                                       void *ret_arg_alloc);
 *
 * DESCRIPTION
 *
 *    Returns decoded argument by type.  This is a helper function to
 *    decode common argument types directly.  The `type' is the argument
 *    type number in the payload, and the `dec_type' is the type the
 *    argument is decoded to.  If the `ret_arg' is non-NULL then the
 *    decodec data is returned into that pointer.  If the `ret_arg_alloc'
 *    is non-NULL then this function will allocate the decoded data and
 *    will return the pointer into `ret_arg_alloc'.  Some types must always
 *    be allocated; see SilcArgumentDecodeType.
 *
 *    Return TRUE if the argument was present and waa successfully decoded.
 *    FALSE if it is not present, or could not be decoded.
 *
 * EXAMPLE
 *
 *    SilcID id;
 *    SilcPublicKey public_key;
 *
 *    if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id, NULL))
 *      error;
 *
 *    if (!silc_argument_get_decoded(args, 4, SILC_ARGUMENT_PUBLIC_KEY,
 *                                   NULL, &public_key))
 *      error;
 *
 ***/
SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
				   SilcUInt32 type,
				   SilcArgumentDecodeType dec_type,
				   void *ret_arg,
				   void **ret_arg_alloc);

/****f* silccore/SilcArgumentAPI/silc_argument_list_parse
 *
 * SYNOPSIS
 *
 *    SilcArgumentPayload
 *    silc_argument_list_parse(const unsigned char *payload,
 *                             SilcUInt32 payload_len);
 *
 * DESCRIPTION
 *
 *    Parses argument list payload.  Returns parsed SilcArgumentPayload which
 *    contains all the arguments from the list.  The caller must free the
 *    returned context with silc_argument_payload_free.
 *
 ***/
SilcArgumentPayload
silc_argument_list_parse(const unsigned char *payload, SilcUInt32 payload_len);

/****s* silccore/SilcArgumentAPI/SilcArgumentDecodedList
 *
 * NAME
 *
 *    typedef struct { ... } *SilcArgumentDecodedList;
 *
 * DESCRIPTION
 *
 *    This structure is in the list returned by the function
 *    silc_argument_list_payload_parse_decoded.  The caller is responsible
 *    of freeing the contents of the structure and the structure itself.
 *
 ***/
typedef struct SilcArgumentDecodedListStruct {
  void *argument;	     /* Decoded argument, caller must know its type */
  SilcUInt32 arg_type;	     /* Argument type number from the payload */
} *SilcArgumentDecodedList;

/****f* silccore/SilcArgumentAPI/silc_argument_list_parse_decoded
 *
 * SYNOPSIS
 *
 *    SilcDList
 *    silc_argument_list_parse_decoded(const unsigned char *payload,
 *                                     SilcUInt32 payload_len,
 *                                     SilcArgumentDecodeType dec_type);
 *
 * DESCRIPTION
 *
 *    Parses argument list payload of arguments of the type `dec_type'.
 *    The returned list includes the already decoded arguments.  The caller
 *    is responsible of freeing the the contents of the list and the list
 *    itself.  Each entry in the list is SilcArgumentDecodedList.  The
 *    caller must free the returned list with silc_argument_list_free.
 *
 ***/
SilcDList
silc_argument_list_parse_decoded(const unsigned char *payload,
				 SilcUInt32 payload_len,
				 SilcArgumentDecodeType dec_type);

/****f* silccore/SilcArgumentAPI/silc_argument_list_free
 *
 * SYNOPSIS
 *
 *    void
 *    silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type);
 *
 * DESCRIPTION
 *
 *    Free's the decoded argument list and its contents.
 *
 ***/
void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type);

#endif /* SILCARGUMENT_H */
