
/* ba_b2hex.c */

/**************************************************************************

  Bit Vectors in C
  
  FILENAME: ba_b2hex.c
  LANGUAGE: ANSI C
  REQUIRES: "types.h" and a definition of BIT_HEX_FORMAT (best included in
            "types.h")

  AUTHOR:   James Blustein <jamie@csd.uwo.ca>
  CREATED:  20 July 1996
  MODIFIED: 20 July 1996  
            (see http://www.csd.uwo.ca/~jamie/BitVectors/New.html
             for other new code).

  IMPORTANT NOTE: This code is an extension to code which I wrote and was 
                 published in 
                  Dr. Dobb's Journal issue #233 (August 1995)
                  Volume 20 Issue 8
                  in an article entitled `Implementing Bit Vectors in C'
                  by James Blustein
                  Pages 42, 44, 46 (article) and pages 96, 98-100 (code)
                  That code is (c) copyright 1995 by Miller Freeman, Inc.
                 This code is not covered by that copyright.

  NOTICE: You are free to use this code for any purpose so long as you 
         include a notice saying that I wrote it and where (and when) you
         obtained it.  These conditions may change with future versions.

 ***************************************************************************/


bool ba_b2hex(const bit     arr[],
              const elem_t  size,
                    char ** dest) {
/*
   ba_b2hex()

   PRE: 1. `arr' is a bit array with at least `size' elements.  Either
           `dest' points to enough allocated space to hold enough 
          characters for the hexadecimal string representation of
	  `arr' or `dest' is NULL and such space is to be dynamically
	  allocated.  See NOTE for the exact amount of space needed.
        2. BIT_HEX_FORMAT must be a quoted pre-processor symbol with
   	  one of the allowable hexadecimal formats for sprintf to
   	  print a variable of type bit (i.e. one of "x", "hx", "lx",
   	  "X", "hX", "lX").  The format *must* correspond to the
   	  definition of bit.
        3. ba_init() must be called before any of the other ba_
       	  functions. 
        4. The <string.h> and <stdio.h> headers must be included.

   POST: Either `dest' points to a null-terminated string that
         contains a character representation of the first `size'
         elements of the bit array `arr';
      OR 
         `dest' is NULL and a request to dynamically allocate memory
         for a string to hold a character representation of `arr' was
         not be granted.

   NOTE: The size of the string of hex digits will be 

             nelem * ((BITS_SZ / 4) + 1)

                  Each hex digit represents 4 bits (log10(16.) = 4)
                  The 1 is because there will be a blank after each
                element, except the last one which will have a null
                character after it.
*/
   #define BITS_PER_HEXIT (4)
          unsigned count      = 0;  
   const  elem_t   nelem      = NELEM(size,(BITS_SZ));
   static char     *onenum    = NULL;
   const  size_t   numofchars = nelem*((BITS_SZ / BITS_PER_HEXIT)+1);
                
   if ((NULL == onenum) && 
        NULL == (onenum = malloc((BITS_SZ / BITS_PER_HEXIT)+1))) {
      return FALSE;
   }

   if ((NULL != dest) || (NULL != (dest = malloc(numofchars)))) {
      register elem_t i; 
      
      *dest[0] = '\0';
      count=0;
      for (i=0; i < nelem; i++) {
         count += sprintf(onenum, "%0*"BIT_HEX_FORMAT"%s", 
                                  BITS_SZ/BITS_PER_HEXIT, 
                                  arr[i],
                                  ((nelem - 1) == i)?"":" ");
         if ((strlen(onenum) + strlen(*dest)) < numofchars) {
            strcat(*dest, onenum);
	 } else {
            /* string would be too long */
            *dest[0] = '\0';
            return FALSE;
	 }
      }
   }
   return (count == numofchars - 1)?TRUE:FALSE; 
} /* ba_b2hex() */

