Back to index

glibc  2.9
Defines | Functions
stringprep.c File Reference
#include <stdlib.h>
#include <string.h>
#include "stringprep.h"

Go to the source code of this file.

Defines

#define INVERTED(x)   ((x) & ((~0UL) >> 1))
#define UNAPPLICAPLEFLAGS(flags, profileflags)

Functions

static ssize_t stringprep_find_character_in_table (uint32_t ucs4, const Stringprep_table_element *table)
static ssize_t stringprep_find_string_in_table (uint32_t *ucs4, size_t ucs4len, size_t *tablepos, const Stringprep_table_element *table)
static int stringprep_apply_table_to_string (uint32_t *ucs4, size_t *ucs4len, size_t maxucs4len, const Stringprep_table_element *table)
int stringprep_4i (uint32_t *ucs4, size_t *len, size_t maxucs4len, Stringprep_profile_flags flags, const Stringprep_profile *profile)
 stringprep_4i: : input/output array with string to prepare.
static int stringprep_4zi_1 (uint32_t *ucs4, size_t ucs4len, size_t maxucs4len, Stringprep_profile_flags flags, const Stringprep_profile *profile)
int stringprep_4zi (uint32_t *ucs4, size_t maxucs4len, Stringprep_profile_flags flags, const Stringprep_profile *profile)
 stringprep_4zi: : input/output array with zero terminated string to prepare.
int stringprep (char *in, size_t maxlen, Stringprep_profile_flags flags, const Stringprep_profile *profile)
 stringprep: : input/ouput array with string to prepare.
int stringprep_profile (const char *in, char **out, const char *profile, Stringprep_profile_flags flags)
 stringprep_profile: : input array with UTF-8 string to prepare.

Define Documentation

#define INVERTED (   x)    ((x) & ((~0UL) >> 1))

Definition at line 101 of file stringprep.c.

#define UNAPPLICAPLEFLAGS (   flags,
  profileflags 
)
Value:
((!INVERTED(profileflags) && !(profileflags & flags) && profileflags) || \
   ( INVERTED(profileflags) && (profileflags & flags)))

Definition at line 102 of file stringprep.c.


Function Documentation

int stringprep ( char *  in,
size_t  maxlen,
Stringprep_profile_flags  flags,
const Stringprep_profile *  profile 
)

stringprep: : input/ouput array with string to prepare.

: maximum length of input/output array. : stringprep profile flags, or 0. : pointer to stringprep profile to use.

Prepare the input zero terminated UTF-8 string according to the stringprep profile, and write back the result to the input string.

Note that you must convert strings entered in the systems locale into UTF-8 before using this function, see stringprep_locale_to_utf8().

Since the stringprep operation can expand the string, indicate how large the buffer holding the string is. This function will not read or write to characters outside that size.

The are one of Stringprep_profile_flags, or 0.

The 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.

Definition at line 357 of file stringprep.c.

