Back to index

lightning-sunbird  0.9+nobinonly
Defines | Enumerations | Functions | Variables
punycode.c File Reference
#include "punycode.h"
#include <string.h>

Go to the source code of this file.

Defines

#define basic(cp)   ((punycode_uint)(cp) < 0x80)
#define delim(cp)   ((cp) == delimiter)
#define flagged(bcp)   ((punycode_uint)(bcp) - 65 < 26)

Enumerations

enum  {
  base = 36, tmin = 1, tmax = 26, skew = 38,
  damp = 700, initial_bias = 72, initial_n = 0x80, delimiter = 0x2D
}

Functions

static punycode_uint decode_digit (punycode_uint cp)
static char encode_digit (punycode_uint d, int flag)
static char encode_basic (punycode_uint bcp, int flag)
static punycode_uint adapt (punycode_uint delta, punycode_uint numpoints, int firsttime)
enum punycode_status punycode_encode (punycode_uint input_length, const punycode_uint input[], const unsigned char case_flags[], punycode_uint *output_length, char output[])
enum punycode_status punycode_decode (punycode_uint input_length, const char input[], punycode_uint *output_length, punycode_uint output[], unsigned char case_flags[])

Variables

static const punycode_uint maxint = (punycode_uint) -1

Define Documentation

#define basic (   cp)    ((punycode_uint)(cp) < 0x80)

Definition at line 36 of file punycode.c.

#define delim (   cp)    ((cp) == delimiter)

Definition at line 39 of file punycode.c.

#define flagged (   bcp)    ((punycode_uint)(bcp) - 65 < 26)

Definition at line 68 of file punycode.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
base 
tmin 
tmax 
skew 
damp 
initial_bias 
initial_n 
delimiter 

Definition at line 32 of file punycode.c.

     { base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
       initial_bias = 72, initial_n = 0x80, delimiter = 0x2D };

Function Documentation

static punycode_uint adapt ( punycode_uint  delta,
punycode_uint  numpoints,
int  firsttime 
) [static]

Definition at line 90 of file punycode.c.

{
  punycode_uint k;

  delta = firsttime ? delta / damp : delta >> 1;
  /* delta >> 1 is a faster way of doing delta / 2 */
  delta += delta / numpoints;

  for (k = 0;  delta > ((base - tmin) * tmax) / 2;  k += base) {
    delta /= base - tmin;
  }

  return k + (base - tmin + 1) * delta / (delta + skew);
}

Here is the caller graph for this function:

static punycode_uint decode_digit ( punycode_uint  cp) [static]

Definition at line 45 of file punycode.c.

{
  return  cp - 48 < 10 ? cp - 22 :  cp - 65 < 26 ? cp - 65 :
          cp - 97 < 26 ? cp - 97 :  base;
}

Here is the caller graph for this function:

static char encode_basic ( punycode_uint  bcp,
int  flag 
) [static]

Definition at line 76 of file punycode.c.

{
  bcp -= (bcp - 97 < 26) << 5;
  return bcp + ((!flag && (bcp - 65 < 26)) << 5);
}

Here is the caller graph for this function:

static char encode_digit ( punycode_uint  d,
int  flag 
) [static]

Definition at line 57 of file punycode.c.

{
  return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
  /*  0..25 map to ASCII a..z or A..Z */
  /* 26..35 map to ASCII 0..9         */
}

Here is the caller graph for this function:

enum punycode_status punycode_decode ( punycode_uint  input_length,
const char  input[],
punycode_uint output_length,
punycode_uint  output[],
unsigned char  case_flags[] 
)

Definition at line 197 of file punycode.c.

