ippCopyAttribute(
    ipp_t           *dst,		/* I - Destination IPP message */
    ipp_attribute_t *srcattr,		/* I - Attribute to copy */
    int             quickcopy)		/* I - 1 for a referenced copy, 0 for normal */
{
  int			i;		/* Looping var */
  ipp_tag_t		srctag;		/* Source value tag */
  ipp_attribute_t	*dstattr;	/* Destination attribute */
  _ipp_value_t		*srcval,	/* Source value */
			*dstval;	/* Destination value */


  DEBUG_printf(("ippCopyAttribute(dst=%p, srcattr=%p, quickcopy=%d)", (void *)dst, (void *)srcattr, quickcopy));

 /*
  * Range check input...
  */

  if (!dst || !srcattr)
    return (NULL);

 /*
  * Copy it...
  */

  quickcopy = (quickcopy && (srcattr->value_tag & IPP_TAG_CUPS_CONST)) ? IPP_TAG_CUPS_CONST : 0;
  srctag    = srcattr->value_tag & IPP_TAG_CUPS_MASK;

  switch (srctag)
  {
    case IPP_TAG_ZERO :
        dstattr = ippAddSeparator(dst);
	break;

    case IPP_TAG_UNSUPPORTED_VALUE :
    case IPP_TAG_DEFAULT :
    case IPP_TAG_UNKNOWN :
    case IPP_TAG_NOVALUE :
    case IPP_TAG_NOTSETTABLE :
    case IPP_TAG_DELETEATTR :
    case IPP_TAG_ADMINDEFINE :
        dstattr = ippAddOutOfBand(dst, srcattr->group_tag, srctag, srcattr->name);
        break;

    case IPP_TAG_INTEGER :
    case IPP_TAG_ENUM :
    case IPP_TAG_BOOLEAN :
    case IPP_TAG_DATE :
    case IPP_TAG_RESOLUTION :
    case IPP_TAG_RANGE :
        if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) != NULL)
	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
        break;

    case IPP_TAG_TEXT :
    case IPP_TAG_NAME :
    case IPP_TAG_RESERVED_STRING :
    case IPP_TAG_KEYWORD :
    case IPP_TAG_URI :
    case IPP_TAG_URISCHEME :
    case IPP_TAG_CHARSET :
    case IPP_TAG_LANGUAGE :
    case IPP_TAG_MIMETYPE :
        if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL)
          break;

        if (quickcopy)
	{
	 /*
	  * Can safely quick-copy these string values...
	  */

	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
        }
	else
	{
	 /*
	  * Otherwise do a normal reference counted copy...
	  */

	  for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
	    dstval->string.text = _cupsStrAlloc(srcval->string.text);
	}
        break;

    case IPP_TAG_TEXTLANG :
    case IPP_TAG_NAMELANG :
        if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL)
          break;

        if (quickcopy)
	{
	 /*
	  * Can safely quick-copy these string values...
	  */

	  memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t));
        }
	else if (srcattr->value_tag & IPP_TAG_CUPS_CONST)
	{
	 /*
	  * Otherwise do a normal reference counted copy...
	  */

	  for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
	  {
	    if (srcval == srcattr->values)
              dstval->string.language = _cupsStrAlloc(srcval->string.language);
	    else
              dstval->string.language = dstattr->values[0].string.language;

	    dstval->string.text = _cupsStrAlloc(srcval->string.text);
          }
        }
        break;

    case IPP_TAG_BEGIN_COLLECTION :
        if ((dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name, srcattr->num_values, NULL)) == NULL)
          break;

        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
	{
	  dstval->collection = srcval->collection;
	  srcval->collection->use ++;
	}
        break;

    case IPP_TAG_STRING :
    default :
        if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) == NULL)
          break;

        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++)
	{
	  dstval->unknown.length = srcval->unknown.length;

	  if (dstval->unknown.length > 0)
	  {
	    if ((dstval->unknown.data = malloc((size_t)dstval->unknown.length)) == NULL)
	      dstval->unknown.length = 0;
	    else
	      memcpy(dstval->unknown.data, srcval->unknown.data, (size_t)dstval->unknown.length);
	  }
	}
        break; /* anti-compiler-warning-code */
  }

  return (dstattr);
}