/*
** mg_mask.c for  in 
** 
** Made by vianney rancurel
** Login   <vianney@epita.fr>
** 
** Started on  Wed Aug 25 12:14:40 1999 vianney rancurel
** Last update Thu Oct 28 20:15:54 1999 
*/
#include "mg.h"

/* gets the t_mask_def structure associated to the left string member.
   It walk the array until a str member is NULL.
   Returns a mask_def structure or NULL if not found */
t_mask_def		*mask_get_def_from_str(defs,str)
t_mask_def		*defs;
char			*str;
{
  while (defs->str)
    {
      if (!strcmp(defs->str,str))
	return (defs);
      defs++;
    }
  return (NULL);
}

/* gets the t_mask_def structure associated to right mask member.
   It walk the array until a str member is NULL.
   Returns a mask_def structure or NULL if not found */
t_mask_def		*mask_get_def_from_mask(defs,mask)
t_mask_def		*defs;
t_mask			mask;
{
  while (defs->str)
    {
      if (mask == defs->mask)
	return (defs);
      defs++;
    }
  return (NULL);
}

/* fills a mask according to a vec_str of tokens.
   Vec_str can be obtained via a vec_str_split(3) call.
   Note that t_mask covers the machine long size.
   If the token isn't found, the function tries to convert the string
   to an unsigned long mask value using strtoul(3): 0nnnnnn will be
   considered as octal, 0[xX]nnnnn will be considered as hexadecimal,
   mnnnnn (m != 0) as a decimal.
   Returns 0 in all cases. might one day return an error */
t_status		mask_from_vec_str(defs,vec_str,mask)
t_mask_def		*defs;		/* NULL left member terminated array*/
t_vec			*vec_str;	/* vector of tokens */
t_mask			*mask;		/* Mask returned */
{
  if (VEC_COUNT(vec_str) > 0)
    {
      VEC_FOR(vec_str,char *str)
	{
	  t_mask_def	*mask_def;
	  
	  if (mask_def = mask_get_def_from_str(defs,str))
	    (*mask) |= mask_def->mask;
	  else
	    {
	      t_mask	value;
	      
	      if (str[0] == '0')
		{
		  if (str[1] == 'x' || str[1] == 'X')
		    value = strtoul(str,NULL,16);
		  else
		    value = strtoul(str,NULL,8);
		}
	      else
		value = strtoul(str,NULL,10);
	      (*mask) |= value;
	    }
	}
      VEC_ENDFOR;
    }
  return (0);
}

/* converts-and-catenates a mask to a bridled string.
   Residue is exprimed in using residue_base.
   Returns 0 if OK, might return ERR_BO */
t_status		mask_to_str(defs,mask,sep,residue_base,str,max_len)
t_mask_def		*defs;		/* NULL left member terminated array*/
t_mask			mask;		
int			residue_base;	/* See ulong_to_str(3) */
char			*sep;		/* Separator, e.g. "|" */
char			*str;		/* Destination string */
int			max_len;	/* Maximum length allowed */
{
  t_boolean		found;
  t_status		status;
  
  found = FALSE;
  while (defs->str)
    {
      if (((mask & defs->mask) == defs->mask) && (defs->mask != 0))
	{
	  mask &= ~(defs->mask);
	  if (found)
	    {
	      if ((status = str_cat_str(str,
					max_len,
					sep)) != 0)
		return (status);
	      found = FALSE;
	    }
	  if ((status = str_cat_str(str,
				    max_len,
				    defs->str)) != 0)
	    return (status);
	  found = TRUE;
	}
      defs++;
    }
  if (mask == 0)
    return (0);
  else
    {
      if (found)
	if ((status = str_cat_str(str,
				  max_len,
				  sep)) != 0)
	  return (status);
      return (ulong_to_str(mask,
			   residue_base,
			   str,
			   max_len));
    }
}
