/**
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *      disclaimer in the documentation and/or other materials provided
 *      with the distribution.
 *    * Neither the name of The Linux Foundation nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef AEEBUFBOUND_H
#define AEEBUFBOUND_H
/*==============================================================================

FILE:  AEEBufBound.h

SERVICES:
        BufBound APIs

GENERAL DESCRIPTION:
        BufBound provides a "bounded buffer" API that facilitates
          measuring strings or character output.  It's design accomodates
          the implementation of functions that can have the same exact logic
          for measuring and outputting char buffer content.

REVISION HISTORY:
        Fri Aug 08 17:38:29 2003: Created

==============================================================================*/

typedef struct BufBound
{
   char* pcBuf;   /* original buffer */
   char* pcWrite; /* write pointer */
   char* pcEnd;   /* first illegal write pointer */
} BufBound;

#ifdef __cplusplus
extern "C" {
#endif /* #ifdef __cplusplus */

extern void BufBound_Init(BufBound *me, char *pBuf, int nLen);
extern void BufBound_Write(BufBound *me, const char *pc, int nLen);
extern void BufBound_Putc(BufBound *me, char c);
extern void BufBound_Putnc(BufBound *me, char c, int nCount);
extern void BufBound_ForceNullTerm(BufBound *me);
extern void BufBound_Puts(BufBound *me, const char* cpsz);
extern void BufBound_Advance(BufBound *me, int nLen);
extern void BufBound_WriteLE(BufBound* me,
                             const void *pvSrc, int nSrcSize,
                             const char *pszFields);
extern void BufBound_WriteBE(BufBound* me,
                             const void *pvSrc, int nSrcSize,
                             const char *pszFields);
extern int BufBound_BufSize(BufBound *me);
extern int BufBound_Left(BufBound* me);
extern int BufBound_ReallyWrote(BufBound* me);
extern int BufBound_Wrote(BufBound* me);

static __inline int BufBound_IsFull(BufBound* me)
{
   return (BufBound_Left(me) <= 0);
}

// Deprecated:
static __inline int BufBound_IsCounter(BufBound* me)
{
   return BufBound_BufSize(me) == 0;
}

#ifdef __cplusplus
}
#endif /* #ifdef __cplusplus */