{
  int rc;
  char *utf8 = NULL;
  uint32_t *ucs4 = NULL;
  size_t ucs4len, maxucs4len, adducs4len = 50;

  do
    {
      free (ucs4);
      ucs4 = stringprep_utf8_to_ucs4 (in, -1, &ucs4len);
      maxucs4len = ucs4len + adducs4len;
      uint32_t *newp = realloc (ucs4, maxucs4len * sizeof (uint32_t));
      if (!newp)
       {
         free (ucs4);
         return STRINGPREP_MALLOC_ERROR;
       }
      ucs4 = newp;

      rc = stringprep_4i (ucs4, &ucs4len, maxucs4len, flags, profile);
      adducs4len += 50;
    }
  while (rc == STRINGPREP_TOO_SMALL_BUFFER);
  if (rc != STRINGPREP_OK)
    {
      free (ucs4);
      return rc;
    }

  utf8 = stringprep_ucs4_to_utf8 (ucs4, ucs4len, 0, 0);
  free (ucs4);
  if (!utf8)
    return STRINGPREP_MALLOC_ERROR;

  if (strlen (utf8) >= maxlen)
    {
      free (utf8);
      return STRINGPREP_TOO_SMALL_BUFFER;
    }

  strcpy (in, utf8);        /* flawfinder: ignore */

  free (utf8);

  return STRINGPREP_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int stringprep_4i ( uint32_t ucs4,
size_t len,
size_t  maxucs4len,
Stringprep_profile_flags  flags,
const Stringprep_profile *  profile 
)

stringprep_4i: : input/output array with string to prepare.

: on input, length of input array with Unicode code points, on exit, length of output array with Unicode code points. : maximum length of input/output array. : stringprep profile flags, or 0. : 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 ([] = 0). The output will not be zero terminated unless [] = 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, indicate how large the buffer holding the string is. This function will not read or write to code points outside that size.

The are one of Stringprep_profile_flags, or 0.

The 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.

Definition at line 137 of file stringprep.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int stringprep_4zi ( uint32_t ucs4,
size_t  maxucs4len,
Stringprep_profile_flags  flags,
const Stringprep_profile *  profile 
)

stringprep_4zi: : input/output array with zero terminated string to prepare.

: maximum length of input/output array. : stringprep profile flags, or 0. : pointer to stringprep profile to use.

Prepare the input zero terminated UCS-4 string according to the stringprep profile, and write back the result to the input string.

Since the stringprep operation can expand the string, indicate how large the buffer holding the string is. This function will not read or write to code points outside that size.

The are one of Stringprep_profile_flags, or 0.

The 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.

Definition at line 317 of file stringprep.c.

{
  size_t ucs4len;

  for (ucs4len = 0; ucs4len < maxucs4len && ucs4[ucs4len] != 0; ucs4len++)
    ;

  return stringprep_4zi_1 (ucs4, ucs4len, maxucs4len, flags, profile);
}

Here is the call graph for this function:

static int stringprep_4zi_1 ( uint32_t ucs4,
size_t  ucs4len,
size_t  maxucs4len,
Stringprep_profile_flags  flags,
const Stringprep_profile *  profile 
) [static]

Definition at line 275 of file stringprep.c.

{
  int rc;

  rc = stringprep_4i (ucs4, &ucs4len, maxucs4len, flags, profile);
  if (rc != STRINGPREP_OK)
    return rc;

  if (ucs4len >= maxucs4len)
    return STRINGPREP_TOO_SMALL_BUFFER;

  ucs4[ucs4len] = 0;

  return STRINGPREP_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int stringprep_apply_table_to_string ( uint32_t ucs4,
size_t ucs4len,
size_t  maxucs4len,
const Stringprep_table_element table 
) [static]

Definition at line 74 of file stringprep.c.

{
  ssize_t pos;
  size_t i, maplen;

  while ((pos = stringprep_find_string_in_table (ucs4, *ucs4len,
                                           &i, table)) != -1)
    {
      for (maplen = STRINGPREP_MAX_MAP_CHARS;
          maplen > 0 && table[i].map[maplen - 1] == 0; maplen--)
       ;

      if (*ucs4len - 1 + maplen >= maxucs4len)
       return STRINGPREP_TOO_SMALL_BUFFER;

      memmove (&ucs4[pos + maplen], &ucs4[pos + 1],
              sizeof (uint32_t) * (*ucs4len - pos - 1));
      memcpy (&ucs4[pos], table[i].map, sizeof (uint32_t) * maplen);
      *ucs4len = *ucs4len - 1 + maplen;
    }

  return STRINGPREP_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 32 of file stringprep.c.

{
  ssize_t i;

  /* This is where typical uses of Libidn spends very close to all CPU
     time and causes most cache misses.  One could easily do a binary
     search instead.  Before rewriting this, I want hard evidence this
     slowness is at all relevant in typical applications.  (I don't
     dispute optimization may improve matters significantly, I'm
     mostly interested in having someone give real-world benchmark on
     the impact of libidn.) */

  for (i = 0; table[i].start || table[i].end; i++)
    if (ucs4 >= table[i].start &&
       ucs4 <= (table[i].end ? table[i].end : table[i].start))
      return i;

  return -1;
}

Here is the caller graph for this function:

static ssize_t stringprep_find_string_in_table ( uint32_t ucs4,
size_t  ucs4len,
size_t tablepos,
const Stringprep_table_element table 
) [static]

Definition at line 54 of file stringprep.c.

{
  size_t j;
  ssize_t pos;

  for (j = 0; j < ucs4len; j++)
    if ((pos = stringprep_find_character_in_table (ucs4[j], table)) != -1)
      {
       if (tablepos)
         *tablepos = pos;
       return j;
      }

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int stringprep_profile ( const char *  in,
char **  out,
const char *  profile,
Stringprep_profile_flags  flags 
)

stringprep_profile: : input array with UTF-8 string to prepare.

: output variable with pointer to newly allocate string. : name of stringprep profile to use. : stringprep profile flags, or 0.

Prepare the input zero terminated UTF-8 string according to the stringprep profile, and return the result in a newly allocated variable.

Note that you must convert strings entered in the systems locale into UTF-8 before using this function, see stringprep_locale_to_utf8().

The output variable must be deallocated by the caller.

The are one of Stringprep_profile_flags, or 0.

The specifies the name of the stringprep profile to use. It must be one of the internally supported stringprep profiles.

Return value: Returns STRINGPREP_OK iff successful, or an error code.

Definition at line 433 of file stringprep.c.

{
  const Stringprep_profiles *p;
  char *str = NULL;
  size_t len = strlen (in) + 1;
  int rc;

  for (p = &stringprep_profiles[0]; p->name; p++)
    if (strcmp (p->name, profile) == 0)
      break;

  if (!p || !p->name || !p->tables)
    return STRINGPREP_UNKNOWN_PROFILE;

  do
    {
      free (str);
      str = (char *) malloc (len);
      if (str == NULL)
       return STRINGPREP_MALLOC_ERROR;

      strcpy (str, in);

      rc = stringprep (str, len, flags, p->tables);
      len += 50;
    }
  while (rc == STRINGPREP_TOO_SMALL_BUFFER);

  if (rc == STRINGPREP_OK)
    *out = str;
  else
    free (str);

  return rc;
}

Here is the call graph for this function: