ippSetStringfv(ipp_t           *ipp,	/* I  - IPP message */
               ipp_attribute_t **attr,	/* IO - IPP attribute */
               int             element,	/* I  - Value number (0-based) */
	       const char      *format,	/* I  - Printf-style format string */
	       va_list         ap)	/* I  - Pointer to additional arguments */
{
  ipp_tag_t	value_tag;		/* Value tag */
  char		buffer[IPP_MAX_TEXT + 4];
					/* Formatted text string */
  ssize_t	bytes,			/* Length of formatted value */
		max_bytes;		/* Maximum number of bytes for value */


 /*
  * Range check input...
  */

  if (attr && *attr)
    value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK;
  else
    value_tag = IPP_TAG_ZERO;

  if (!ipp || !attr || !*attr || (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && value_tag != IPP_TAG_NAMELANG && value_tag != IPP_TAG_NOVALUE && value_tag != IPP_TAG_UNKNOWN) || value_tag > IPP_TAG_MIMETYPE || !format)
    return (0);

 /*
  * Format the string...
  */

  if (!strcmp(format, "%s"))
  {
   /*
    * Optimize the simple case...
    */

    const char *s = va_arg(ap, char *);

    if (!s)
      s = "(null)";

    bytes = (ssize_t)strlen(s);
    strlcpy(buffer, s, sizeof(buffer));
  }
  else
  {
   /*
    * Do a full formatting of the message...
    */

    if ((bytes = vsnprintf(buffer, sizeof(buffer), format, ap)) < 0)
      return (0);
  }

 /*
  * Limit the length of the string...
  */

  switch (value_tag)
  {
    default :
    case IPP_TAG_TEXT :
    case IPP_TAG_TEXTLANG :
        max_bytes = IPP_MAX_TEXT;
        break;

    case IPP_TAG_NAME :
    case IPP_TAG_NAMELANG :
        max_bytes = IPP_MAX_NAME;
        break;

    case IPP_TAG_CHARSET :
        max_bytes = IPP_MAX_CHARSET;
        break;

    case IPP_TAG_NOVALUE :
    case IPP_TAG_UNKNOWN :
    case IPP_TAG_KEYWORD :
        max_bytes = IPP_MAX_KEYWORD;
        break;

    case IPP_TAG_LANGUAGE :
        max_bytes = IPP_MAX_LANGUAGE;
        break;

    case IPP_TAG_MIMETYPE :
        max_bytes = IPP_MAX_MIMETYPE;
        break;

    case IPP_TAG_URI :
        max_bytes = IPP_MAX_URI;
        break;

    case IPP_TAG_URISCHEME :
        max_bytes = IPP_MAX_URISCHEME;
        break;
  }

  if (bytes >= max_bytes)
  {
    char	*bufmax,		/* Buffer at max_bytes */
		*bufptr;		/* Pointer into buffer */

    bufptr = buffer + strlen(buffer) - 1;
    bufmax = buffer + max_bytes - 1;

    while (bufptr > bufmax)
    {
      if (*bufptr & 0x80)
      {
        while ((*bufptr & 0xc0) == 0x80 && bufptr > buffer)
          bufptr --;
      }

      bufptr --;
    }

    *bufptr = '\0';
  }

 /*
  * Set the formatted string and return...
  */

  return (ippSetString(ipp, attr, element, buffer));
}
ippSetStringfv(ipp_t           *ipp,	 
               ipp_attribute_t **attr,	 
               int             element,	 
	       const char      *format,	 
	       va_list         ap)	 
{
  ipp_tag_t	value_tag;		 
  char		buffer[IPP_MAX_TEXT + 4];
					 
  ssize_t	bytes,			 
		max_bytes;		 


  

  if (attr && *attr)
    value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK;
  else
    value_tag = IPP_TAG_ZERO;

  if (!ipp || !attr || !*attr || (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && value_tag != IPP_TAG_NAMELANG && value_tag != IPP_TAG_NOVALUE && value_tag != IPP_TAG_UNKNOWN) || value_tag > IPP_TAG_MIMETYPE || !format)
    return (0);

  

  if (!strcmp(format, "%s"))
  {
    

    const char *s = va_arg(ap, char *);

    if (!s)
      s = "(null)";

    bytes = (ssize_t)strlen(s);
    strlcpy(buffer, s, sizeof(buffer));
  }
  else
  {
    

    if ((bytes = vsnprintf(buffer, sizeof(buffer), format, ap)) < 0)
      return (0);
  }

  

  switch (value_tag)
  {
    default :
    case IPP_TAG_TEXT :
    case IPP_TAG_TEXTLANG :
        max_bytes = IPP_MAX_TEXT;
        break;

    case IPP_TAG_NAME :
    case IPP_TAG_NAMELANG :
        max_bytes = IPP_MAX_NAME;
        break;

    case IPP_TAG_CHARSET :
        max_bytes = IPP_MAX_CHARSET;
        break;

    case IPP_TAG_NOVALUE :
    case IPP_TAG_UNKNOWN :
    case IPP_TAG_KEYWORD :
        max_bytes = IPP_MAX_KEYWORD;
        break;

    case IPP_TAG_LANGUAGE :
        max_bytes = IPP_MAX_LANGUAGE;
        break;

    case IPP_TAG_MIMETYPE :
        max_bytes = IPP_MAX_MIMETYPE;
        break;

    case IPP_TAG_URI :
        max_bytes = IPP_MAX_URI;
        break;

    case IPP_TAG_URISCHEME :
        max_bytes = IPP_MAX_URISCHEME;
        break;
  }

  if (bytes >= max_bytes)
  {
    char	*bufmax,		 
		*bufptr;		 

    bufptr = buffer + strlen(buffer) - 1;
    bufmax = buffer + max_bytes - 1;

    while (bufptr > bufmax)
    {
      if (*bufptr & 0x80)
      {
        while ((*bufptr & 0xc0) == 0x80 && bufptr > buffer)
          bufptr --;
      }

      bufptr --;
    }

    *bufptr = '\0';
  }

  

  return (ippSetString(ipp, attr, element, buffer));
}