/*=====================================================================
=======================================================================
DATA STRUCTURE DOCUMENTATION
=======================================================================

BufBound

Description:
   An BufBound keeps track of whether appending to a bounded buffer
    has overflowed.

Definition:
   typedef struct BufBound
   {
      char* pcBuf;
      char* pcWrite;
      char* pcEnd;
   } BufBound;

Members:
      pcBuf: original start pointer
      pcWrite: current write location
      pcEnd: first illegal write position

See Also:
      BufBound Interface

=======================================================================
INTERFACE DOCUMENTATION
=======================================================================
BufBound Interface

  BufBound is a statically-linked interface.

  BufBound provides functions for safely appending to a character buffer.  On
  initialization, the buffer start address and size are provided.  Subsequent
  write operations are checked against the buffer bounds.

  Once the buffer bounds are exceeded, no bytes will be written but the
  BufBound will continue to increment its internal "write pointer" to reflect
  the number of bytes that would have been written (had the bounds not been
  exceeded).

  When initialized with a buffer size of zero, a BufBound simply counts the
  number of bytes that would be required to contain the result.  This design
  accommodates implementations that use the same logic for generating output
  and measuring the space required for generated output.

  BufBound protects clients from numerical overflow by limiting the write
  pointer to a maximum offset of INT_MAX from the start of the buffer.
  Functions that write data into the buffer safely ignore negative size inputs
  (Write and Putnc).

=======================================================================
BufBound_Init()

Description:
   initialize a BufBound for appending to a buffer

Prototype:

   void BufBound_Init(BufBound *me, char *pBuf, int nLen);

Parameters:
   me: the BufBound
   pBuf: the bounded buffer
   nLen: size of pBuf, in bytes

Return Value:
   None

Comments:
   None

Side Effects:
   None

See Also:
   None

=======================================================================

BufBound_Write()

Description:
   Appends some number of bytes to a BufBound, if possible.

   When a negative size is passed, it is safely treated as zero.

Prototype:

   void BufBound_Write(BufBound *me, const char *pc, int nLen);

Parameters:
   me: the BufBound
   pc: pointer to bytes to append
   int nLen: number of bytes to write

Return Value:
   None

Comments:
   If the BufBound has overflowed, no bytes are written, but pcWrite is
      *always* advanced by nLen.

Side Effects:
   None

See Also:
   None

=======================================================================

BufBound_Advance()

Description:

   Moves the write pointer.  Advance is like a relative seek operation.  It
   does not change the contents of the buffer, so when using a forward seek
   (positive advance) be careful of advancing over uninitialized data.

   Negative numbers will decrease the write pointer down to 0 (the start of
   the buffer) and not below.  Positive numbers will increase the write
   pointer up to offset INT_MAX and not beyond.

Prototype:

   void BufBound_Advance(BufBound *me, int nDelta);

Parameters:
   me: the BufBound
   int nLen: number of bytes to advance

Return Value:
   None

Comments:
   None

Side Effects:
   None

See Also:
   None

=======================================================================

BufBound_Putc()

Description:
   Appends one byte to a BufBound, if possible.

Prototype:

   void BufBound_Putc(BufBound *me, char c);

Parameters:
   me: the BufBound
   c: the byte

Return Value:
   None

Comments:
   If the BufBound has overflowed, no byte is written, but pcWrite is
      *always* advanced by 1.

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_Putnc()

Description:
   Appends a byte to a BufBound repeatedly.

   When a negative size is passed, it is safely treated as zero.

Prototype:

   void BufBound_Putnc(BufBound *me, char c, int nCount);

Parameters:
   me: the BufBound
   c: the byte
   nCount: number of times to append c

Return Value:
   None

Comments:
   If the BufBound has overflowed, no byte is written, but pcWrite is
      *always* advanced by nCount.

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_ForceNullTerm()

Description:
   Appends a null terminating character to a BufBound, if possible.
     If the BufBound has overflowed, the last legal location is
     set to '\0'.

Prototype:
   void BufBound_ForceNullTerm(BufBound *me);

Parameters:
   me: the BufBound

Return Value:
   None

Comments:
   pcWrite is *always* advanced by 1.

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_Puts()

Description:
   Appends a null-terminated string to a BufBound, if possible

Prototype:

   void BufBound_Puts(BufBound *me, const char* cpsz);

Parameters:
   me: the BufBound
   cpsz: the string to append

Return Value:

Comments:
   If the BufBound has overflowed, no bytes are written, but pcWrite is
      *always* advanced by strlen(cpsz).

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_BufSize()

Description:
   Returns the size of the buffer owned by the BufBound.  This is
   the same as the number passed to BufBound_Init (MAXed with zero).

Prototype:

   int BufBound_IsCounter(BufBound* me);

Parameters:
   me: the BufBound

Return Value:
   1 if the BufBound is a counter, 0 otherwise

Comments:
   None

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_Left()

Description:
   Returns the number of bytes the BufBound can still accomodate,
   without overflowing.  If overflow has occurred, it will return
   a negative number.

Prototype:

   int BufBound_Left(BufBound* me);

Parameters:
    me: the BufBound

Return Value:
   The number of bytes the BufBound can still accomodate,
     without overflowing.

Comments:
   The return value may be negative, if overflow has already occurred.

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_ReallyWrote()

Description:
   Returns the number of bytes actually written to the BufBound,
     not including any overflow.

Prototype:

   int BufBound_ReallyWrote(BufBound* me);

Parameters:
    me: the BufBound

Return Value:
   The number of bytes actually written to the BufBound,
     not including any overflow.

Comments:
   None

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_Wrote()

Description:

   Returns the number of bytes written to the BufBound, including any
   overflow, up to INT_MAX.

Prototype:

   int BufBound_Wrote(BufBound* me);

Parameters:
    me: the BufBound

Return Value:

   The number of bytes written to the BufBound, including any overflow.

Comments:
   None

Side Effects:
   None

See Also:
   None


=======================================================================

BufBound_IsFull()

Description:
   Tests whether an AEEBuffBound has overflowed.

Prototype:

   int BufBound_IsFull(BufBound* me);

Parameters:
    me: the BufBound

Return Value:
   1 if the BufBound has overflowed, 0 otherwise

Comments:
   None

Side Effects:
   None

See Also:
   None

=======================================================================

BufBound_WriteLE()

Description:

   Writes data while translating numeric values between host byte ordering and
   "little endian" byte ordering.

   The input buffer is treated as an array of structures.  The 'abySizes'
   parameter describes the sizes of fields in the structure.

   When the host byte ordering matches the target byte ordering (little
   endian) this operation is equivalent to BufBound_Write().

Prototype:

   void BufBound_WriteLE(BufBound* me,
                         const void *pvSrc, int nSrcSize,
                         const unsigned char *pszFields);

Parameters:
   me:        the BufBound
   pvSrc:     the source buffer
   nSrcSize:  number of bytes to copy from the source buffer
   pszFields: Description of the fields that comprise the source data,
              as defined in std_CopyLE.

Return Value:
   None

See Also:
   BufBound_WriteBE, std_CopyLE

=======================================================================

BufBound_WriteBE()

Description:

   BufBounf_WriteBE() has the same semantics as BufBound_WriteLE() except it
   copies between host byte ordering and big-endian ("network") byte order.

   See BufBound_WriteLE() for more details.


Prototype:

   void BufBound_WriteBE(BufBound* me,
                         const void *pvSrc, int nSrcSize,
                         const unsigned char *pszFields);

Parameters:
   me:        the BufBound
   pvSrc:     the source buffer
   nSrcSize:  number of bytes to copy from the source buffer
   pszFields: Description of the fields that comprise the source data,
              as defined in std_CopyLE.

Return Value:
   None

See Also:
   BufBound_WriteLE, std_CopyBE

======================================================================= */
#endif /* #ifndef AEEBUFBOUND_H */

