/**************************************************************************** 
** File: hexbuffer.c
**
** Author: Mike Borella
**
** Comments: Hex buffer manipulation routines
**
** $Id: hexbuffer.c,v 1.6 2007/06/25 10:17:57 farooq-i-azam Exp $
**
** 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.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/

#include "hexbuffer.h"
#include "display.h"
#include "error.h"

#define HEXBUFFER_SIZE  4000 /* max size of hex buffer */
#define TEMPBUFFER_SIZE 128

static u_int8_t  hexbuffer[HEXBUFFER_SIZE];
static u_int16_t current_ptr = 0;

extern struct arg_t * my_args;

/*----------------------------------------------------------------------------
**
** hexbuffer_kill()
**
** Reset the hex buffer without displaying its contents
**
**----------------------------------------------------------------------------
*/

inline void hexbuffer_kill()
{
  /*
   * Sanity check
   */
  if (!my_args->x || my_args->m)
    return;

  current_ptr = 0;
}

/*----------------------------------------------------------------------------
**
** hexbuffer_add()
**
** Add bytes to the hex buffer
**
**----------------------------------------------------------------------------
*/

inline void hexbuffer_add(u_int8_t * bytes, int length)
{
  /*
   * Sanity checks
   */
  if (!my_args->x || my_args->m)
    return;
  if (length < 0)
    error_fatal("can't add length %d string to the hex buffer", length);


  /* check for buffer overflow */
  if (current_ptr + length > HEXBUFFER_SIZE)
    {
      fprintf(stderr,"Hex buffer overflow!\n");
      length = HEXBUFFER_SIZE - current_ptr;
    }

  /* copy the bytes into the hex buffer */
  memcpy(&hexbuffer[current_ptr], bytes, length);
  current_ptr = current_ptr + length;
}

/*----------------------------------------------------------------------------
**
** hexbuffer_flush()
**
** Flush the hex buffer
**
**----------------------------------------------------------------------------
*/

inline void hexbuffer_flush(void)
{
  u_int8_t temp_hexbuf[TEMPBUFFER_SIZE], temp_charbuf[TEMPBUFFER_SIZE];
  u_int8_t *buf_ptr, *buf_end;
  int i;

  /*
   * Sanity check
   */
  if (!my_args->x || my_args->m)
    return;

  /* if there's nothing to print, skip out */
  if (current_ptr == 0)
    return;

  /* mark the beginning and the end of the area to print */
  buf_ptr = &hexbuffer[0];
  buf_end = &hexbuffer[current_ptr];

  /* display some dots as a separator */
  display_header_line(HEADERLINE_DOTS);

  /* loop through the hex buffer, printing a line at a time */
  do
    {
      memset(temp_hexbuf, 0, TEMPBUFFER_SIZE);
      memset(temp_charbuf, 0, TEMPBUFFER_SIZE);

      for(i=0;i<18;i++)
        {
          if(buf_ptr < buf_end)
            {
              snprintf(temp_hexbuf+(i*3), TEMPBUFFER_SIZE-1,"%.2X ",
		       buf_ptr[0] & 0xFF);
              
              if(*buf_ptr > 0x1F && *buf_ptr < 0x7E)
                snprintf(temp_charbuf+i, TEMPBUFFER_SIZE-1, "%c",
			 buf_ptr[0]);
              else
                snprintf(temp_charbuf+i, TEMPBUFFER_SIZE-1, ".");
              
              buf_ptr++;
            }
        }
      if (!check_layer())
	printf("%-54s %s\n", temp_hexbuf, temp_charbuf);
    }
  while(buf_ptr < buf_end);
  
  /* now that the hex buffer is flushed, reset its size */
  current_ptr = 0;
}

