Ejemplo n.º 1
0
/**
 * stringprep_4i:
 * @ucs4: input/output array with string to prepare.
 * @len: on input, length of input array with Unicode code points,
 *          on exit, length of output array with Unicode code points.
 * @maxucs4len: maximum length of input/output array.
 * @flags: stringprep profile flags, or 0.
 * @profile: pointer to stringprep profile to use.
 *
 * Prepare the input UCS-4 string according to the stringprep profile,
 * and write back the result to the input string.
 *
 * The input is not required to be zero terminated (@ucs4[@len] = 0).
 * The output will not be zero terminated unless @ucs4[@len] = 0.
 * Instead, see stringprep_4zi() if your input is zero terminated or
 * if you want the output to be.
 *
 * Since the stringprep operation can expand the string, @maxucs4len
 * indicate how large the buffer holding the string is.  This function
 * will not read or write to code points outside that size.
 *
 * The @flags are one of Stringprep_profile_flags, or 0.
 *
 * The @profile contain the instructions to perform.  Your application
 * can define new profiles, possibly re-using the generic stringprep
 * tables that always will be part of the library, or use one of the
 * currently supported profiles.
 *
 * Return value: Returns %STRINGPREP_OK iff successful, or an error code.
 **/
int
stringprep_4i (uint32_t * ucs4, size_t * len, size_t maxucs4len,
	       Stringprep_profile_flags flags,
	       const Stringprep_profile * profile)
{
  size_t i, j;
  ssize_t k;
  size_t ucs4len = *len;
  int rc;

  for (i = 0; profile[i].operation; i++)
    {
      switch (profile[i].operation)
	{
	case STRINGPREP_NFKC:
	  {
	    uint32_t *q = 0;

	    if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
	      break;

	    if (flags & STRINGPREP_NO_NFKC && !profile[i].flags)
	      /* Profile requires NFKC, but callee asked for no NFKC. */
	      return STRINGPREP_FLAG_ERROR;

	    q = stringprep_ucs4_nfkc_normalize (ucs4, ucs4len);
	    if (!q)
	      return STRINGPREP_NFKC_FAILED;

	    for (ucs4len = 0; q[ucs4len]; ucs4len++)
	      ;

	    if (ucs4len >= maxucs4len)
	      {
		free (q);
		return STRINGPREP_TOO_SMALL_BUFFER;
	      }

	    memcpy (ucs4, q, ucs4len * sizeof (ucs4[0]));

	    free (q);
	  }
	  break;

	case STRINGPREP_PROHIBIT_TABLE:
	  k = stringprep_find_string_in_table (ucs4, ucs4len,
					       NULL, profile[i].table);
	  if (k != -1)
	    return STRINGPREP_CONTAINS_PROHIBITED;
	  break;

	case STRINGPREP_UNASSIGNED_TABLE:
	  if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
	    break;
	  if (flags & STRINGPREP_NO_UNASSIGNED)
	    {
	      k = stringprep_find_string_in_table
		(ucs4, ucs4len, NULL, profile[i].table);
	      if (k != -1)
		return STRINGPREP_CONTAINS_UNASSIGNED;
	    }
	  break;

	case STRINGPREP_MAP_TABLE:
	  if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
	    break;
	  rc = stringprep_apply_table_to_string
	    (ucs4, &ucs4len, maxucs4len, profile[i].table);
	  if (rc != STRINGPREP_OK)
	    return rc;
	  break;

	case STRINGPREP_BIDI_PROHIBIT_TABLE:
	case STRINGPREP_BIDI_RAL_TABLE:
	case STRINGPREP_BIDI_L_TABLE:
	  break;

	case STRINGPREP_BIDI:
	  {
	    int done_prohibited = 0;
	    int done_ral = 0;
	    int done_l = 0;
	    int contains_ral = -1;
	    int contains_l = -1;

	    for (j = 0; profile[j].operation; j++)
	      if (profile[j].operation == STRINGPREP_BIDI_PROHIBIT_TABLE)
		{
		  done_prohibited = 1;
		  k = stringprep_find_string_in_table (ucs4, ucs4len,
						       NULL,
						       profile[j].table);
		  if (k != -1)
		    return STRINGPREP_BIDI_CONTAINS_PROHIBITED;
		}
	      else if (profile[j].operation == STRINGPREP_BIDI_RAL_TABLE)
		{
		  done_ral = 1;
		  if (stringprep_find_string_in_table
		      (ucs4, ucs4len, NULL, profile[j].table) != -1)
		    contains_ral = j;
		}
	      else if (profile[j].operation == STRINGPREP_BIDI_L_TABLE)
		{
		  done_l = 1;
		  if (stringprep_find_string_in_table
		      (ucs4, ucs4len, NULL, profile[j].table) != -1)
		    contains_l = j;
		}

	    if (!done_prohibited || !done_ral || !done_l)
	      return STRINGPREP_PROFILE_ERROR;

	    if (contains_ral != -1 && contains_l != -1)
	      return STRINGPREP_BIDI_BOTH_L_AND_RAL;

	    if (contains_ral != -1)
	      {
		if (!(stringprep_find_character_in_table
		      (ucs4[0], profile[contains_ral].table) != -1 &&
		      stringprep_find_character_in_table
		      (ucs4[ucs4len - 1], profile[contains_ral].table) != -1))
		  return STRINGPREP_BIDI_LEADTRAIL_NOT_RAL;
	      }
	  }
	  break;

	default:
	  return STRINGPREP_PROFILE_ERROR;
	  break;
	}
    }

  *len = ucs4len;

  return STRINGPREP_OK;
}
Ejemplo n.º 2
0
void
doit (void)
{
  size_t i;
  int rc;

  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
    {
      if (debug)
	{
	  uint32_t *p, *q;

	  printf ("PR29 entry %ld: %s\n", i, tv[i].name);

	  printf ("in:\n");
	  ucs4print (tv[i].in, tv[i].inlen);

	  printf ("nfkc:\n");
	  p = stringprep_ucs4_nfkc_normalize (tv[i].in, tv[i].inlen);
	  ucs4print (p, -1);

	  printf ("second nfkc:\n");
	  q = stringprep_ucs4_nfkc_normalize (p, -1);
	  ucs4print (q, -1);

	  free (p);
	  free (q);
	}

      rc = pr29_4 (tv[i].in, tv[i].inlen);
      if (rc != tv[i].rc)
	{
	  fail ("PR29 entry %ld failed (expected %d): %d\n", i, tv[i].rc, rc);
	  if (debug)
	    printf ("FATAL\n");
	  continue;
	}

      rc = pr29_4z (tv[i].in);
      if (rc != tv[i].rc)
	{
	  fail ("PR29 entry %ld failed (expected %d): %d\n", i, tv[i].rc, rc);
	  if (debug)
	    printf ("FATAL\n");
	  continue;
	}

      {
	char *p;
	size_t items_read, items_written;

	p = stringprep_ucs4_to_utf8 (tv[i].in, (ssize_t) tv[i].inlen,
				     &items_read, &items_written);
	if (p == NULL)
	  fail ("FAIL: stringprep_ucs4_to_utf8(tv[%ld]) == NULL\n", i);
	if (debug)
	  hexprint (p, strlen (p));

	rc = pr29_8z (p);
	free (p);
	if (rc != tv[i].rc)
	  {
	    fail ("PR29 entry %ld failed (expected %d): %d\n",
		  i, tv[i].rc, rc);
	    if (debug)
	      printf ("FATAL\n");
	    continue;
	  }
      }

      if (debug)
	{
	  if (tv[i].rc != PR29_SUCCESS)
	    printf ("EXPECTED FAIL\n");
	  else
	    printf ("OK\n");
	}
    }
}