{
  punycode_uint n, out, i, max_out, bias,
                 b, j, in, oldi, w, k, digit, t;

  /* Initialize the state: */

  n = initial_n;
  out = i = 0;
  max_out = *output_length;
  bias = initial_bias;

  /* Handle the basic code points:  Let b be the number of input code */
  /* points before the last delimiter, or 0 if there is none, then    */
  /* copy the first b code points to the output.                      */

  for (b = j = 0;  j < input_length;  ++j) if (delim(input[j])) b = j;
  if (b > max_out) return punycode_big_output;

  for (j = 0;  j < b;  ++j) {
    if (case_flags) case_flags[out] = flagged(input[j]);
    if (!basic(input[j])) return punycode_bad_input;
    output[out++] = input[j];
  }

  /* Main decoding loop:  Start just after the last delimiter if any  */
  /* basic code points were copied; start at the beginning otherwise. */

  for (in = b > 0 ? b + 1 : 0;  in < input_length;  ++out) {

    /* in is the index of the next character to be consumed, and */
    /* out is the number of code points in the output array.     */

    /* Decode a generalized variable-length integer into delta,  */
    /* which gets added to i.  The overflow checking is easier   */
    /* if we increase i as we go, then subtract off its starting */
    /* value at the end to obtain delta.                         */

    for (oldi = i, w = 1, k = base;  ;  k += base) {
      if (in >= input_length) return punycode_bad_input;
      digit = decode_digit(input[in++]);
      if (digit >= base) return punycode_bad_input;
      if (digit > (maxint - i) / w) return punycode_overflow;
      i += digit * w;
      t = k <= bias /* + tmin */ ? tmin :     /* +tmin not needed */
          k >= bias + tmax ? tmax : k - bias;
      if (digit < t) break;
      if (w > maxint / (base - t)) return punycode_overflow;
      w *= (base - t);
    }

    bias = adapt(i - oldi, out + 1, oldi == 0);

    /* i was supposed to wrap around from out+1 to 0,   */
    /* incrementing n each time, so we'll fix that now: */

    if (i / (out + 1) > maxint - n) return punycode_overflow;
    n += i / (out + 1);
    i %= (out + 1);

    /* Insert n at position i of the output: */

    /* not needed for Punycode: */
    /* if (decode_digit(n) <= base) return punycode_invalid_input; */
    if (out >= max_out) return punycode_big_output;

    if (case_flags) {
      memmove(case_flags + i + 1, case_flags + i, out - i);
      /* Case of last character determines uppercase flag: */
      case_flags[i] = flagged(input[in - 1]);
    }

    memmove(output + i + 1, output + i, (out - i) * sizeof *output);
    output[i++] = n;
  }

  *output_length = out;
  return punycode_success;
}

Here is the call graph for this function:

Here is the caller graph for this function:

enum punycode_status punycode_encode ( punycode_uint  input_length,
const punycode_uint  input[],
const unsigned char  case_flags[],
punycode_uint output_length,
char  output[] 
)

Definition at line 108 of file punycode.c.

{
  punycode_uint n, delta, h, b, out, max_out, bias, j, m, q, k, t;

  /* Initialize the state: */

  n = initial_n;
  delta = out = 0;
  max_out = *output_length;
  bias = initial_bias;

  /* Handle the basic code points: */

  for (j = 0;  j < input_length;  ++j) {
    if (basic(input[j])) {
      if (max_out - out < 2) return punycode_big_output;
      output[out++] =
        case_flags ? encode_basic(input[j], case_flags[j]) : (char)input[j];
    }
    /* else if (input[j] < n) return punycode_bad_input; */
    /* (not needed for Punycode with unsigned code points) */
  }

  h = b = out;

  /* h is the number of code points that have been handled, b is the  */
  /* number of basic code points, and out is the number of characters */
  /* that have been output.                                           */

  if (b > 0) output[out++] = delimiter;

  /* Main encoding loop: */

  while (h < input_length) {
    /* All non-basic code points < n have been     */
    /* handled already.  Find the next larger one: */

    for (m = maxint, j = 0;  j < input_length;  ++j) {
      /* if (basic(input[j])) continue; */
      /* (not needed for Punycode) */
      if (input[j] >= n && input[j] < m) m = input[j];
    }

    /* Increase delta enough to advance the decoder's    */
    /* <n,i> state to <m,0>, but guard against overflow: */

    if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow;
    delta += (m - n) * (h + 1);
    n = m;

    for (j = 0;  j < input_length;  ++j) {
      /* Punycode does not need to check whether input[j] is basic: */
      if (input[j] < n /* || basic(input[j]) */ ) {
        if (++delta == 0) return punycode_overflow;
      }

      if (input[j] == n) {
        /* Represent delta as a generalized variable-length integer: */

        for (q = delta, k = base;  ;  k += base) {
          if (out >= max_out) return punycode_big_output;
          t = k <= bias /* + tmin */ ? tmin :     /* +tmin not needed */
              k >= bias + tmax ? tmax : k - bias;
          if (q < t) break;
          output[out++] = encode_digit(t + (q - t) % (base - t), 0);
          q = (q - t) / (base - t);
        }

        output[out++] = encode_digit(q, case_flags && case_flags[j]);
        bias = adapt(delta, h + 1, h == b);
        delta = 0;
        ++h;
      }
    }

    ++delta, ++n;
  }

  *output_length = out;
  return punycode_success;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 85 of file punycode.c.