/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 *
 * License: GPL (version 3 or any later version).
 * See LICENSE for details.
 * END COPYRIGHT BLOCK **/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifndef __attrec_h
#define __attrec_h

/*
 * Description (attrec.h)
 *
 *    This file describes the encoding and decoding of attribute
 *    records.  Attribute records consist of a sequence of items
 *    of the form:
 *
 *        <tag><length><contents>
 *
 *    The <tag> is an integer code which identifies a particular
 *    attribute.  The <length> is the integer length in bytes of
 *    the <contents>.  The encoding of the contents is determined
 *    by the <tag>, and is application-specific.
 *
 *    Primitive data types currently supported are unsigned
 *    integers (USI) and null-terminated strings (NTS).  The
 *    encoding of USI values less than 128 is simply an octet
 *    containing the value.  For values 128 or greater, the first
 *    octet is 0x80 plus the length of the value, in octets.
 *    This octet is followed by the indicated number of octets,
 *    containing the USI value, with the most significant bits in
 *    the first octet, and the least significant bits in the last
 *    octet.
 *
 *    Examples of USI encoding:
 *
 *        Value        Encoding (each value is an octet)
 *            4        0x04
 *          127        0x7f
 *           -1        (this is not a USI)
 *          128        0x81 0x80
 *         1023        0x82 0x03 0xff
 *
 *    The encoding of a null-terminated string (NTS) is simply the
 *    sequence of octets which comprise the string, including the
 *    terminating null (0x00) octet.  The terminating null octet is
 *    the only null value in the string.  The character set used to
 *    encode the other string octets is ASCII.
 */

#include "usi.h"

NSPR_BEGIN_EXTERN_C

/* Define a type to reference an attribute record */
typedef unsigned char *ATR_t;

/*
 * Description (USILENGTH)
 *
 *    This macro returns the length of the USI encoding for a specified
 *    unsigned integer value.  The length is the number of octets
 *    required.  It will be greater than zero, and less than or equal
 *    to USIALLOC().  This is a partial inline optimization of
 *    USI_Length().
 */

#define USILENGTH(val) (((USI_t)(val) <= 0x7f) ? 1 : USI_Length((USI_t)(val)))

/*
 * Description (USIALLOC)
 *
 *    This macro returns the maximum length of an unsigned integer
 *    encoding.
 */

#define USIALLOC() (5)

/*
 * Description (USIENCODE)
 *
 *    This macro encodes a USI value into a specified buffer.  It
 *    returns a pointer to the first octet after the encoding.
 *    This is a partial inline optimization for USI_Encode().
 */

#define USIENCODE(cp, val) (((USI_t)(val) <= 0x7f) ? (*(cp) = (val), (cp) + 1) \
                                                   : USI_Encode((cp), (val)))

/*
 * Description (USIINSERT)
 *
 *    This macro performs a variation of USIENCODE which always
 *    generates the maximum-sized USI encoding, i.e. the number of
 *    octets indicated by USIALLOC().
 */

#define USIINSERT(cp, val) USI_Insert((ATR_t)(cp), (USI_t)(val))

/*
 * Description (USIDECODE)
 *
 *    This macro decodes a USI value from a specified buffer.  It
 *    returns a pointer to the first octet after the encoding.
 *    This is a partial inline optimization for USI_Decode().
 */

#define USIDECODE(cp, pval)                  \
    ((*(cp)&0x80) ? USI_Decode((cp), (pval)) \
                  : (((pval) ? (*(pval) = *(cp)) : 0), (cp) + 1))

/* Define a type to reference a null-terminated string */
typedef unsigned char *NTS_t;

/*
 * Decription (NTSLENGTH)
 *
 *    Return the length, in octets, of a null-terminated string.
 *    It includes the terminating null octet.
 */

#define NTSLENGTH(nts) ((nts) ? strlen((char *)(nts)) + 1 : 1)

/*
 * Description (NTSENCODE)
 *
 *    This macro copies a null-terminated string to a specified
 *    attribute record buffer.  It returns a pointer to the octet
 *    following the NTS in the buffer.
 */

#define NTSENCODE(cp, nts)                                       \
    ((ATR_t)memccpy((void *)(cp),                                \
                    (void *)((nts) ? (NTS_t)(nts) : (NTS_t) ""), \
                    0, NTSLENGTH(nts)))

/*
 * Description (NTSDECODE)
 *
 *    This macro decodes a null-terminated string in a specified
 *    attribute record buffer into a dynamically allocated buffer.
 *    It returns a pointer to the first octet after the NTS in the
 *    attribute record buffer.
 */

#define NTSDECODE(cp, pnts) NTS_Decode((cp), (pnts))

/* Functions in attrec.c */
extern int NTS_Length(NTS_t ntsp);
extern ATR_t NTS_Decode(ATR_t cp, NTS_t *pnts);
extern ATR_t NTS_Encode(ATR_t cp, NTS_t nts);
extern ATR_t USI_Decode(ATR_t cp, USI_t *pval);
extern ATR_t USI_Encode(ATR_t cp, USI_t val);
extern ATR_t USI_Insert(ATR_t cp, USI_t val);
extern int USI_Length(USI_t val);

NSPR_END_EXTERN_C

#endif /* __attrec_h */
