初始化
This commit is contained in:
560
LFtid1056/lib/libuv-v1.51.0/src/idna.c
Normal file
560
LFtid1056/lib/libuv-v1.51.0/src/idna.c
Normal file
@@ -0,0 +1,560 @@
|
||||
/* Copyright libuv contributors. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Derived from https://github.com/bnoordhuis/punycode
|
||||
* but updated to support IDNA 2008.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
#include "idna.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
|
||||
|
||||
static int32_t uv__wtf8_decode1(const char** input) {
|
||||
uint32_t code_point;
|
||||
uint8_t b1;
|
||||
uint8_t b2;
|
||||
uint8_t b3;
|
||||
uint8_t b4;
|
||||
|
||||
b1 = **input;
|
||||
if (b1 <= 0x7F)
|
||||
return b1; /* ASCII code point */
|
||||
if (b1 < 0xC2)
|
||||
return -1; /* invalid: continuation byte */
|
||||
code_point = b1;
|
||||
|
||||
b2 = *++*input;
|
||||
if ((b2 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b2 & 0x3F);
|
||||
if (b1 <= 0xDF)
|
||||
return 0x7FF & code_point; /* two-byte character */
|
||||
|
||||
b3 = *++*input;
|
||||
if ((b3 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b3 & 0x3F);
|
||||
if (b1 <= 0xEF)
|
||||
return 0xFFFF & code_point; /* three-byte character */
|
||||
|
||||
b4 = *++*input;
|
||||
if ((b4 & 0xC0) != 0x80)
|
||||
return -1; /* invalid: not a continuation byte */
|
||||
code_point = (code_point << 6) | (b4 & 0x3F);
|
||||
if (b1 <= 0xF4) {
|
||||
code_point &= 0x1FFFFF;
|
||||
if (code_point <= 0x10FFFF)
|
||||
return code_point; /* four-byte character */
|
||||
}
|
||||
|
||||
/* code point too large */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static unsigned uv__utf8_decode1_slow(const char** p,
|
||||
const char* pe,
|
||||
unsigned a) {
|
||||
unsigned b;
|
||||
unsigned c;
|
||||
unsigned d;
|
||||
unsigned min;
|
||||
|
||||
if (a > 0xF7)
|
||||
return -1;
|
||||
|
||||
switch (pe - *p) {
|
||||
default:
|
||||
if (a > 0xEF) {
|
||||
min = 0x10000;
|
||||
a = a & 7;
|
||||
b = (unsigned char) *(*p)++;
|
||||
c = (unsigned char) *(*p)++;
|
||||
d = (unsigned char) *(*p)++;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case 2:
|
||||
if (a > 0xDF) {
|
||||
min = 0x800;
|
||||
b = 0x80 | (a & 15);
|
||||
c = (unsigned char) *(*p)++;
|
||||
d = (unsigned char) *(*p)++;
|
||||
a = 0;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case 1:
|
||||
if (a > 0xBF) {
|
||||
min = 0x80;
|
||||
b = 0x80;
|
||||
c = 0x80 | (a & 31);
|
||||
d = (unsigned char) *(*p)++;
|
||||
a = 0;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case 0:
|
||||
return -1; /* Invalid continuation byte. */
|
||||
}
|
||||
|
||||
if (0x80 != (0xC0 & (b ^ c ^ d)))
|
||||
return -1; /* Invalid sequence. */
|
||||
|
||||
b &= 63;
|
||||
c &= 63;
|
||||
d &= 63;
|
||||
a = (a << 18) | (b << 12) | (c << 6) | d;
|
||||
|
||||
if (a < min)
|
||||
return -1; /* Overlong sequence. */
|
||||
|
||||
if (a > 0x10FFFF)
|
||||
return -1; /* Four-byte sequence > U+10FFFF. */
|
||||
|
||||
if (a >= 0xD800 && a <= 0xDFFF)
|
||||
return -1; /* Surrogate pair. */
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||
unsigned a;
|
||||
|
||||
assert(*p < pe);
|
||||
|
||||
a = (unsigned char) *(*p)++;
|
||||
|
||||
if (a < 128)
|
||||
return a; /* ASCII, common case. */
|
||||
|
||||
return uv__utf8_decode1_slow(p, pe, a);
|
||||
}
|
||||
|
||||
|
||||
static int uv__idna_toascii_label(const char* s, const char* se,
|
||||
char** d, char* de) {
|
||||
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
const char* ss;
|
||||
unsigned c;
|
||||
unsigned h;
|
||||
unsigned k;
|
||||
unsigned n;
|
||||
unsigned m;
|
||||
unsigned q;
|
||||
unsigned t;
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
unsigned bias;
|
||||
unsigned delta;
|
||||
unsigned todo;
|
||||
int first;
|
||||
|
||||
h = 0;
|
||||
ss = s;
|
||||
todo = 0;
|
||||
|
||||
/* Note: after this loop we've visited all UTF-8 characters and know
|
||||
* they're legal so we no longer need to check for decode errors.
|
||||
*/
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c < 128)
|
||||
h++;
|
||||
else
|
||||
todo++;
|
||||
}
|
||||
|
||||
/* Only write "xn--" when there are non-ASCII characters. */
|
||||
if (todo > 0) {
|
||||
if (*d < de) *(*d)++ = 'x';
|
||||
if (*d < de) *(*d)++ = 'n';
|
||||
if (*d < de) *(*d)++ = '-';
|
||||
if (*d < de) *(*d)++ = '-';
|
||||
}
|
||||
|
||||
/* Write ASCII characters. */
|
||||
x = 0;
|
||||
s = ss;
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c > 127)
|
||||
continue;
|
||||
|
||||
if (*d < de)
|
||||
*(*d)++ = c;
|
||||
|
||||
if (++x == h)
|
||||
break; /* Visited all ASCII characters. */
|
||||
}
|
||||
|
||||
if (todo == 0)
|
||||
return h;
|
||||
|
||||
/* Only write separator when we've written ASCII characters first. */
|
||||
if (h > 0)
|
||||
if (*d < de)
|
||||
*(*d)++ = '-';
|
||||
|
||||
n = 128;
|
||||
bias = 72;
|
||||
delta = 0;
|
||||
first = 1;
|
||||
|
||||
while (todo > 0) {
|
||||
m = -1;
|
||||
s = ss;
|
||||
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c >= n)
|
||||
if (c < m)
|
||||
m = c;
|
||||
}
|
||||
|
||||
x = m - n;
|
||||
y = h + 1;
|
||||
|
||||
if (x > ~delta / y)
|
||||
return UV_E2BIG; /* Overflow. */
|
||||
|
||||
delta += x * y;
|
||||
n = m;
|
||||
|
||||
s = ss;
|
||||
while (s < se) {
|
||||
c = uv__utf8_decode1(&s, se);
|
||||
assert(c != UINT_MAX);
|
||||
|
||||
if (c < n)
|
||||
if (++delta == 0)
|
||||
return UV_E2BIG; /* Overflow. */
|
||||
|
||||
if (c != n)
|
||||
continue;
|
||||
|
||||
for (k = 36, q = delta; /* empty */; k += 36) {
|
||||
t = 1;
|
||||
|
||||
if (k > bias)
|
||||
t = k - bias;
|
||||
|
||||
if (t > 26)
|
||||
t = 26;
|
||||
|
||||
if (q < t)
|
||||
break;
|
||||
|
||||
/* TODO(bnoordhuis) Since 1 <= t <= 26 and therefore
|
||||
* 10 <= y <= 35, we can optimize the long division
|
||||
* into a table-based reciprocal multiplication.
|
||||
*/
|
||||
x = q - t;
|
||||
y = 36 - t; /* 10 <= y <= 35 since 1 <= t <= 26. */
|
||||
q = x / y;
|
||||
t = t + x % y; /* 1 <= t <= 35 because of y. */
|
||||
|
||||
if (*d < de)
|
||||
*(*d)++ = alphabet[t];
|
||||
}
|
||||
|
||||
if (*d < de)
|
||||
*(*d)++ = alphabet[q];
|
||||
|
||||
delta /= 2;
|
||||
|
||||
if (first) {
|
||||
delta /= 350;
|
||||
first = 0;
|
||||
}
|
||||
|
||||
/* No overflow check is needed because |delta| was just
|
||||
* divided by 2 and |delta+delta >= delta + delta/h|.
|
||||
*/
|
||||
h++;
|
||||
delta += delta / h;
|
||||
|
||||
for (bias = 0; delta > 35 * 26 / 2; bias += 36)
|
||||
delta /= 35;
|
||||
|
||||
bias += 36 * delta / (delta + 38);
|
||||
delta = 0;
|
||||
todo--;
|
||||
}
|
||||
|
||||
delta++;
|
||||
n++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||
const char* si;
|
||||
const char* st;
|
||||
unsigned c;
|
||||
char* ds;
|
||||
int rc;
|
||||
|
||||
if (s == se)
|
||||
return UV_EINVAL;
|
||||
|
||||
ds = d;
|
||||
|
||||
si = s;
|
||||
while (si < se) {
|
||||
st = si;
|
||||
c = uv__utf8_decode1(&si, se);
|
||||
|
||||
if (c == UINT_MAX)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (c != '.')
|
||||
if (c != 0x3002) /* 。 */
|
||||
if (c != 0xFF0E) /* . */
|
||||
if (c != 0xFF61) /* 。 */
|
||||
continue;
|
||||
|
||||
rc = uv__idna_toascii_label(s, st, &d, de);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (d < de)
|
||||
*d++ = '.';
|
||||
|
||||
s = si;
|
||||
}
|
||||
|
||||
if (s < se) {
|
||||
rc = uv__idna_toascii_label(s, se, &d, de);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (d >= de)
|
||||
return UV_EINVAL;
|
||||
|
||||
*d++ = '\0';
|
||||
return d - ds; /* Number of bytes written. */
|
||||
}
|
||||
|
||||
|
||||
ssize_t uv_wtf8_length_as_utf16(const char* source_ptr) {
|
||||
size_t w_target_len = 0;
|
||||
int32_t code_point;
|
||||
|
||||
do {
|
||||
code_point = uv__wtf8_decode1(&source_ptr);
|
||||
if (code_point < 0)
|
||||
return -1;
|
||||
if (code_point > 0xFFFF)
|
||||
w_target_len++;
|
||||
w_target_len++;
|
||||
} while (*source_ptr++);
|
||||
|
||||
return w_target_len;
|
||||
}
|
||||
|
||||
|
||||
void uv_wtf8_to_utf16(const char* source_ptr,
|
||||
uint16_t* w_target,
|
||||
size_t w_target_len) {
|
||||
int32_t code_point;
|
||||
|
||||
do {
|
||||
code_point = uv__wtf8_decode1(&source_ptr);
|
||||
/* uv_wtf8_length_as_utf16 should have been called and checked first. */
|
||||
assert(code_point >= 0);
|
||||
if (code_point > 0xFFFF) {
|
||||
assert(code_point < 0x10FFFF);
|
||||
*w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
|
||||
*w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
|
||||
w_target_len -= 2;
|
||||
} else {
|
||||
*w_target++ = code_point;
|
||||
w_target_len -= 1;
|
||||
}
|
||||
} while (*source_ptr++);
|
||||
|
||||
(void)w_target_len;
|
||||
assert(w_target_len == 0);
|
||||
}
|
||||
|
||||
|
||||
static int32_t uv__get_surrogate_value(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len) {
|
||||
uint16_t u;
|
||||
uint16_t next;
|
||||
|
||||
u = w_source_ptr[0];
|
||||
if (u >= 0xD800 && u <= 0xDBFF && w_source_len != 1) {
|
||||
next = w_source_ptr[1];
|
||||
if (next >= 0xDC00 && next <= 0xDFFF)
|
||||
return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
size_t uv_utf16_length_as_wtf8(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len) {
|
||||
size_t target_len;
|
||||
int32_t code_point;
|
||||
|
||||
target_len = 0;
|
||||
while (w_source_len) {
|
||||
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
|
||||
/* Can be invalid UTF-8 but must be valid WTF-8. */
|
||||
assert(code_point >= 0);
|
||||
if (w_source_len < 0 && code_point == 0)
|
||||
break;
|
||||
if (code_point < 0x80)
|
||||
target_len += 1;
|
||||
else if (code_point < 0x800)
|
||||
target_len += 2;
|
||||
else if (code_point < 0x10000)
|
||||
target_len += 3;
|
||||
else {
|
||||
target_len += 4;
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
|
||||
return target_len;
|
||||
}
|
||||
|
||||
|
||||
int uv_utf16_to_wtf8(const uint16_t* w_source_ptr,
|
||||
ssize_t w_source_len,
|
||||
char** target_ptr,
|
||||
size_t* target_len_ptr) {
|
||||
size_t target_len;
|
||||
char* target;
|
||||
char* target_end;
|
||||
int32_t code_point;
|
||||
|
||||
/* If *target_ptr is provided, then *target_len_ptr must be its length
|
||||
* (excluding space for NUL), otherwise we will compute the target_len_ptr
|
||||
* length and may return a new allocation in *target_ptr if target_ptr is
|
||||
* provided. */
|
||||
if (target_ptr == NULL || *target_ptr == NULL) {
|
||||
target_len = uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
|
||||
if (target_len_ptr != NULL)
|
||||
*target_len_ptr = target_len;
|
||||
} else {
|
||||
target_len = *target_len_ptr;
|
||||
}
|
||||
|
||||
if (target_ptr == NULL)
|
||||
return 0;
|
||||
|
||||
if (*target_ptr == NULL) {
|
||||
target = uv__malloc(target_len + 1);
|
||||
if (target == NULL) {
|
||||
return UV_ENOMEM;
|
||||
}
|
||||
*target_ptr = target;
|
||||
} else {
|
||||
target = *target_ptr;
|
||||
}
|
||||
|
||||
target_end = target + target_len;
|
||||
|
||||
while (target != target_end && w_source_len) {
|
||||
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
|
||||
/* Can be invalid UTF-8 but must be valid WTF-8. */
|
||||
assert(code_point >= 0);
|
||||
if (w_source_len < 0 && code_point == 0) {
|
||||
w_source_len = 0;
|
||||
break;
|
||||
}
|
||||
if (code_point < 0x80) {
|
||||
*target++ = code_point;
|
||||
} else if (code_point < 0x800) {
|
||||
*target++ = 0xC0 | (code_point >> 6);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
} else if (code_point < 0x10000) {
|
||||
*target++ = 0xE0 | (code_point >> 12);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
} else {
|
||||
*target++ = 0xF0 | (code_point >> 18);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 12) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
|
||||
if (target == target_end)
|
||||
break;
|
||||
*target++ = 0x80 | (code_point & 0x3F);
|
||||
/* uv__get_surrogate_value consumed 2 input characters */
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
target_len = target - *target_ptr;
|
||||
w_source_ptr++;
|
||||
if (w_source_len > 0)
|
||||
w_source_len--;
|
||||
}
|
||||
|
||||
if (target != target_end && target_len_ptr != NULL)
|
||||
/* Did not fill all of the provided buffer, so update the target_len_ptr
|
||||
* output with the space used. */
|
||||
*target_len_ptr = target - *target_ptr;
|
||||
|
||||
/* Check if input fit into target exactly. */
|
||||
if (w_source_len < 0 && target == target_end && w_source_ptr[0] == 0)
|
||||
w_source_len = 0;
|
||||
|
||||
*target++ = '\0';
|
||||
|
||||
/* Characters remained after filling the buffer, compute the remaining length now. */
|
||||
if (w_source_len) {
|
||||
if (target_len_ptr != NULL)
|
||||
*target_len_ptr = target_len + uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user